pax_global_header00006660000000000000000000000064137370656170014531gustar00rootroot0000000000000052 comment=4e9daf282a12ecba19fe12f296a31315f6a6bd2d vcu-omx-il-xilinx-v2020.2/000077500000000000000000000000001373706561700153155ustar00rootroot00000000000000vcu-omx-il-xilinx-v2020.2/3rd_party/000077500000000000000000000000001373706561700172245ustar00rootroot00000000000000vcu-omx-il-xilinx-v2020.2/3rd_party/date.h000066400000000000000000007273631373706561700203340ustar00rootroot00000000000000#ifndef DATE_H #define DATE_H // The MIT License (MIT) // // Copyright (c) 2015, 2016, 2017 Howard Hinnant // Copyright (c) 2016 Adrian Colomitchi // Copyright (c) 2017 Florian Dang // Copyright (c) 2017 Paul Thompson // Copyright (c) 2018 Tomasz KamiƄski // // 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 and this permission notice 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. // // Our apologies. When the previous paragraph was written, lowercase had not yet // been invented (that would involve another several millennia of evolution). // We did not mean to shout. #ifndef HAS_STRING_VIEW # if __cplusplus >= 201703 # define HAS_STRING_VIEW 1 # else # define HAS_STRING_VIEW 0 # endif #endif // HAS_STRING_VIEW #include #include #include #include #include #if !(__cplusplus >= 201402) # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAS_STRING_VIEW # include #endif #include #include #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpedantic" # if __GNUC__ < 5 // GCC 4.9 Bug 61489 Wrong warning with -Wmissing-field-initializers # pragma GCC diagnostic ignored "-Wmissing-field-initializers" # endif #endif namespace date { //---------------+ // Configuration | //---------------+ #ifndef ONLY_C_LOCALE # define ONLY_C_LOCALE 0 #endif #if defined(_MSC_VER) && (!defined(__clang__) || (_MSC_VER < 1910)) // MSVC # define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING # if _MSC_VER < 1910 // before VS2017 # define CONSTDATA const # define CONSTCD11 # define CONSTCD14 # define NOEXCEPT _NOEXCEPT # else // VS2017 and later # define CONSTDATA constexpr const # define CONSTCD11 constexpr # define CONSTCD14 constexpr # define NOEXCEPT noexcept # endif #elif defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x5150 // Oracle Developer Studio 12.6 and earlier # define CONSTDATA constexpr const # define CONSTCD11 constexpr # define CONSTCD14 # define NOEXCEPT noexcept #elif __cplusplus >= 201402 // C++14 # define CONSTDATA constexpr const # define CONSTCD11 constexpr # define CONSTCD14 constexpr # define NOEXCEPT noexcept #else // C++11 # define CONSTDATA constexpr const # define CONSTCD11 constexpr # define CONSTCD14 # define NOEXCEPT noexcept #endif #ifndef HAS_VOID_T # if __cplusplus >= 201703 # define HAS_VOID_T 1 # else # define HAS_VOID_T 0 # endif #endif // HAS_VOID_T // Protect from Oracle sun macro #ifdef sun # undef sun #endif //-----------+ // Interface | //-----------+ // durations using days = std::chrono::duration , std::chrono::hours::period>>; using weeks = std::chrono::duration , days::period>>; using years = std::chrono::duration , days::period>>; using months = std::chrono::duration >>; // time_point template using sys_time = std::chrono::time_point; using sys_days = sys_time; using sys_seconds = sys_time; struct local_t {}; template using local_time = std::chrono::time_point; using local_seconds = local_time; using local_days = local_time; // types struct last_spec { explicit last_spec() = default; }; class day; class month; class year; class weekday; class weekday_indexed; class weekday_last; class month_day; class month_day_last; class month_weekday; class month_weekday_last; class year_month; class year_month_day; class year_month_day_last; class year_month_weekday; class year_month_weekday_last; // date composition operators CONSTCD11 year_month operator/(const year& y, const month& m) NOEXCEPT; CONSTCD11 year_month operator/(const year& y, int m) NOEXCEPT; CONSTCD11 month_day operator/(const day& d, const month& m) NOEXCEPT; CONSTCD11 month_day operator/(const day& d, int m) NOEXCEPT; CONSTCD11 month_day operator/(const month& m, const day& d) NOEXCEPT; CONSTCD11 month_day operator/(const month& m, int d) NOEXCEPT; CONSTCD11 month_day operator/(int m, const day& d) NOEXCEPT; CONSTCD11 month_day_last operator/(const month& m, last_spec) NOEXCEPT; CONSTCD11 month_day_last operator/(int m, last_spec) NOEXCEPT; CONSTCD11 month_day_last operator/(last_spec, const month& m) NOEXCEPT; CONSTCD11 month_day_last operator/(last_spec, int m) NOEXCEPT; CONSTCD11 month_weekday operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT; CONSTCD11 month_weekday operator/(int m, const weekday_indexed& wdi) NOEXCEPT; CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT; CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, int m) NOEXCEPT; CONSTCD11 month_weekday_last operator/(const month& m, const weekday_last& wdl) NOEXCEPT; CONSTCD11 month_weekday_last operator/(int m, const weekday_last& wdl) NOEXCEPT; CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, const month& m) NOEXCEPT; CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, int m) NOEXCEPT; CONSTCD11 year_month_day operator/(const year_month& ym, const day& d) NOEXCEPT; CONSTCD11 year_month_day operator/(const year_month& ym, int d) NOEXCEPT; CONSTCD11 year_month_day operator/(const year& y, const month_day& md) NOEXCEPT; CONSTCD11 year_month_day operator/(int y, const month_day& md) NOEXCEPT; CONSTCD11 year_month_day operator/(const month_day& md, const year& y) NOEXCEPT; CONSTCD11 year_month_day operator/(const month_day& md, int y) NOEXCEPT; CONSTCD11 year_month_day_last operator/(const year_month& ym, last_spec) NOEXCEPT; CONSTCD11 year_month_day_last operator/(const year& y, const month_day_last& mdl) NOEXCEPT; CONSTCD11 year_month_day_last operator/(int y, const month_day_last& mdl) NOEXCEPT; CONSTCD11 year_month_day_last operator/(const month_day_last& mdl, const year& y) NOEXCEPT; CONSTCD11 year_month_day_last operator/(const month_day_last& mdl, int y) NOEXCEPT; CONSTCD11 year_month_weekday operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT; CONSTCD11 year_month_weekday operator/(const year& y, const month_weekday& mwd) NOEXCEPT; CONSTCD11 year_month_weekday operator/(int y, const month_weekday& mwd) NOEXCEPT; CONSTCD11 year_month_weekday operator/(const month_weekday& mwd, const year& y) NOEXCEPT; CONSTCD11 year_month_weekday operator/(const month_weekday& mwd, int y) NOEXCEPT; CONSTCD11 year_month_weekday_last operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT; CONSTCD11 year_month_weekday_last operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT; CONSTCD11 year_month_weekday_last operator/(int y, const month_weekday_last& mwdl) NOEXCEPT; CONSTCD11 year_month_weekday_last operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT; CONSTCD11 year_month_weekday_last operator/(const month_weekday_last& mwdl, int y) NOEXCEPT; // Detailed interface // day class day { unsigned char d_; public: day() = default; explicit CONSTCD11 day(unsigned d) NOEXCEPT; CONSTCD14 day& operator++() NOEXCEPT; CONSTCD14 day operator++(int) NOEXCEPT; CONSTCD14 day& operator--() NOEXCEPT; CONSTCD14 day operator--(int) NOEXCEPT; CONSTCD14 day& operator+=(const days& d) NOEXCEPT; CONSTCD14 day& operator-=(const days& d) NOEXCEPT; CONSTCD11 explicit operator unsigned() const NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; }; CONSTCD11 bool operator==(const day& x, const day& y) NOEXCEPT; CONSTCD11 bool operator!=(const day& x, const day& y) NOEXCEPT; CONSTCD11 bool operator< (const day& x, const day& y) NOEXCEPT; CONSTCD11 bool operator> (const day& x, const day& y) NOEXCEPT; CONSTCD11 bool operator<=(const day& x, const day& y) NOEXCEPT; CONSTCD11 bool operator>=(const day& x, const day& y) NOEXCEPT; CONSTCD11 day operator+(const day& x, const days& y) NOEXCEPT; CONSTCD11 day operator+(const days& x, const day& y) NOEXCEPT; CONSTCD11 day operator-(const day& x, const days& y) NOEXCEPT; CONSTCD11 days operator-(const day& x, const day& y) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const day& d); // month class month { unsigned char m_; public: month() = default; explicit CONSTCD11 month(unsigned m) NOEXCEPT; CONSTCD14 month& operator++() NOEXCEPT; CONSTCD14 month operator++(int) NOEXCEPT; CONSTCD14 month& operator--() NOEXCEPT; CONSTCD14 month operator--(int) NOEXCEPT; CONSTCD14 month& operator+=(const months& m) NOEXCEPT; CONSTCD14 month& operator-=(const months& m) NOEXCEPT; CONSTCD11 explicit operator unsigned() const NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; }; CONSTCD11 bool operator==(const month& x, const month& y) NOEXCEPT; CONSTCD11 bool operator!=(const month& x, const month& y) NOEXCEPT; CONSTCD11 bool operator< (const month& x, const month& y) NOEXCEPT; CONSTCD11 bool operator> (const month& x, const month& y) NOEXCEPT; CONSTCD11 bool operator<=(const month& x, const month& y) NOEXCEPT; CONSTCD11 bool operator>=(const month& x, const month& y) NOEXCEPT; CONSTCD14 month operator+(const month& x, const months& y) NOEXCEPT; CONSTCD14 month operator+(const months& x, const month& y) NOEXCEPT; CONSTCD14 month operator-(const month& x, const months& y) NOEXCEPT; CONSTCD14 months operator-(const month& x, const month& y) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const month& m); // year class year { short y_; public: year() = default; explicit CONSTCD11 year(int y) NOEXCEPT; CONSTCD14 year& operator++() NOEXCEPT; CONSTCD14 year operator++(int) NOEXCEPT; CONSTCD14 year& operator--() NOEXCEPT; CONSTCD14 year operator--(int) NOEXCEPT; CONSTCD14 year& operator+=(const years& y) NOEXCEPT; CONSTCD14 year& operator-=(const years& y) NOEXCEPT; CONSTCD11 year operator-() const NOEXCEPT; CONSTCD11 year operator+() const NOEXCEPT; CONSTCD11 bool is_leap() const NOEXCEPT; CONSTCD11 explicit operator int() const NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; static CONSTCD11 year min() NOEXCEPT; static CONSTCD11 year max() NOEXCEPT; }; CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT; CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT; CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT; CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT; CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT; CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT; CONSTCD11 year operator+(const year& x, const years& y) NOEXCEPT; CONSTCD11 year operator+(const years& x, const year& y) NOEXCEPT; CONSTCD11 year operator-(const year& x, const years& y) NOEXCEPT; CONSTCD11 years operator-(const year& x, const year& y) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const year& y); // weekday class weekday { unsigned char wd_; public: weekday() = default; explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT; CONSTCD11 weekday(const sys_days& dp) NOEXCEPT; CONSTCD11 explicit weekday(const local_days& dp) NOEXCEPT; CONSTCD14 weekday& operator++() NOEXCEPT; CONSTCD14 weekday operator++(int) NOEXCEPT; CONSTCD14 weekday& operator--() NOEXCEPT; CONSTCD14 weekday operator--(int) NOEXCEPT; CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT; CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT; CONSTCD11 weekday_last operator[](last_spec) const NOEXCEPT; private: static CONSTCD11 unsigned char weekday_from_days(int z) NOEXCEPT; friend CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; friend CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT; friend CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT; template friend std::basic_ostream& operator<<(std::basic_ostream& os, const weekday& wd); friend class weekday_indexed; }; CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT; CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT; CONSTCD14 weekday operator+(const days& x, const weekday& y) NOEXCEPT; CONSTCD14 weekday operator-(const weekday& x, const days& y) NOEXCEPT; CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const weekday& wd); // weekday_indexed class weekday_indexed { unsigned char wd_ : 4; unsigned char index_ : 4; public: weekday_indexed() = default; CONSTCD11 weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT; CONSTCD11 date::weekday weekday() const NOEXCEPT; CONSTCD11 unsigned index() const NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; }; CONSTCD11 bool operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT; CONSTCD11 bool operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const weekday_indexed& wdi); // weekday_last class weekday_last { date::weekday wd_; public: explicit CONSTCD11 weekday_last(const date::weekday& wd) NOEXCEPT; CONSTCD11 date::weekday weekday() const NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; }; CONSTCD11 bool operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT; CONSTCD11 bool operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const weekday_last& wdl); namespace detail { struct unspecified_month_disambiguator {}; } // namespace detail // year_month class year_month { date::year y_; date::month m_; public: year_month() = default; CONSTCD11 year_month(const date::year& y, const date::month& m) NOEXCEPT; CONSTCD11 date::year year() const NOEXCEPT; CONSTCD11 date::month month() const NOEXCEPT; template CONSTCD14 year_month& operator+=(const months& dm) NOEXCEPT; template CONSTCD14 year_month& operator-=(const months& dm) NOEXCEPT; CONSTCD14 year_month& operator+=(const years& dy) NOEXCEPT; CONSTCD14 year_month& operator-=(const years& dy) NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; }; CONSTCD11 bool operator==(const year_month& x, const year_month& y) NOEXCEPT; CONSTCD11 bool operator!=(const year_month& x, const year_month& y) NOEXCEPT; CONSTCD11 bool operator< (const year_month& x, const year_month& y) NOEXCEPT; CONSTCD11 bool operator> (const year_month& x, const year_month& y) NOEXCEPT; CONSTCD11 bool operator<=(const year_month& x, const year_month& y) NOEXCEPT; CONSTCD11 bool operator>=(const year_month& x, const year_month& y) NOEXCEPT; template CONSTCD14 year_month operator+(const year_month& ym, const months& dm) NOEXCEPT; template CONSTCD14 year_month operator+(const months& dm, const year_month& ym) NOEXCEPT; template CONSTCD14 year_month operator-(const year_month& ym, const months& dm) NOEXCEPT; CONSTCD11 months operator-(const year_month& x, const year_month& y) NOEXCEPT; CONSTCD11 year_month operator+(const year_month& ym, const years& dy) NOEXCEPT; CONSTCD11 year_month operator+(const years& dy, const year_month& ym) NOEXCEPT; CONSTCD11 year_month operator-(const year_month& ym, const years& dy) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const year_month& ym); // month_day class month_day { date::month m_; date::day d_; public: month_day() = default; CONSTCD11 month_day(const date::month& m, const date::day& d) NOEXCEPT; CONSTCD11 date::month month() const NOEXCEPT; CONSTCD11 date::day day() const NOEXCEPT; CONSTCD14 bool ok() const NOEXCEPT; }; CONSTCD11 bool operator==(const month_day& x, const month_day& y) NOEXCEPT; CONSTCD11 bool operator!=(const month_day& x, const month_day& y) NOEXCEPT; CONSTCD11 bool operator< (const month_day& x, const month_day& y) NOEXCEPT; CONSTCD11 bool operator> (const month_day& x, const month_day& y) NOEXCEPT; CONSTCD11 bool operator<=(const month_day& x, const month_day& y) NOEXCEPT; CONSTCD11 bool operator>=(const month_day& x, const month_day& y) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const month_day& md); // month_day_last class month_day_last { date::month m_; public: CONSTCD11 explicit month_day_last(const date::month& m) NOEXCEPT; CONSTCD11 date::month month() const NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; }; CONSTCD11 bool operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT; CONSTCD11 bool operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT; CONSTCD11 bool operator< (const month_day_last& x, const month_day_last& y) NOEXCEPT; CONSTCD11 bool operator> (const month_day_last& x, const month_day_last& y) NOEXCEPT; CONSTCD11 bool operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT; CONSTCD11 bool operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const month_day_last& mdl); // month_weekday class month_weekday { date::month m_; date::weekday_indexed wdi_; public: CONSTCD11 month_weekday(const date::month& m, const date::weekday_indexed& wdi) NOEXCEPT; CONSTCD11 date::month month() const NOEXCEPT; CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; }; CONSTCD11 bool operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT; CONSTCD11 bool operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const month_weekday& mwd); // month_weekday_last class month_weekday_last { date::month m_; date::weekday_last wdl_; public: CONSTCD11 month_weekday_last(const date::month& m, const date::weekday_last& wd) NOEXCEPT; CONSTCD11 date::month month() const NOEXCEPT; CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; }; CONSTCD11 bool operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT; CONSTCD11 bool operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const month_weekday_last& mwdl); // class year_month_day class year_month_day { date::year y_; date::month m_; date::day d_; public: year_month_day() = default; CONSTCD11 year_month_day(const date::year& y, const date::month& m, const date::day& d) NOEXCEPT; CONSTCD14 year_month_day(const year_month_day_last& ymdl) NOEXCEPT; CONSTCD14 year_month_day(sys_days dp) NOEXCEPT; CONSTCD14 explicit year_month_day(local_days dp) NOEXCEPT; template CONSTCD14 year_month_day& operator+=(const months& m) NOEXCEPT; template CONSTCD14 year_month_day& operator-=(const months& m) NOEXCEPT; CONSTCD14 year_month_day& operator+=(const years& y) NOEXCEPT; CONSTCD14 year_month_day& operator-=(const years& y) NOEXCEPT; CONSTCD11 date::year year() const NOEXCEPT; CONSTCD11 date::month month() const NOEXCEPT; CONSTCD11 date::day day() const NOEXCEPT; CONSTCD14 operator sys_days() const NOEXCEPT; CONSTCD14 explicit operator local_days() const NOEXCEPT; CONSTCD14 bool ok() const NOEXCEPT; private: static CONSTCD14 year_month_day from_days(days dp) NOEXCEPT; CONSTCD14 days to_days() const NOEXCEPT; }; CONSTCD11 bool operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT; CONSTCD11 bool operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT; CONSTCD11 bool operator< (const year_month_day& x, const year_month_day& y) NOEXCEPT; CONSTCD11 bool operator> (const year_month_day& x, const year_month_day& y) NOEXCEPT; CONSTCD11 bool operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT; CONSTCD11 bool operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT; template CONSTCD14 year_month_day operator+(const year_month_day& ymd, const months& dm) NOEXCEPT; template CONSTCD14 year_month_day operator+(const months& dm, const year_month_day& ymd) NOEXCEPT; template CONSTCD14 year_month_day operator-(const year_month_day& ymd, const months& dm) NOEXCEPT; CONSTCD11 year_month_day operator+(const year_month_day& ymd, const years& dy) NOEXCEPT; CONSTCD11 year_month_day operator+(const years& dy, const year_month_day& ymd) NOEXCEPT; CONSTCD11 year_month_day operator-(const year_month_day& ymd, const years& dy) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const year_month_day& ymd); // year_month_day_last class year_month_day_last { date::year y_; date::month_day_last mdl_; public: CONSTCD11 year_month_day_last(const date::year& y, const date::month_day_last& mdl) NOEXCEPT; template CONSTCD14 year_month_day_last& operator+=(const months& m) NOEXCEPT; template CONSTCD14 year_month_day_last& operator-=(const months& m) NOEXCEPT; CONSTCD14 year_month_day_last& operator+=(const years& y) NOEXCEPT; CONSTCD14 year_month_day_last& operator-=(const years& y) NOEXCEPT; CONSTCD11 date::year year() const NOEXCEPT; CONSTCD11 date::month month() const NOEXCEPT; CONSTCD11 date::month_day_last month_day_last() const NOEXCEPT; CONSTCD14 date::day day() const NOEXCEPT; CONSTCD14 operator sys_days() const NOEXCEPT; CONSTCD14 explicit operator local_days() const NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; }; CONSTCD11 bool operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; CONSTCD11 bool operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; CONSTCD11 bool operator< (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; CONSTCD11 bool operator> (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; CONSTCD11 bool operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; CONSTCD11 bool operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; template CONSTCD14 year_month_day_last operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT; template CONSTCD14 year_month_day_last operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT; CONSTCD11 year_month_day_last operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT; CONSTCD11 year_month_day_last operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT; template CONSTCD14 year_month_day_last operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT; CONSTCD11 year_month_day_last operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const year_month_day_last& ymdl); // year_month_weekday class year_month_weekday { date::year y_; date::month m_; date::weekday_indexed wdi_; public: year_month_weekday() = default; CONSTCD11 year_month_weekday(const date::year& y, const date::month& m, const date::weekday_indexed& wdi) NOEXCEPT; CONSTCD14 year_month_weekday(const sys_days& dp) NOEXCEPT; CONSTCD14 explicit year_month_weekday(const local_days& dp) NOEXCEPT; template CONSTCD14 year_month_weekday& operator+=(const months& m) NOEXCEPT; template CONSTCD14 year_month_weekday& operator-=(const months& m) NOEXCEPT; CONSTCD14 year_month_weekday& operator+=(const years& y) NOEXCEPT; CONSTCD14 year_month_weekday& operator-=(const years& y) NOEXCEPT; CONSTCD11 date::year year() const NOEXCEPT; CONSTCD11 date::month month() const NOEXCEPT; CONSTCD11 date::weekday weekday() const NOEXCEPT; CONSTCD11 unsigned index() const NOEXCEPT; CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT; CONSTCD14 operator sys_days() const NOEXCEPT; CONSTCD14 explicit operator local_days() const NOEXCEPT; CONSTCD14 bool ok() const NOEXCEPT; private: static CONSTCD14 year_month_weekday from_days(days dp) NOEXCEPT; CONSTCD14 days to_days() const NOEXCEPT; }; CONSTCD11 bool operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT; CONSTCD11 bool operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT; template CONSTCD14 year_month_weekday operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT; template CONSTCD14 year_month_weekday operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT; CONSTCD11 year_month_weekday operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT; CONSTCD11 year_month_weekday operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT; template CONSTCD14 year_month_weekday operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT; CONSTCD11 year_month_weekday operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const year_month_weekday& ymwdi); // year_month_weekday_last class year_month_weekday_last { date::year y_; date::month m_; date::weekday_last wdl_; public: CONSTCD11 year_month_weekday_last(const date::year& y, const date::month& m, const date::weekday_last& wdl) NOEXCEPT; template CONSTCD14 year_month_weekday_last& operator+=(const months& m) NOEXCEPT; template CONSTCD14 year_month_weekday_last& operator-=(const months& m) NOEXCEPT; CONSTCD14 year_month_weekday_last& operator+=(const years& y) NOEXCEPT; CONSTCD14 year_month_weekday_last& operator-=(const years& y) NOEXCEPT; CONSTCD11 date::year year() const NOEXCEPT; CONSTCD11 date::month month() const NOEXCEPT; CONSTCD11 date::weekday weekday() const NOEXCEPT; CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT; CONSTCD14 operator sys_days() const NOEXCEPT; CONSTCD14 explicit operator local_days() const NOEXCEPT; CONSTCD11 bool ok() const NOEXCEPT; private: CONSTCD14 days to_days() const NOEXCEPT; }; CONSTCD11 bool operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT; CONSTCD11 bool operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT; template CONSTCD14 year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT; template CONSTCD14 year_month_weekday_last operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT; CONSTCD11 year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT; CONSTCD11 year_month_weekday_last operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT; template CONSTCD14 year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT; CONSTCD11 year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT; template std::basic_ostream& operator<<(std::basic_ostream& os, const year_month_weekday_last& ymwdl); #if !defined(_MSC_VER) || (_MSC_VER >= 1900) inline namespace literals { CONSTCD11 date::day operator "" _d(unsigned long long d) NOEXCEPT; CONSTCD11 date::year operator "" _y(unsigned long long y) NOEXCEPT; } // inline namespace literals #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) // CONSTDATA date::month January{1}; // CONSTDATA date::month February{2}; // CONSTDATA date::month March{3}; // CONSTDATA date::month April{4}; // CONSTDATA date::month May{5}; // CONSTDATA date::month June{6}; // CONSTDATA date::month July{7}; // CONSTDATA date::month August{8}; // CONSTDATA date::month September{9}; // CONSTDATA date::month October{10}; // CONSTDATA date::month November{11}; // CONSTDATA date::month December{12}; // // CONSTDATA date::weekday Sunday{0u}; // CONSTDATA date::weekday Monday{1u}; // CONSTDATA date::weekday Tuesday{2u}; // CONSTDATA date::weekday Wednesday{3u}; // CONSTDATA date::weekday Thursday{4u}; // CONSTDATA date::weekday Friday{5u}; // CONSTDATA date::weekday Saturday{6u}; #if HAS_VOID_T template > struct is_clock : std::false_type {}; template struct is_clock> : std::true_type {}; #endif // HAS_VOID_T //----------------+ // Implementation | //----------------+ // utilities namespace detail { template> class save_istream { protected: std::basic_ios& is_; CharT fill_; std::ios::fmtflags flags_; std::streamsize width_; std::basic_ostream* tie_; std::locale loc_; public: ~save_istream() { is_.fill(fill_); is_.flags(flags_); is_.width(width_); is_.imbue(loc_); is_.tie(tie_); } save_istream(const save_istream&) = delete; save_istream& operator=(const save_istream&) = delete; explicit save_istream(std::basic_ios& is) : is_(is) , fill_(is.fill()) , flags_(is.flags()) , width_(is.width(0)) , tie_(is.tie(nullptr)) , loc_(is.getloc()) { if (tie_ != nullptr) tie_->flush(); } }; template> class save_ostream : private save_istream { public: ~save_ostream() { if ((this->flags_ & std::ios::unitbuf) && #if __cplusplus >= 201703 std::uncaught_exceptions() == 0 && #else !std::uncaught_exception() && #endif this->is_.good()) this->is_.rdbuf()->pubsync(); } save_ostream(const save_ostream&) = delete; save_ostream& operator=(const save_ostream&) = delete; explicit save_ostream(std::basic_ios& os) : save_istream(os) { } }; template struct choose_trunc_type { static const int digits = std::numeric_limits::digits; using type = typename std::conditional < digits < 32, std::int32_t, typename std::conditional < digits < 64, std::int64_t, #ifdef __SIZEOF_INT128__ __int128 #else std::int64_t #endif >::type >::type; }; template CONSTCD11 inline typename std::enable_if < !std::chrono::treat_as_floating_point::value, T >::type trunc(T t) NOEXCEPT { return t; } template CONSTCD14 inline typename std::enable_if < std::chrono::treat_as_floating_point::value, T >::type trunc(T t) NOEXCEPT { using namespace std; using I = typename choose_trunc_type::type; CONSTDATA auto digits = numeric_limits::digits; static_assert(digits < numeric_limits::digits, ""); CONSTDATA auto max = I{1} << (digits-1); CONSTDATA auto min = -max; const auto negative = t < T{0}; if (min <= t && t <= max && t != 0 && t == t) { t = static_cast(static_cast(t)); if (t == 0 && negative) t = -t; } return t; } template struct static_gcd { static const std::intmax_t value = static_gcd::value; }; template struct static_gcd { static const std::intmax_t value = Xp; }; template <> struct static_gcd<0, 0> { static const std::intmax_t value = 1; }; template struct no_overflow { private: static const std::intmax_t gcd_n1_n2 = static_gcd::value; static const std::intmax_t gcd_d1_d2 = static_gcd::value; static const std::intmax_t n1 = R1::num / gcd_n1_n2; static const std::intmax_t d1 = R1::den / gcd_d1_d2; static const std::intmax_t n2 = R2::num / gcd_n1_n2; static const std::intmax_t d2 = R2::den / gcd_d1_d2; static const std::intmax_t max = -((std::intmax_t(1) << (sizeof(std::intmax_t) * CHAR_BIT - 1)) + 1); template struct mul // overflow == false { static const std::intmax_t value = Xp * Yp; }; template struct mul { static const std::intmax_t value = 1; }; public: static const bool value = (n1 <= max / d2) && (n2 <= max / d1); typedef std::ratio::value, mul::value> type; }; } // detail // trunc towards zero template CONSTCD11 inline typename std::enable_if < detail::no_overflow::value, To >::type trunc(const std::chrono::duration& d) { return To{detail::trunc(std::chrono::duration_cast(d).count())}; } template CONSTCD11 inline typename std::enable_if < !detail::no_overflow::value, To >::type trunc(const std::chrono::duration& d) { using namespace std::chrono; using rep = typename std::common_type::type; return To{detail::trunc(duration_cast(duration_cast>(d)).count())}; } #ifndef HAS_CHRONO_ROUNDING # if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023918 || (_MSC_FULL_VER >= 190000000 && defined (__clang__))) # define HAS_CHRONO_ROUNDING 1 # elif defined(__cpp_lib_chrono) && __cplusplus > 201402 && __cpp_lib_chrono >= 201510 # define HAS_CHRONO_ROUNDING 1 # elif defined(_LIBCPP_VERSION) && __cplusplus > 201402 && _LIBCPP_VERSION >= 3800 # define HAS_CHRONO_ROUNDING 1 # else # define HAS_CHRONO_ROUNDING 0 # endif #endif // HAS_CHRONO_ROUNDING #if HAS_CHRONO_ROUNDING == 0 // round down template CONSTCD14 inline typename std::enable_if < detail::no_overflow::value, To >::type floor(const std::chrono::duration& d) { auto t = trunc(d); if (t > d) return t - To{1}; return t; } template CONSTCD14 inline typename std::enable_if < !detail::no_overflow::value, To >::type floor(const std::chrono::duration& d) { using namespace std::chrono; using rep = typename std::common_type::type; return floor(floor>(d)); } // round to nearest, to even on tie template CONSTCD14 inline To round(const std::chrono::duration& d) { auto t0 = floor(d); auto t1 = t0 + To{1}; if (t1 == To{0} && t0 < To{0}) t1 = -t1; auto diff0 = d - t0; auto diff1 = t1 - d; if (diff0 == diff1) { if (t0 - trunc(t0/2)*2 == To{0}) return t0; return t1; } if (diff0 < diff1) return t0; return t1; } // round up template CONSTCD14 inline To ceil(const std::chrono::duration& d) { auto t = trunc(d); if (t < d) return t + To{1}; return t; } template ::is_signed >::type> CONSTCD11 std::chrono::duration abs(std::chrono::duration d) { return d >= d.zero() ? d : -d; } // round down template CONSTCD11 inline std::chrono::time_point floor(const std::chrono::time_point& tp) { using std::chrono::time_point; return time_point{date::floor(tp.time_since_epoch())}; } // round to nearest, to even on tie template CONSTCD11 inline std::chrono::time_point round(const std::chrono::time_point& tp) { using std::chrono::time_point; return time_point{round(tp.time_since_epoch())}; } // round up template CONSTCD11 inline std::chrono::time_point ceil(const std::chrono::time_point& tp) { using std::chrono::time_point; return time_point{ceil(tp.time_since_epoch())}; } #else // HAS_CHRONO_ROUNDING == 1 using std::chrono::floor; using std::chrono::ceil; using std::chrono::round; using std::chrono::abs; #endif // HAS_CHRONO_ROUNDING // trunc towards zero template CONSTCD11 inline std::chrono::time_point trunc(const std::chrono::time_point& tp) { using std::chrono::time_point; return time_point{trunc(tp.time_since_epoch())}; } // day CONSTCD11 inline day::day(unsigned d) NOEXCEPT : d_(static_cast(d)) {} CONSTCD14 inline day& day::operator++() NOEXCEPT {++d_; return *this;} CONSTCD14 inline day day::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} CONSTCD14 inline day& day::operator--() NOEXCEPT {--d_; return *this;} CONSTCD14 inline day day::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} CONSTCD14 inline day& day::operator+=(const days& d) NOEXCEPT {*this = *this + d; return *this;} CONSTCD14 inline day& day::operator-=(const days& d) NOEXCEPT {*this = *this - d; return *this;} CONSTCD11 inline day::operator unsigned() const NOEXCEPT {return d_;} CONSTCD11 inline bool day::ok() const NOEXCEPT {return 1 <= d_ && d_ <= 31;} CONSTCD11 inline bool operator==(const day& x, const day& y) NOEXCEPT { return static_cast(x) == static_cast(y); } CONSTCD11 inline bool operator!=(const day& x, const day& y) NOEXCEPT { return !(x == y); } CONSTCD11 inline bool operator<(const day& x, const day& y) NOEXCEPT { return static_cast(x) < static_cast(y); } CONSTCD11 inline bool operator>(const day& x, const day& y) NOEXCEPT { return y < x; } CONSTCD11 inline bool operator<=(const day& x, const day& y) NOEXCEPT { return !(y < x); } CONSTCD11 inline bool operator>=(const day& x, const day& y) NOEXCEPT { return !(x < y); } CONSTCD11 inline days operator-(const day& x, const day& y) NOEXCEPT { return days{static_cast(static_cast(x) - static_cast(y))}; } CONSTCD11 inline day operator+(const day& x, const days& y) NOEXCEPT { return day{static_cast(x) + static_cast(y.count())}; } CONSTCD11 inline day operator+(const days& x, const day& y) NOEXCEPT { return y + x; } CONSTCD11 inline day operator-(const day& x, const days& y) NOEXCEPT { return x + -y; } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const day& d) { detail::save_ostream _(os); os.fill('0'); os.flags(std::ios::dec | std::ios::right); os.width(2); os << static_cast(d); if (!d.ok()) os << " is not a valid day"; return os; } // month CONSTCD11 inline month::month(unsigned m) NOEXCEPT : m_(static_cast(m)) {} CONSTCD14 inline month& month::operator++() NOEXCEPT {*this += months{1}; return *this;} CONSTCD14 inline month month::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} CONSTCD14 inline month& month::operator--() NOEXCEPT {*this -= months{1}; return *this;} CONSTCD14 inline month month::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} CONSTCD14 inline month& month::operator+=(const months& m) NOEXCEPT { *this = *this + m; return *this; } CONSTCD14 inline month& month::operator-=(const months& m) NOEXCEPT { *this = *this - m; return *this; } CONSTCD11 inline month::operator unsigned() const NOEXCEPT {return m_;} CONSTCD11 inline bool month::ok() const NOEXCEPT {return 1 <= m_ && m_ <= 12;} CONSTCD11 inline bool operator==(const month& x, const month& y) NOEXCEPT { return static_cast(x) == static_cast(y); } CONSTCD11 inline bool operator!=(const month& x, const month& y) NOEXCEPT { return !(x == y); } CONSTCD11 inline bool operator<(const month& x, const month& y) NOEXCEPT { return static_cast(x) < static_cast(y); } CONSTCD11 inline bool operator>(const month& x, const month& y) NOEXCEPT { return y < x; } CONSTCD11 inline bool operator<=(const month& x, const month& y) NOEXCEPT { return !(y < x); } CONSTCD11 inline bool operator>=(const month& x, const month& y) NOEXCEPT { return !(x < y); } CONSTCD14 inline months operator-(const month& x, const month& y) NOEXCEPT { auto const d = static_cast(x) - static_cast(y); return months(d <= 11 ? d : d + 12); } CONSTCD14 inline month operator+(const month& x, const months& y) NOEXCEPT { auto const mu = static_cast(static_cast(x)) + (y.count() - 1); auto const yr = (mu >= 0 ? mu : mu-11) / 12; return month{static_cast(mu - yr * 12 + 1)}; } CONSTCD14 inline month operator+(const months& x, const month& y) NOEXCEPT { return y + x; } CONSTCD14 inline month operator-(const month& x, const months& y) NOEXCEPT { return x + -y; } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const month& m) { if (m.ok()) { CharT fmt[] = {'%', 'b', 0}; os << format(os.getloc(), fmt, m); } else os << static_cast(m) << " is not a valid month"; return os; } // year CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast(y)) {} CONSTCD14 inline year& year::operator++() NOEXCEPT {++y_; return *this;} CONSTCD14 inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} CONSTCD14 inline year& year::operator--() NOEXCEPT {--y_; return *this;} CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;} CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;} CONSTCD11 inline year year::operator-() const NOEXCEPT {return year{-y_};} CONSTCD11 inline year year::operator+() const NOEXCEPT {return *this;} CONSTCD11 inline bool year::is_leap() const NOEXCEPT { return y_ % 4 == 0 && (y_ % 100 != 0 || y_ % 400 == 0); } CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;} CONSTCD11 inline bool year::ok() const NOEXCEPT { return y_ != std::numeric_limits::min(); } CONSTCD11 inline year year::min() NOEXCEPT { return year{-32767}; } CONSTCD11 inline year year::max() NOEXCEPT { return year{32767}; } CONSTCD11 inline bool operator==(const year& x, const year& y) NOEXCEPT { return static_cast(x) == static_cast(y); } CONSTCD11 inline bool operator!=(const year& x, const year& y) NOEXCEPT { return !(x == y); } CONSTCD11 inline bool operator<(const year& x, const year& y) NOEXCEPT { return static_cast(x) < static_cast(y); } CONSTCD11 inline bool operator>(const year& x, const year& y) NOEXCEPT { return y < x; } CONSTCD11 inline bool operator<=(const year& x, const year& y) NOEXCEPT { return !(y < x); } CONSTCD11 inline bool operator>=(const year& x, const year& y) NOEXCEPT { return !(x < y); } CONSTCD11 inline years operator-(const year& x, const year& y) NOEXCEPT { return years{static_cast(x) - static_cast(y)}; } CONSTCD11 inline year operator+(const year& x, const years& y) NOEXCEPT { return year{static_cast(x) + y.count()}; } CONSTCD11 inline year operator+(const years& x, const year& y) NOEXCEPT { return y + x; } CONSTCD11 inline year operator-(const year& x, const years& y) NOEXCEPT { return year{static_cast(x) - y.count()}; } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const year& y) { detail::save_ostream _(os); os.fill('0'); os.flags(std::ios::dec | std::ios::internal); os.width(4 + (y < year{0})); os << static_cast(y); if (!y.ok()) os << " is not a valid year"; return os; } // weekday CONSTCD11 inline unsigned char weekday::weekday_from_days(int z) NOEXCEPT { return static_cast(static_cast( z >= -4 ? (z+4) % 7 : (z+5) % 7 + 6)); } CONSTCD11 inline weekday::weekday(unsigned wd) NOEXCEPT : wd_(static_cast(wd != 7 ? wd : 0)) {} CONSTCD11 inline weekday::weekday(const sys_days& dp) NOEXCEPT : wd_(weekday_from_days(dp.time_since_epoch().count())) {} CONSTCD11 inline weekday::weekday(const local_days& dp) NOEXCEPT : wd_(weekday_from_days(dp.time_since_epoch().count())) {} CONSTCD14 inline weekday& weekday::operator++() NOEXCEPT {*this += days{1}; return *this;} CONSTCD14 inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} CONSTCD14 inline weekday& weekday::operator--() NOEXCEPT {*this -= days{1}; return *this;} CONSTCD14 inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} CONSTCD14 inline weekday& weekday::operator+=(const days& d) NOEXCEPT { *this = *this + d; return *this; } CONSTCD14 inline weekday& weekday::operator-=(const days& d) NOEXCEPT { *this = *this - d; return *this; } CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;} CONSTCD11 inline bool operator==(const weekday& x, const weekday& y) NOEXCEPT { return x.wd_ == y.wd_; } CONSTCD11 inline bool operator!=(const weekday& x, const weekday& y) NOEXCEPT { return !(x == y); } CONSTCD14 inline days operator-(const weekday& x, const weekday& y) NOEXCEPT { auto const wdu = x.wd_ - y.wd_; auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; return days{wdu - wk * 7}; } CONSTCD14 inline weekday operator+(const weekday& x, const days& y) NOEXCEPT { auto const wdu = static_cast(static_cast(x.wd_)) + y.count(); auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; return weekday{static_cast(wdu - wk * 7)}; } CONSTCD14 inline weekday operator+(const days& x, const weekday& y) NOEXCEPT { return y + x; } CONSTCD14 inline weekday operator-(const weekday& x, const days& y) NOEXCEPT { return x + -y; } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const weekday& wd) { if (wd.ok()) { CharT fmt[] = {'%', 'a', 0}; os << format(fmt, wd); } else os << static_cast(wd.wd_) << " is not a valid weekday"; return os; } #if !defined(_MSC_VER) || (_MSC_VER >= 1900) inline namespace literals { CONSTCD11 inline date::day operator "" _d(unsigned long long d) NOEXCEPT { return date::day{static_cast(d)}; } CONSTCD11 inline date::year operator "" _y(unsigned long long y) NOEXCEPT { return date::year(static_cast(y)); } #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) CONSTDATA date::last_spec last{}; CONSTDATA date::month jan{1}; CONSTDATA date::month feb{2}; CONSTDATA date::month mar{3}; CONSTDATA date::month apr{4}; CONSTDATA date::month may{5}; CONSTDATA date::month jun{6}; CONSTDATA date::month jul{7}; CONSTDATA date::month aug{8}; CONSTDATA date::month sep{9}; CONSTDATA date::month oct{10}; CONSTDATA date::month nov{11}; CONSTDATA date::month dec{12}; CONSTDATA date::weekday sun{0u}; CONSTDATA date::weekday mon{1u}; CONSTDATA date::weekday tue{2u}; CONSTDATA date::weekday wed{3u}; CONSTDATA date::weekday thu{4u}; CONSTDATA date::weekday fri{5u}; CONSTDATA date::weekday sat{6u}; #if !defined(_MSC_VER) || (_MSC_VER >= 1900) } // inline namespace literals #endif CONSTDATA date::month January{1}; CONSTDATA date::month February{2}; CONSTDATA date::month March{3}; CONSTDATA date::month April{4}; CONSTDATA date::month May{5}; CONSTDATA date::month June{6}; CONSTDATA date::month July{7}; CONSTDATA date::month August{8}; CONSTDATA date::month September{9}; CONSTDATA date::month October{10}; CONSTDATA date::month November{11}; CONSTDATA date::month December{12}; CONSTDATA date::weekday Monday{1}; CONSTDATA date::weekday Tuesday{2}; CONSTDATA date::weekday Wednesday{3}; CONSTDATA date::weekday Thursday{4}; CONSTDATA date::weekday Friday{5}; CONSTDATA date::weekday Saturday{6}; CONSTDATA date::weekday Sunday{7}; // weekday_indexed CONSTCD11 inline weekday weekday_indexed::weekday() const NOEXCEPT { return date::weekday{static_cast(wd_)}; } CONSTCD11 inline unsigned weekday_indexed::index() const NOEXCEPT {return index_;} CONSTCD11 inline bool weekday_indexed::ok() const NOEXCEPT { return weekday().ok() && 1 <= index_ && index_ <= 5; } #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" #endif // __GNUC__ CONSTCD11 inline weekday_indexed::weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT : wd_(static_cast(static_cast(wd.wd_))) , index_(static_cast(index)) {} #ifdef __GNUC__ # pragma GCC diagnostic pop #endif // __GNUC__ template inline std::basic_ostream& operator<<(std::basic_ostream& os, const weekday_indexed& wdi) { os << wdi.weekday() << '[' << wdi.index(); if (!(1 <= wdi.index() && wdi.index() <= 5)) os << " is not a valid index"; os << ']'; return os; } CONSTCD11 inline weekday_indexed weekday::operator[](unsigned index) const NOEXCEPT { return {*this, index}; } CONSTCD11 inline bool operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT { return x.weekday() == y.weekday() && x.index() == y.index(); } CONSTCD11 inline bool operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT { return !(x == y); } // weekday_last CONSTCD11 inline date::weekday weekday_last::weekday() const NOEXCEPT {return wd_;} CONSTCD11 inline bool weekday_last::ok() const NOEXCEPT {return wd_.ok();} CONSTCD11 inline weekday_last::weekday_last(const date::weekday& wd) NOEXCEPT : wd_(wd) {} CONSTCD11 inline bool operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT { return x.weekday() == y.weekday(); } CONSTCD11 inline bool operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT { return !(x == y); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const weekday_last& wdl) { return os << wdl.weekday() << "[last]"; } CONSTCD11 inline weekday_last weekday::operator[](last_spec) const NOEXCEPT { return weekday_last{*this}; } // year_month CONSTCD11 inline year_month::year_month(const date::year& y, const date::month& m) NOEXCEPT : y_(y) , m_(m) {} CONSTCD11 inline year year_month::year() const NOEXCEPT {return y_;} CONSTCD11 inline month year_month::month() const NOEXCEPT {return m_;} CONSTCD11 inline bool year_month::ok() const NOEXCEPT {return y_.ok() && m_.ok();} template CONSTCD14 inline year_month& year_month::operator+=(const months& dm) NOEXCEPT { *this = *this + dm; return *this; } template CONSTCD14 inline year_month& year_month::operator-=(const months& dm) NOEXCEPT { *this = *this - dm; return *this; } CONSTCD14 inline year_month& year_month::operator+=(const years& dy) NOEXCEPT { *this = *this + dy; return *this; } CONSTCD14 inline year_month& year_month::operator-=(const years& dy) NOEXCEPT { *this = *this - dy; return *this; } CONSTCD11 inline bool operator==(const year_month& x, const year_month& y) NOEXCEPT { return x.year() == y.year() && x.month() == y.month(); } CONSTCD11 inline bool operator!=(const year_month& x, const year_month& y) NOEXCEPT { return !(x == y); } CONSTCD11 inline bool operator<(const year_month& x, const year_month& y) NOEXCEPT { return x.year() < y.year() ? true : (x.year() > y.year() ? false : (x.month() < y.month())); } CONSTCD11 inline bool operator>(const year_month& x, const year_month& y) NOEXCEPT { return y < x; } CONSTCD11 inline bool operator<=(const year_month& x, const year_month& y) NOEXCEPT { return !(y < x); } CONSTCD11 inline bool operator>=(const year_month& x, const year_month& y) NOEXCEPT { return !(x < y); } template CONSTCD14 inline year_month operator+(const year_month& ym, const months& dm) NOEXCEPT { auto dmi = static_cast(static_cast(ym.month())) - 1 + dm.count(); auto dy = (dmi >= 0 ? dmi : dmi-11) / 12; dmi = dmi - dy * 12 + 1; return (ym.year() + years(dy)) / month(static_cast(dmi)); } template CONSTCD14 inline year_month operator+(const months& dm, const year_month& ym) NOEXCEPT { return ym + dm; } template CONSTCD14 inline year_month operator-(const year_month& ym, const months& dm) NOEXCEPT { return ym + -dm; } CONSTCD11 inline months operator-(const year_month& x, const year_month& y) NOEXCEPT { return (x.year() - y.year()) + months(static_cast(x.month()) - static_cast(y.month())); } CONSTCD11 inline year_month operator+(const year_month& ym, const years& dy) NOEXCEPT { return (ym.year() + dy) / ym.month(); } CONSTCD11 inline year_month operator+(const years& dy, const year_month& ym) NOEXCEPT { return ym + dy; } CONSTCD11 inline year_month operator-(const year_month& ym, const years& dy) NOEXCEPT { return ym + -dy; } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const year_month& ym) { return os << ym.year() << '/' << ym.month(); } // month_day CONSTCD11 inline month_day::month_day(const date::month& m, const date::day& d) NOEXCEPT : m_(m) , d_(d) {} CONSTCD11 inline date::month month_day::month() const NOEXCEPT {return m_;} CONSTCD11 inline date::day month_day::day() const NOEXCEPT {return d_;} CONSTCD14 inline bool month_day::ok() const NOEXCEPT { CONSTDATA date::day d[] = { date::day(31), date::day(29), date::day(31), date::day(30), date::day(31), date::day(30), date::day(31), date::day(31), date::day(30), date::day(31), date::day(30), date::day(31) }; return m_.ok() && date::day{1} <= d_ && d_ <= d[static_cast(m_)-1]; } CONSTCD11 inline bool operator==(const month_day& x, const month_day& y) NOEXCEPT { return x.month() == y.month() && x.day() == y.day(); } CONSTCD11 inline bool operator!=(const month_day& x, const month_day& y) NOEXCEPT { return !(x == y); } CONSTCD11 inline bool operator<(const month_day& x, const month_day& y) NOEXCEPT { return x.month() < y.month() ? true : (x.month() > y.month() ? false : (x.day() < y.day())); } CONSTCD11 inline bool operator>(const month_day& x, const month_day& y) NOEXCEPT { return y < x; } CONSTCD11 inline bool operator<=(const month_day& x, const month_day& y) NOEXCEPT { return !(y < x); } CONSTCD11 inline bool operator>=(const month_day& x, const month_day& y) NOEXCEPT { return !(x < y); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const month_day& md) { return os << md.month() << '/' << md.day(); } // month_day_last CONSTCD11 inline month month_day_last::month() const NOEXCEPT {return m_;} CONSTCD11 inline bool month_day_last::ok() const NOEXCEPT {return m_.ok();} CONSTCD11 inline month_day_last::month_day_last(const date::month& m) NOEXCEPT : m_(m) {} CONSTCD11 inline bool operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT { return x.month() == y.month(); } CONSTCD11 inline bool operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT { return !(x == y); } CONSTCD11 inline bool operator<(const month_day_last& x, const month_day_last& y) NOEXCEPT { return x.month() < y.month(); } CONSTCD11 inline bool operator>(const month_day_last& x, const month_day_last& y) NOEXCEPT { return y < x; } CONSTCD11 inline bool operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT { return !(y < x); } CONSTCD11 inline bool operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT { return !(x < y); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const month_day_last& mdl) { return os << mdl.month() << "/last"; } // month_weekday CONSTCD11 inline month_weekday::month_weekday(const date::month& m, const date::weekday_indexed& wdi) NOEXCEPT : m_(m) , wdi_(wdi) {} CONSTCD11 inline month month_weekday::month() const NOEXCEPT {return m_;} CONSTCD11 inline weekday_indexed month_weekday::weekday_indexed() const NOEXCEPT { return wdi_; } CONSTCD11 inline bool month_weekday::ok() const NOEXCEPT { return m_.ok() && wdi_.ok(); } CONSTCD11 inline bool operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT { return x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed(); } CONSTCD11 inline bool operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT { return !(x == y); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const month_weekday& mwd) { return os << mwd.month() << '/' << mwd.weekday_indexed(); } // month_weekday_last CONSTCD11 inline month_weekday_last::month_weekday_last(const date::month& m, const date::weekday_last& wdl) NOEXCEPT : m_(m) , wdl_(wdl) {} CONSTCD11 inline month month_weekday_last::month() const NOEXCEPT {return m_;} CONSTCD11 inline weekday_last month_weekday_last::weekday_last() const NOEXCEPT { return wdl_; } CONSTCD11 inline bool month_weekday_last::ok() const NOEXCEPT { return m_.ok() && wdl_.ok(); } CONSTCD11 inline bool operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT { return x.month() == y.month() && x.weekday_last() == y.weekday_last(); } CONSTCD11 inline bool operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT { return !(x == y); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const month_weekday_last& mwdl) { return os << mwdl.month() << '/' << mwdl.weekday_last(); } // year_month_day_last CONSTCD11 inline year_month_day_last::year_month_day_last(const date::year& y, const date::month_day_last& mdl) NOEXCEPT : y_(y) , mdl_(mdl) {} template CONSTCD14 inline year_month_day_last& year_month_day_last::operator+=(const months& m) NOEXCEPT { *this = *this + m; return *this; } template CONSTCD14 inline year_month_day_last& year_month_day_last::operator-=(const months& m) NOEXCEPT { *this = *this - m; return *this; } CONSTCD14 inline year_month_day_last& year_month_day_last::operator+=(const years& y) NOEXCEPT { *this = *this + y; return *this; } CONSTCD14 inline year_month_day_last& year_month_day_last::operator-=(const years& y) NOEXCEPT { *this = *this - y; return *this; } CONSTCD11 inline year year_month_day_last::year() const NOEXCEPT {return y_;} CONSTCD11 inline month year_month_day_last::month() const NOEXCEPT {return mdl_.month();} CONSTCD11 inline month_day_last year_month_day_last::month_day_last() const NOEXCEPT { return mdl_; } CONSTCD14 inline day year_month_day_last::day() const NOEXCEPT { CONSTDATA date::day d[] = { date::day(31), date::day(28), date::day(31), date::day(30), date::day(31), date::day(30), date::day(31), date::day(31), date::day(30), date::day(31), date::day(30), date::day(31) }; return month() != February || !y_.is_leap() ? d[static_cast(month()) - 1] : date::day{29}; } CONSTCD14 inline year_month_day_last::operator sys_days() const NOEXCEPT { return sys_days(year()/month()/day()); } CONSTCD14 inline year_month_day_last::operator local_days() const NOEXCEPT { return local_days(year()/month()/day()); } CONSTCD11 inline bool year_month_day_last::ok() const NOEXCEPT { return y_.ok() && mdl_.ok(); } CONSTCD11 inline bool operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT { return x.year() == y.year() && x.month_day_last() == y.month_day_last(); } CONSTCD11 inline bool operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT { return !(x == y); } CONSTCD11 inline bool operator<(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT { return x.year() < y.year() ? true : (x.year() > y.year() ? false : (x.month_day_last() < y.month_day_last())); } CONSTCD11 inline bool operator>(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT { return y < x; } CONSTCD11 inline bool operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT { return !(y < x); } CONSTCD11 inline bool operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT { return !(x < y); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const year_month_day_last& ymdl) { return os << ymdl.year() << '/' << ymdl.month_day_last(); } template CONSTCD14 inline year_month_day_last operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT { return (ymdl.year() / ymdl.month() + dm) / last; } template CONSTCD14 inline year_month_day_last operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT { return ymdl + dm; } template CONSTCD14 inline year_month_day_last operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT { return ymdl + (-dm); } CONSTCD11 inline year_month_day_last operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT { return {ymdl.year()+dy, ymdl.month_day_last()}; } CONSTCD11 inline year_month_day_last operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT { return ymdl + dy; } CONSTCD11 inline year_month_day_last operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT { return ymdl + (-dy); } // year_month_day CONSTCD11 inline year_month_day::year_month_day(const date::year& y, const date::month& m, const date::day& d) NOEXCEPT : y_(y) , m_(m) , d_(d) {} CONSTCD14 inline year_month_day::year_month_day(const year_month_day_last& ymdl) NOEXCEPT : y_(ymdl.year()) , m_(ymdl.month()) , d_(ymdl.day()) {} CONSTCD14 inline year_month_day::year_month_day(sys_days dp) NOEXCEPT : year_month_day(from_days(dp.time_since_epoch())) {} CONSTCD14 inline year_month_day::year_month_day(local_days dp) NOEXCEPT : year_month_day(from_days(dp.time_since_epoch())) {} CONSTCD11 inline year year_month_day::year() const NOEXCEPT {return y_;} CONSTCD11 inline month year_month_day::month() const NOEXCEPT {return m_;} CONSTCD11 inline day year_month_day::day() const NOEXCEPT {return d_;} template CONSTCD14 inline year_month_day& year_month_day::operator+=(const months& m) NOEXCEPT { *this = *this + m; return *this; } template CONSTCD14 inline year_month_day& year_month_day::operator-=(const months& m) NOEXCEPT { *this = *this - m; return *this; } CONSTCD14 inline year_month_day& year_month_day::operator+=(const years& y) NOEXCEPT { *this = *this + y; return *this; } CONSTCD14 inline year_month_day& year_month_day::operator-=(const years& y) NOEXCEPT { *this = *this - y; return *this; } CONSTCD14 inline days year_month_day::to_days() const NOEXCEPT { static_assert(std::numeric_limits::digits >= 18, "This algorithm has not been ported to a 16 bit unsigned integer"); static_assert(std::numeric_limits::digits >= 20, "This algorithm has not been ported to a 16 bit signed integer"); auto const y = static_cast(y_) - (m_ <= February); auto const m = static_cast(m_); auto const d = static_cast(d_); auto const era = (y >= 0 ? y : y-399) / 400; auto const yoe = static_cast(y - era * 400); // [0, 399] auto const doy = (153*(m > 2 ? m-3 : m+9) + 2)/5 + d-1; // [0, 365] auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096] return days{era * 146097 + static_cast(doe) - 719468}; } CONSTCD14 inline year_month_day::operator sys_days() const NOEXCEPT { return sys_days{to_days()}; } CONSTCD14 inline year_month_day::operator local_days() const NOEXCEPT { return local_days{to_days()}; } CONSTCD14 inline bool year_month_day::ok() const NOEXCEPT { if (!(y_.ok() && m_.ok())) return false; return date::day{1} <= d_ && d_ <= (y_ / m_ / last).day(); } CONSTCD11 inline bool operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT { return x.year() == y.year() && x.month() == y.month() && x.day() == y.day(); } CONSTCD11 inline bool operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT { return !(x == y); } CONSTCD11 inline bool operator<(const year_month_day& x, const year_month_day& y) NOEXCEPT { return x.year() < y.year() ? true : (x.year() > y.year() ? false : (x.month() < y.month() ? true : (x.month() > y.month() ? false : (x.day() < y.day())))); } CONSTCD11 inline bool operator>(const year_month_day& x, const year_month_day& y) NOEXCEPT { return y < x; } CONSTCD11 inline bool operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT { return !(y < x); } CONSTCD11 inline bool operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT { return !(x < y); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const year_month_day& ymd) { detail::save_ostream _(os); os.fill('0'); os.flags(std::ios::dec | std::ios::right); os << ymd.year() << '-'; os.width(2); os << static_cast(ymd.month()) << '-'; os << ymd.day(); if (!ymd.ok()) os << " is not a valid date"; return os; } CONSTCD14 inline year_month_day year_month_day::from_days(days dp) NOEXCEPT { static_assert(std::numeric_limits::digits >= 18, "This algorithm has not been ported to a 16 bit unsigned integer"); static_assert(std::numeric_limits::digits >= 20, "This algorithm has not been ported to a 16 bit signed integer"); auto const z = dp.count() + 719468; auto const era = (z >= 0 ? z : z - 146096) / 146097; auto const doe = static_cast(z - era * 146097); // [0, 146096] auto const yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399] auto const y = static_cast(yoe) + era * 400; auto const doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365] auto const mp = (5*doy + 2)/153; // [0, 11] auto const d = doy - (153*mp+2)/5 + 1; // [1, 31] auto const m = mp < 10 ? mp+3 : mp-9; // [1, 12] return year_month_day{date::year{y + (m <= 2)}, date::month(m), date::day(d)}; } template CONSTCD14 inline year_month_day operator+(const year_month_day& ymd, const months& dm) NOEXCEPT { return (ymd.year() / ymd.month() + dm) / ymd.day(); } template CONSTCD14 inline year_month_day operator+(const months& dm, const year_month_day& ymd) NOEXCEPT { return ymd + dm; } template CONSTCD14 inline year_month_day operator-(const year_month_day& ymd, const months& dm) NOEXCEPT { return ymd + (-dm); } CONSTCD11 inline year_month_day operator+(const year_month_day& ymd, const years& dy) NOEXCEPT { return (ymd.year() + dy) / ymd.month() / ymd.day(); } CONSTCD11 inline year_month_day operator+(const years& dy, const year_month_day& ymd) NOEXCEPT { return ymd + dy; } CONSTCD11 inline year_month_day operator-(const year_month_day& ymd, const years& dy) NOEXCEPT { return ymd + (-dy); } // year_month_weekday CONSTCD11 inline year_month_weekday::year_month_weekday(const date::year& y, const date::month& m, const date::weekday_indexed& wdi) NOEXCEPT : y_(y) , m_(m) , wdi_(wdi) {} CONSTCD14 inline year_month_weekday::year_month_weekday(const sys_days& dp) NOEXCEPT : year_month_weekday(from_days(dp.time_since_epoch())) {} CONSTCD14 inline year_month_weekday::year_month_weekday(const local_days& dp) NOEXCEPT : year_month_weekday(from_days(dp.time_since_epoch())) {} template CONSTCD14 inline year_month_weekday& year_month_weekday::operator+=(const months& m) NOEXCEPT { *this = *this + m; return *this; } template CONSTCD14 inline year_month_weekday& year_month_weekday::operator-=(const months& m) NOEXCEPT { *this = *this - m; return *this; } CONSTCD14 inline year_month_weekday& year_month_weekday::operator+=(const years& y) NOEXCEPT { *this = *this + y; return *this; } CONSTCD14 inline year_month_weekday& year_month_weekday::operator-=(const years& y) NOEXCEPT { *this = *this - y; return *this; } CONSTCD11 inline year year_month_weekday::year() const NOEXCEPT {return y_;} CONSTCD11 inline month year_month_weekday::month() const NOEXCEPT {return m_;} CONSTCD11 inline weekday year_month_weekday::weekday() const NOEXCEPT { return wdi_.weekday(); } CONSTCD11 inline unsigned year_month_weekday::index() const NOEXCEPT { return wdi_.index(); } CONSTCD11 inline weekday_indexed year_month_weekday::weekday_indexed() const NOEXCEPT { return wdi_; } CONSTCD14 inline year_month_weekday::operator sys_days() const NOEXCEPT { return sys_days{to_days()}; } CONSTCD14 inline year_month_weekday::operator local_days() const NOEXCEPT { return local_days{to_days()}; } CONSTCD14 inline bool year_month_weekday::ok() const NOEXCEPT { if (!y_.ok() || !m_.ok() || !wdi_.weekday().ok() || wdi_.index() < 1) return false; if (wdi_.index() <= 4) return true; auto d2 = wdi_.weekday() - date::weekday(static_cast(y_/m_/1)) + days((wdi_.index()-1)*7 + 1); return static_cast(d2.count()) <= static_cast((y_/m_/last).day()); } CONSTCD14 inline year_month_weekday year_month_weekday::from_days(days d) NOEXCEPT { sys_days dp{d}; auto const wd = date::weekday(dp); auto const ymd = year_month_day(dp); return {ymd.year(), ymd.month(), wd[(static_cast(ymd.day())-1)/7+1]}; } CONSTCD14 inline days year_month_weekday::to_days() const NOEXCEPT { auto d = sys_days(y_/m_/1); return (d + (wdi_.weekday() - date::weekday(d) + days{(wdi_.index()-1)*7}) ).time_since_epoch(); } CONSTCD11 inline bool operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT { return x.year() == y.year() && x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed(); } CONSTCD11 inline bool operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT { return !(x == y); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const year_month_weekday& ymwdi) { return os << ymwdi.year() << '/' << ymwdi.month() << '/' << ymwdi.weekday_indexed(); } template CONSTCD14 inline year_month_weekday operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT { return (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed(); } template CONSTCD14 inline year_month_weekday operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT { return ymwd + dm; } template CONSTCD14 inline year_month_weekday operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT { return ymwd + (-dm); } CONSTCD11 inline year_month_weekday operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT { return {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()}; } CONSTCD11 inline year_month_weekday operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT { return ymwd + dy; } CONSTCD11 inline year_month_weekday operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT { return ymwd + (-dy); } // year_month_weekday_last CONSTCD11 inline year_month_weekday_last::year_month_weekday_last(const date::year& y, const date::month& m, const date::weekday_last& wdl) NOEXCEPT : y_(y) , m_(m) , wdl_(wdl) {} template CONSTCD14 inline year_month_weekday_last& year_month_weekday_last::operator+=(const months& m) NOEXCEPT { *this = *this + m; return *this; } template CONSTCD14 inline year_month_weekday_last& year_month_weekday_last::operator-=(const months& m) NOEXCEPT { *this = *this - m; return *this; } CONSTCD14 inline year_month_weekday_last& year_month_weekday_last::operator+=(const years& y) NOEXCEPT { *this = *this + y; return *this; } CONSTCD14 inline year_month_weekday_last& year_month_weekday_last::operator-=(const years& y) NOEXCEPT { *this = *this - y; return *this; } CONSTCD11 inline year year_month_weekday_last::year() const NOEXCEPT {return y_;} CONSTCD11 inline month year_month_weekday_last::month() const NOEXCEPT {return m_;} CONSTCD11 inline weekday year_month_weekday_last::weekday() const NOEXCEPT { return wdl_.weekday(); } CONSTCD11 inline weekday_last year_month_weekday_last::weekday_last() const NOEXCEPT { return wdl_; } CONSTCD14 inline year_month_weekday_last::operator sys_days() const NOEXCEPT { return sys_days{to_days()}; } CONSTCD14 inline year_month_weekday_last::operator local_days() const NOEXCEPT { return local_days{to_days()}; } CONSTCD11 inline bool year_month_weekday_last::ok() const NOEXCEPT { return y_.ok() && m_.ok() && wdl_.ok(); } CONSTCD14 inline days year_month_weekday_last::to_days() const NOEXCEPT { auto const d = sys_days(y_/m_/last); return (d - (date::weekday{d} - wdl_.weekday())).time_since_epoch(); } CONSTCD11 inline bool operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT { return x.year() == y.year() && x.month() == y.month() && x.weekday_last() == y.weekday_last(); } CONSTCD11 inline bool operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT { return !(x == y); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const year_month_weekday_last& ymwdl) { return os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last(); } template CONSTCD14 inline year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT { return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last(); } template CONSTCD14 inline year_month_weekday_last operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT { return ymwdl + dm; } template CONSTCD14 inline year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT { return ymwdl + (-dm); } CONSTCD11 inline year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT { return {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()}; } CONSTCD11 inline year_month_weekday_last operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT { return ymwdl + dy; } CONSTCD11 inline year_month_weekday_last operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT { return ymwdl + (-dy); } // year_month from operator/() CONSTCD11 inline year_month operator/(const year& y, const month& m) NOEXCEPT { return {y, m}; } CONSTCD11 inline year_month operator/(const year& y, int m) NOEXCEPT { return y / month(static_cast(m)); } // month_day from operator/() CONSTCD11 inline month_day operator/(const month& m, const day& d) NOEXCEPT { return {m, d}; } CONSTCD11 inline month_day operator/(const day& d, const month& m) NOEXCEPT { return m / d; } CONSTCD11 inline month_day operator/(const month& m, int d) NOEXCEPT { return m / day(static_cast(d)); } CONSTCD11 inline month_day operator/(int m, const day& d) NOEXCEPT { return month(static_cast(m)) / d; } CONSTCD11 inline month_day operator/(const day& d, int m) NOEXCEPT {return m / d;} // month_day_last from operator/() CONSTCD11 inline month_day_last operator/(const month& m, last_spec) NOEXCEPT { return month_day_last{m}; } CONSTCD11 inline month_day_last operator/(last_spec, const month& m) NOEXCEPT { return m/last; } CONSTCD11 inline month_day_last operator/(int m, last_spec) NOEXCEPT { return month(static_cast(m))/last; } CONSTCD11 inline month_day_last operator/(last_spec, int m) NOEXCEPT { return m/last; } // month_weekday from operator/() CONSTCD11 inline month_weekday operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT { return {m, wdi}; } CONSTCD11 inline month_weekday operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT { return m / wdi; } CONSTCD11 inline month_weekday operator/(int m, const weekday_indexed& wdi) NOEXCEPT { return month(static_cast(m)) / wdi; } CONSTCD11 inline month_weekday operator/(const weekday_indexed& wdi, int m) NOEXCEPT { return m / wdi; } // month_weekday_last from operator/() CONSTCD11 inline month_weekday_last operator/(const month& m, const weekday_last& wdl) NOEXCEPT { return {m, wdl}; } CONSTCD11 inline month_weekday_last operator/(const weekday_last& wdl, const month& m) NOEXCEPT { return m / wdl; } CONSTCD11 inline month_weekday_last operator/(int m, const weekday_last& wdl) NOEXCEPT { return month(static_cast(m)) / wdl; } CONSTCD11 inline month_weekday_last operator/(const weekday_last& wdl, int m) NOEXCEPT { return m / wdl; } // year_month_day from operator/() CONSTCD11 inline year_month_day operator/(const year_month& ym, const day& d) NOEXCEPT { return {ym.year(), ym.month(), d}; } CONSTCD11 inline year_month_day operator/(const year_month& ym, int d) NOEXCEPT { return ym / day(static_cast(d)); } CONSTCD11 inline year_month_day operator/(const year& y, const month_day& md) NOEXCEPT { return y / md.month() / md.day(); } CONSTCD11 inline year_month_day operator/(int y, const month_day& md) NOEXCEPT { return year(y) / md; } CONSTCD11 inline year_month_day operator/(const month_day& md, const year& y) NOEXCEPT { return y / md; } CONSTCD11 inline year_month_day operator/(const month_day& md, int y) NOEXCEPT { return year(y) / md; } // year_month_day_last from operator/() CONSTCD11 inline year_month_day_last operator/(const year_month& ym, last_spec) NOEXCEPT { return {ym.year(), month_day_last{ym.month()}}; } CONSTCD11 inline year_month_day_last operator/(const year& y, const month_day_last& mdl) NOEXCEPT { return {y, mdl}; } CONSTCD11 inline year_month_day_last operator/(int y, const month_day_last& mdl) NOEXCEPT { return year(y) / mdl; } CONSTCD11 inline year_month_day_last operator/(const month_day_last& mdl, const year& y) NOEXCEPT { return y / mdl; } CONSTCD11 inline year_month_day_last operator/(const month_day_last& mdl, int y) NOEXCEPT { return year(y) / mdl; } // year_month_weekday from operator/() CONSTCD11 inline year_month_weekday operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT { return {ym.year(), ym.month(), wdi}; } CONSTCD11 inline year_month_weekday operator/(const year& y, const month_weekday& mwd) NOEXCEPT { return {y, mwd.month(), mwd.weekday_indexed()}; } CONSTCD11 inline year_month_weekday operator/(int y, const month_weekday& mwd) NOEXCEPT { return year(y) / mwd; } CONSTCD11 inline year_month_weekday operator/(const month_weekday& mwd, const year& y) NOEXCEPT { return y / mwd; } CONSTCD11 inline year_month_weekday operator/(const month_weekday& mwd, int y) NOEXCEPT { return year(y) / mwd; } // year_month_weekday_last from operator/() CONSTCD11 inline year_month_weekday_last operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT { return {ym.year(), ym.month(), wdl}; } CONSTCD11 inline year_month_weekday_last operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT { return {y, mwdl.month(), mwdl.weekday_last()}; } CONSTCD11 inline year_month_weekday_last operator/(int y, const month_weekday_last& mwdl) NOEXCEPT { return year(y) / mwdl; } CONSTCD11 inline year_month_weekday_last operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT { return y / mwdl; } CONSTCD11 inline year_month_weekday_last operator/(const month_weekday_last& mwdl, int y) NOEXCEPT { return year(y) / mwdl; } template struct fields; template std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const fields& fds, const std::string* abbrev = nullptr, const std::chrono::seconds* offset_sec = nullptr); template std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, fields& fds, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr); // time_of_day enum {am = 1, pm}; namespace detail { // width::value is the number of fractional decimal digits in 1/n // width<0>::value and width<1>::value are defined to be 0 // If 1/n takes more than 18 fractional decimal digits, // the result is truncated to 19. // Example: width<2>::value == 1 // Example: width<3>::value == 19 // Example: width<4>::value == 2 // Example: width<10>::value == 1 // Example: width<1000>::value == 3 template struct width { static CONSTDATA unsigned value = 1 + width::value; }; template struct width { static CONSTDATA unsigned value = 0; }; template struct static_pow10 { private: static CONSTDATA std::uint64_t h = static_pow10::value; public: static CONSTDATA std::uint64_t value = h * h * (exp % 2 ? 10 : 1); }; template <> struct static_pow10<0> { static CONSTDATA std::uint64_t value = 1; }; template struct make_precision { using type = std::chrono::duration::value>>; static CONSTDATA unsigned width = w; }; template struct make_precision { using type = std::chrono::duration; static CONSTDATA unsigned width = 6; }; template ::type::period::den>::value> class decimal_format_seconds { public: using rep = typename std::common_type::type::rep; using precision = typename make_precision::type; static auto CONSTDATA width = make_precision::width; private: std::chrono::seconds s_; precision sub_s_; public: CONSTCD11 decimal_format_seconds() : s_() , sub_s_() {} CONSTCD11 explicit decimal_format_seconds(const Duration& d) NOEXCEPT : s_(std::chrono::duration_cast(d)) , sub_s_(std::chrono::duration_cast(d - s_)) {} CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_;} CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_;} CONSTCD11 precision subseconds() const NOEXCEPT {return sub_s_;} CONSTCD14 precision to_duration() const NOEXCEPT { return s_ + sub_s_; } CONSTCD11 bool in_conventional_range() const NOEXCEPT { using namespace std::chrono; return sub_s_ < std::chrono::seconds{1} && s_ < minutes{1}; } template friend std::basic_ostream& operator<<(std::basic_ostream& os, const decimal_format_seconds& x) { date::detail::save_ostream _(os); os.fill('0'); os.flags(std::ios::dec | std::ios::right); os.width(2); os << x.s_.count() << std::use_facet>(os.getloc()).decimal_point(); os.width(width); os << static_cast(x.sub_s_.count()); return os; } }; template class decimal_format_seconds { static CONSTDATA unsigned w = 0; public: using rep = typename std::common_type::type::rep; using precision = std::chrono::duration; static auto CONSTDATA width = make_precision::width; private: std::chrono::seconds s_; public: CONSTCD11 decimal_format_seconds() : s_() {} CONSTCD11 explicit decimal_format_seconds(const precision& s) NOEXCEPT : s_(s) {} CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_;} CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_;} CONSTCD14 precision to_duration() const NOEXCEPT {return s_;} CONSTCD11 bool in_conventional_range() const NOEXCEPT { using namespace std::chrono; return s_ < minutes{1}; } template friend std::basic_ostream& operator<<(std::basic_ostream& os, const decimal_format_seconds& x) { date::detail::save_ostream _(os); os.fill('0'); os.flags(std::ios::dec | std::ios::right); os.width(2); os << x.s_.count(); return os; } }; enum class classify { not_valid, hour, minute, second, subsecond }; template struct classify_duration { static CONSTDATA classify value = std::is_convertible::value ? classify::hour : std::is_convertible::value ? classify::minute : std::is_convertible::value ? classify::second : std::chrono::treat_as_floating_point::value ? classify::not_valid : classify::subsecond; }; template inline CONSTCD11 typename std::enable_if < std::numeric_limits::is_signed, std::chrono::duration >::type abs(std::chrono::duration d) { return d >= d.zero() ? +d : -d; } template inline CONSTCD11 typename std::enable_if < !std::numeric_limits::is_signed, std::chrono::duration >::type abs(std::chrono::duration d) { return d; } class time_of_day_base { protected: std::chrono::hours h_; unsigned char mode_; bool neg_; enum {is24hr}; CONSTCD11 time_of_day_base() NOEXCEPT : h_(0) , mode_(static_cast(is24hr)) , neg_(false) {} CONSTCD11 time_of_day_base(std::chrono::hours h, bool neg, unsigned m) NOEXCEPT : h_(detail::abs(h)) , mode_(static_cast(m)) , neg_(neg) {} CONSTCD14 void make24() NOEXCEPT; CONSTCD14 void make12() NOEXCEPT; CONSTCD14 std::chrono::hours to24hr() const; CONSTCD11 bool in_conventional_range() const NOEXCEPT { return !neg_ && h_ < days{1}; } }; CONSTCD14 inline std::chrono::hours time_of_day_base::to24hr() const { auto h = h_; if (mode_ == am || mode_ == pm) { CONSTDATA auto h12 = std::chrono::hours(12); if (mode_ == pm) { if (h != h12) h = h + h12; } else if (h == h12) h = std::chrono::hours(0); } return h; } CONSTCD14 inline void time_of_day_base::make24() NOEXCEPT { h_ = to24hr(); mode_ = is24hr; } CONSTCD14 inline void time_of_day_base::make12() NOEXCEPT { if (mode_ == is24hr) { CONSTDATA auto h12 = std::chrono::hours(12); if (h_ >= h12) { if (h_ > h12) h_ = h_ - h12; mode_ = pm; } else { if (h_ == std::chrono::hours(0)) h_ = h12; mode_ = am; } } } template ::value> class time_of_day_storage; template class time_of_day_storage, detail::classify::hour> : private detail::time_of_day_base { using base = detail::time_of_day_base; public: using precision = std::chrono::hours; #if !defined(_MSC_VER) || _MSC_VER >= 1900 CONSTCD11 time_of_day_storage() NOEXCEPT = default; #else CONSTCD11 time_of_day_storage() = default; #endif /* !defined(_MSC_VER) || _MSC_VER >= 1900 */ CONSTCD11 explicit time_of_day_storage(std::chrono::hours since_midnight) NOEXCEPT : base(since_midnight, since_midnight < std::chrono::hours{0}, is24hr) {} CONSTCD11 explicit time_of_day_storage(std::chrono::hours h, unsigned md) NOEXCEPT : base(h, h < std::chrono::hours{0}, md) {} CONSTCD11 std::chrono::hours hours() const NOEXCEPT {return h_;} CONSTCD11 unsigned mode() const NOEXCEPT {return mode_;} CONSTCD14 explicit operator precision() const NOEXCEPT { auto p = to24hr(); if (neg_) p = -p; return p; } CONSTCD14 precision to_duration() const NOEXCEPT { return static_cast(*this); } CONSTCD14 time_of_day_storage& make24() NOEXCEPT {base::make24(); return *this;} CONSTCD14 time_of_day_storage& make12() NOEXCEPT {base::make12(); return *this;} CONSTCD11 bool in_conventional_range() const NOEXCEPT { return base::in_conventional_range(); } template friend std::basic_ostream& operator<<(std::basic_ostream& os, const time_of_day_storage& t) { using namespace std; detail::save_ostream _(os); if (t.neg_) os << '-'; os.fill('0'); os.flags(std::ios::dec | std::ios::right); if (t.mode_ != am && t.mode_ != pm) os.width(2); os << t.h_.count(); switch (t.mode_) { case time_of_day_storage::is24hr: os << "00"; break; case am: os << "am"; break; case pm: os << "pm"; break; } return os; } }; template class time_of_day_storage, detail::classify::minute> : private detail::time_of_day_base { using base = detail::time_of_day_base; std::chrono::minutes m_; public: using precision = std::chrono::minutes; CONSTCD11 time_of_day_storage() NOEXCEPT : base() , m_(0) {} CONSTCD11 explicit time_of_day_storage(std::chrono::minutes since_midnight) NOEXCEPT : base(std::chrono::duration_cast(since_midnight), since_midnight < std::chrono::minutes{0}, is24hr) , m_(detail::abs(since_midnight) - h_) {} CONSTCD11 explicit time_of_day_storage(std::chrono::hours h, std::chrono::minutes m, unsigned md) NOEXCEPT : base(h, false, md) , m_(m) {} CONSTCD11 std::chrono::hours hours() const NOEXCEPT {return h_;} CONSTCD11 std::chrono::minutes minutes() const NOEXCEPT {return m_;} CONSTCD11 unsigned mode() const NOEXCEPT {return mode_;} CONSTCD14 explicit operator precision() const NOEXCEPT { auto p = to24hr() + m_; if (neg_) p = -p; return p; } CONSTCD14 precision to_duration() const NOEXCEPT { return static_cast(*this); } CONSTCD14 time_of_day_storage& make24() NOEXCEPT {base::make24(); return *this;} CONSTCD14 time_of_day_storage& make12() NOEXCEPT {base::make12(); return *this;} CONSTCD11 bool in_conventional_range() const NOEXCEPT { return base::in_conventional_range() && m_ < std::chrono::hours{1}; } template friend std::basic_ostream& operator<<(std::basic_ostream& os, const time_of_day_storage& t) { using namespace std; detail::save_ostream _(os); if (t.neg_) os << '-'; os.fill('0'); os.flags(std::ios::dec | std::ios::right); if (t.mode_ != am && t.mode_ != pm) os.width(2); os << t.h_.count() << ':'; os.width(2); os << t.m_.count(); switch (t.mode_) { case am: os << "am"; break; case pm: os << "pm"; break; } return os; } }; template class time_of_day_storage, detail::classify::second> : private detail::time_of_day_base { using base = detail::time_of_day_base; using dfs = decimal_format_seconds; std::chrono::minutes m_; dfs s_; public: using precision = std::chrono::seconds; CONSTCD11 time_of_day_storage() NOEXCEPT : base() , m_(0) , s_() {} CONSTCD11 explicit time_of_day_storage(std::chrono::seconds since_midnight) NOEXCEPT : base(std::chrono::duration_cast(since_midnight), since_midnight < std::chrono::seconds{0}, is24hr) , m_(std::chrono::duration_cast(detail::abs(since_midnight) - h_)) , s_(detail::abs(since_midnight) - h_ - m_) {} CONSTCD11 explicit time_of_day_storage(std::chrono::hours h, std::chrono::minutes m, std::chrono::seconds s, unsigned md) NOEXCEPT : base(h, false, md) , m_(m) , s_(s) {} CONSTCD11 std::chrono::hours hours() const NOEXCEPT {return h_;} CONSTCD11 std::chrono::minutes minutes() const NOEXCEPT {return m_;} CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_.seconds();} CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_.seconds();} CONSTCD11 unsigned mode() const NOEXCEPT {return mode_;} CONSTCD14 explicit operator precision() const NOEXCEPT { auto p = to24hr() + s_.to_duration() + m_; if (neg_) p = -p; return p; } CONSTCD14 precision to_duration() const NOEXCEPT { return static_cast(*this); } CONSTCD14 time_of_day_storage& make24() NOEXCEPT {base::make24(); return *this;} CONSTCD14 time_of_day_storage& make12() NOEXCEPT {base::make12(); return *this;} CONSTCD11 bool in_conventional_range() const NOEXCEPT { return base::in_conventional_range() && m_ < std::chrono::hours{1} && s_.in_conventional_range(); } template friend std::basic_ostream& operator<<(std::basic_ostream& os, const time_of_day_storage& t) { using namespace std; detail::save_ostream _(os); if (t.neg_) os << '-'; os.fill('0'); os.flags(std::ios::dec | std::ios::right); if (t.mode_ != am && t.mode_ != pm) os.width(2); os << t.h_.count() << ':'; os.width(2); os << t.m_.count() << ':' << t.s_; switch (t.mode_) { case am: os << "am"; break; case pm: os << "pm"; break; } return os; } template friend std::basic_ostream& date::to_stream(std::basic_ostream& os, const CharT* fmt, const fields& fds, const std::string* abbrev, const std::chrono::seconds* offset_sec); template friend std::basic_istream& date::from_stream(std::basic_istream& is, const CharT* fmt, fields& fds, std::basic_string* abbrev, std::chrono::minutes* offset); }; template class time_of_day_storage, detail::classify::subsecond> : private detail::time_of_day_base { public: using Duration = std::chrono::duration; using dfs = decimal_format_seconds::type>; using precision = typename dfs::precision; private: using base = detail::time_of_day_base; std::chrono::minutes m_; dfs s_; public: CONSTCD11 time_of_day_storage() NOEXCEPT : base() , m_(0) , s_() {} CONSTCD11 explicit time_of_day_storage(Duration since_midnight) NOEXCEPT : base(date::trunc(since_midnight), since_midnight < Duration{0}, is24hr) , m_(date::trunc(detail::abs(since_midnight) - h_)) , s_(detail::abs(since_midnight) - h_ - m_) {} CONSTCD11 explicit time_of_day_storage(std::chrono::hours h, std::chrono::minutes m, std::chrono::seconds s, precision sub_s, unsigned md) NOEXCEPT : base(h, false, md) , m_(m) , s_(s + sub_s) {} CONSTCD11 std::chrono::hours hours() const NOEXCEPT {return h_;} CONSTCD11 std::chrono::minutes minutes() const NOEXCEPT {return m_;} CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_.seconds();} CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_.seconds();} CONSTCD11 precision subseconds() const NOEXCEPT {return s_.subseconds();} CONSTCD11 unsigned mode() const NOEXCEPT {return mode_;} CONSTCD14 explicit operator precision() const NOEXCEPT { auto p = to24hr() + s_.to_duration() + m_; if (neg_) p = -p; return p; } CONSTCD14 precision to_duration() const NOEXCEPT { return static_cast(*this); } CONSTCD14 time_of_day_storage& make24() NOEXCEPT {base::make24(); return *this;} CONSTCD14 time_of_day_storage& make12() NOEXCEPT {base::make12(); return *this;} CONSTCD11 bool in_conventional_range() const NOEXCEPT { return base::in_conventional_range() && m_ < std::chrono::hours{1} && s_.in_conventional_range(); } template friend std::basic_ostream& operator<<(std::basic_ostream& os, const time_of_day_storage& t) { using namespace std; detail::save_ostream _(os); if (t.neg_) os << '-'; os.fill('0'); os.flags(std::ios::dec | std::ios::right); if (t.mode_ != am && t.mode_ != pm) os.width(2); os << t.h_.count() << ':'; os.width(2); os << t.m_.count() << ':' << t.s_; switch (t.mode_) { case am: os << "am"; break; case pm: os << "pm"; break; } return os; } template friend std::basic_ostream& date::to_stream(std::basic_ostream& os, const CharT* fmt, const fields& fds, const std::string* abbrev, const std::chrono::seconds* offset_sec); template friend std::basic_istream& date::from_stream(std::basic_istream& is, const CharT* fmt, fields& fds, std::basic_string* abbrev, std::chrono::minutes* offset); }; } // namespace detail template class time_of_day : public detail::time_of_day_storage { using base = detail::time_of_day_storage; public: #if !defined(_MSC_VER) || _MSC_VER >= 1900 CONSTCD11 time_of_day() NOEXCEPT = default; #else CONSTCD11 time_of_day() = default; #endif /* !defined(_MSC_VER) || _MSC_VER >= 1900 */ CONSTCD11 explicit time_of_day(Duration since_midnight) NOEXCEPT : base(since_midnight) {} template CONSTCD11 explicit time_of_day(Arg0&& arg0, Arg1&& arg1, Args&& ...args) NOEXCEPT : base(std::forward(arg0), std::forward(arg1), std::forward(args)...) {} }; template ::value>::type> CONSTCD11 inline time_of_day> make_time(const std::chrono::duration& d) { return time_of_day>(d); } CONSTCD11 inline time_of_day make_time(const std::chrono::hours& h, unsigned md) { return time_of_day(h, md); } CONSTCD11 inline time_of_day make_time(const std::chrono::hours& h, const std::chrono::minutes& m, unsigned md) { return time_of_day(h, m, md); } CONSTCD11 inline time_of_day make_time(const std::chrono::hours& h, const std::chrono::minutes& m, const std::chrono::seconds& s, unsigned md) { return time_of_day(h, m, s, md); } template >::value>::type> CONSTCD11 inline time_of_day> make_time(const std::chrono::hours& h, const std::chrono::minutes& m, const std::chrono::seconds& s, const std::chrono::duration& sub_s, unsigned md) { return time_of_day>(h, m, s, sub_s, md); } template inline typename std::enable_if < !std::chrono::treat_as_floating_point::value && std::ratio_less::value , std::basic_ostream& >::type operator<<(std::basic_ostream& os, const sys_time& tp) { auto const dp = date::floor(tp); return os << year_month_day(dp) << ' ' << make_time(tp-dp); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const sys_days& dp) { return os << year_month_day(dp); } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const local_time& ut) { return (os << sys_time{ut.time_since_epoch()}); } // to_stream CONSTDATA year nanyear{-32768}; template struct fields { year_month_day ymd{nanyear/0/0}; weekday wd{8u}; time_of_day tod{}; bool has_tod = false; fields() = default; fields(year_month_day ymd_) : ymd(ymd_) {} fields(weekday wd_) : wd(wd_) {} fields(time_of_day tod_) : tod(tod_), has_tod(true) {} fields(year_month_day ymd_, weekday wd_) : ymd(ymd_), wd(wd_) {} fields(year_month_day ymd_, time_of_day tod_) : ymd(ymd_), tod(tod_), has_tod(true) {} fields(weekday wd_, time_of_day tod_) : wd(wd_), tod(tod_), has_tod(true) {} fields(year_month_day ymd_, weekday wd_, time_of_day tod_) : ymd(ymd_) , wd(wd_) , tod(tod_) , has_tod(true) {} }; namespace detail { template unsigned extract_weekday(std::basic_ostream& os, const fields& fds) { if (!fds.ymd.ok() && !fds.wd.ok()) { // fds does not contain a valid weekday os.setstate(std::ios::failbit); return 8; } weekday wd; if (fds.ymd.ok()) { wd = weekday{sys_days(fds.ymd)}; if (fds.wd.ok() && wd != fds.wd) { // fds.ymd and fds.wd are inconsistent os.setstate(std::ios::failbit); return 8; } } else wd = fds.wd; return static_cast((wd - Sunday).count()); } template unsigned extract_month(std::basic_ostream& os, const fields& fds) { if (!fds.ymd.month().ok()) { // fds does not contain a valid month os.setstate(std::ios::failbit); return 0; } return static_cast(fds.ymd.month()); } } // namespace detail #if ONLY_C_LOCALE namespace detail { inline std::pair weekday_names() { static const std::string nm[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); } inline std::pair month_names() { static const std::string nm[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); } inline std::pair ampm_names() { static const std::string nm[] = { "AM", "PM" }; return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); } template FwdIter scan_keyword(std::basic_istream& is, FwdIter kb, FwdIter ke) { using namespace std; size_t nkw = static_cast(std::distance(kb, ke)); const unsigned char doesnt_match = '\0'; const unsigned char might_match = '\1'; const unsigned char does_match = '\2'; unsigned char statbuf[100]; unsigned char* status = statbuf; unique_ptr stat_hold(0, free); if (nkw > sizeof(statbuf)) { status = (unsigned char*)malloc(nkw); if (status == nullptr) throw bad_alloc(); stat_hold.reset(status); } size_t n_might_match = nkw; // At this point, any keyword might match size_t n_does_match = 0; // but none of them definitely do // Initialize all statuses to might_match, except for "" keywords are does_match unsigned char* st = status; for (auto ky = kb; ky != ke; ++ky, ++st) { if (!ky->empty()) *st = might_match; else { *st = does_match; --n_might_match; ++n_does_match; } } // While there might be a match, test keywords against the next CharT for (size_t indx = 0; is && n_might_match > 0; ++indx) { // Peek at the next CharT but don't consume it auto ic = is.peek(); if (ic == EOF) { is.setstate(ios::eofbit); break; } auto c = static_cast(toupper(ic)); bool consume = false; // For each keyword which might match, see if the indx character is c // If a match if found, consume c // If a match is found, and that is the last character in the keyword, // then that keyword matches. // If the keyword doesn't match this character, then change the keyword // to doesn't match st = status; for (auto ky = kb; ky != ke; ++ky, ++st) { if (*st == might_match) { if (c == static_cast(toupper((*ky)[indx]))) { consume = true; if (ky->size() == indx+1) { *st = does_match; --n_might_match; ++n_does_match; } } else { *st = doesnt_match; --n_might_match; } } } // consume if we matched a character if (consume) { (void)is.get(); // If we consumed a character and there might be a matched keyword that // was marked matched on a previous iteration, then such keywords // are now marked as not matching. if (n_might_match + n_does_match > 1) { st = status; for (auto ky = kb; ky != ke; ++ky, ++st) { if (*st == does_match && ky->size() != indx+1) { *st = doesnt_match; --n_does_match; } } } } } // We've exited the loop because we hit eof and/or we have no more "might matches". // Return the first matching result for (st = status; kb != ke; ++kb, ++st) if (*st == does_match) break; if (kb == ke) is.setstate(ios_base::failbit); return kb; } } // namespace detail #endif // ONLY_C_LOCALE template std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const fields& fds, const std::string* abbrev, const std::chrono::seconds* offset_sec) { using namespace std; using namespace std::chrono; using namespace detail; date::detail::save_ostream ss(os); os.fill(' '); os.flags(std::ios::skipws | std::ios::dec); os.width(0); tm tm{}; bool insert_negative = fds.has_tod && fds.tod.to_duration() < Duration::zero(); #if !ONLY_C_LOCALE auto& facet = use_facet>(os.getloc()); #endif const CharT* command = nullptr; CharT modified = CharT{}; for (; *fmt; ++fmt) { switch (*fmt) { case 'a': case 'A': if (command) { if (modified == CharT{}) { tm.tm_wday = static_cast(extract_weekday(os, fds)); if (os.fail()) return os; #if !ONLY_C_LOCALE const CharT f[] = {'%', *fmt}; facet.put(os, os, os.fill(), &tm, begin(f), end(f)); #else // ONLY_C_LOCALE os << weekday_names().first[tm.tm_wday+7*(*fmt == 'a')]; #endif // ONLY_C_LOCALE } else { os << CharT{'%'} << modified << *fmt; modified = CharT{}; } command = nullptr; } else os << *fmt; break; case 'b': case 'B': case 'h': if (command) { if (modified == CharT{}) { tm.tm_mon = static_cast(extract_month(os, fds)) - 1; #if !ONLY_C_LOCALE const CharT f[] = {'%', *fmt}; facet.put(os, os, os.fill(), &tm, begin(f), end(f)); #else // ONLY_C_LOCALE os << month_names().first[tm.tm_mon+12*(*fmt != 'B')]; #endif // ONLY_C_LOCALE } else { os << CharT{'%'} << modified << *fmt; modified = CharT{}; } command = nullptr; } else os << *fmt; break; case 'c': case 'x': if (command) { if (modified == CharT{'O'}) os << CharT{'%'} << modified << *fmt; else { if (!fds.ymd.ok()) os.setstate(std::ios::failbit); if (*fmt == 'c' && !fds.has_tod) os.setstate(std::ios::failbit); #if !ONLY_C_LOCALE tm = std::tm{}; auto const& ymd = fds.ymd; auto ld = local_days(ymd); if (*fmt == 'c') { tm.tm_sec = static_cast(fds.tod.seconds().count()); tm.tm_min = static_cast(fds.tod.minutes().count()); tm.tm_hour = static_cast(fds.tod.hours().count()); } tm.tm_mday = static_cast(static_cast(ymd.day())); tm.tm_mon = static_cast(extract_month(os, fds) - 1); tm.tm_year = static_cast(ymd.year()) - 1900; tm.tm_wday = static_cast(extract_weekday(os, fds)); if (os.fail()) return os; tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); CharT f[3] = {'%'}; auto fe = begin(f) + 1; if (modified == CharT{'E'}) *fe++ = modified; *fe++ = *fmt; facet.put(os, os, os.fill(), &tm, begin(f), fe); #else // ONLY_C_LOCALE if (*fmt == 'c') { auto wd = static_cast(extract_weekday(os, fds)); os << weekday_names().first[static_cast(wd)+7] << ' '; os << month_names().first[extract_month(os, fds)-1+12] << ' '; auto d = static_cast(static_cast(fds.ymd.day())); if (d < 10) os << ' '; os << d << ' ' << make_time(duration_cast(fds.tod.to_duration())) << ' ' << fds.ymd.year(); } else // *fmt == 'x' { auto const& ymd = fds.ymd; save_ostream _(os); os.fill('0'); os.flags(std::ios::dec | std::ios::right); os.width(2); os << static_cast(ymd.month()) << CharT{'/'}; os.width(2); os << static_cast(ymd.day()) << CharT{'/'}; os.width(2); os << static_cast(ymd.year()) % 100; } #endif // ONLY_C_LOCALE } command = nullptr; modified = CharT{}; } else os << *fmt; break; case 'C': if (command) { if (modified == CharT{'O'}) os << CharT{'%'} << modified << *fmt; else { if (!fds.ymd.year().ok()) os.setstate(std::ios::failbit); auto y = static_cast(fds.ymd.year()); #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { save_ostream _(os); os.fill('0'); os.flags(std::ios::dec | std::ios::right); if (y >= 0) { os.width(2); os << y/100; } else { os << CharT{'-'}; os.width(2); os << -(y-99)/100; } } #if !ONLY_C_LOCALE else if (modified == CharT{'E'}) { tm.tm_year = y - 1900; CharT f[3] = {'%', 'E', 'C'}; facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif } command = nullptr; modified = CharT{}; } else os << *fmt; break; case 'd': case 'e': if (command) { if (modified == CharT{'E'}) os << CharT{'%'} << modified << *fmt; else { if (!fds.ymd.day().ok()) os.setstate(std::ios::failbit); auto d = static_cast(static_cast(fds.ymd.day())); #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { save_ostream _(os); if (*fmt == CharT{'d'}) os.fill('0'); else os.fill(' '); os.flags(std::ios::dec | std::ios::right); os.width(2); os << d; } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { tm.tm_mday = d; CharT f[3] = {'%', 'O', *fmt}; facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif } command = nullptr; modified = CharT{}; } else os << *fmt; break; case 'D': if (command) { if (modified == CharT{}) { if (!fds.ymd.ok()) os.setstate(std::ios::failbit); auto const& ymd = fds.ymd; save_ostream _(os); os.fill('0'); os.flags(std::ios::dec | std::ios::right); os.width(2); os << static_cast(ymd.month()) << CharT{'/'}; os.width(2); os << static_cast(ymd.day()) << CharT{'/'}; os.width(2); os << static_cast(ymd.year()) % 100; } else { os << CharT{'%'} << modified << *fmt; modified = CharT{}; } command = nullptr; } else os << *fmt; break; case 'F': if (command) { if (modified == CharT{}) { if (!fds.ymd.ok()) os.setstate(std::ios::failbit); auto const& ymd = fds.ymd; save_ostream _(os); os.fill('0'); os.flags(std::ios::dec | std::ios::right); os.width(4); os << static_cast(ymd.year()) << CharT{'-'}; os.width(2); os << static_cast(ymd.month()) << CharT{'-'}; os.width(2); os << static_cast(ymd.day()); } else { os << CharT{'%'} << modified << *fmt; modified = CharT{}; } command = nullptr; } else os << *fmt; break; case 'g': case 'G': if (command) { if (modified == CharT{}) { if (!fds.ymd.ok()) os.setstate(std::ios::failbit); auto ld = local_days(fds.ymd); auto y = year_month_day{ld + days{3}}.year(); auto start = local_days((y-years{1})/December/Thursday[last]) + (Monday-Thursday); if (ld < start) --y; if (*fmt == CharT{'G'}) os << y; else { save_ostream _(os); os.fill('0'); os.flags(std::ios::dec | std::ios::right); os.width(2); os << std::abs(static_cast(y)) % 100; } } else { os << CharT{'%'} << modified << *fmt; modified = CharT{}; } command = nullptr; } else os << *fmt; break; case 'H': case 'I': if (command) { if (modified == CharT{'E'}) os << CharT{'%'} << modified << *fmt; else { if (!fds.has_tod) os.setstate(std::ios::failbit); if (insert_negative) { os << '-'; insert_negative = false; } auto hms = fds.tod; #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { if (*fmt == CharT{'I'}) hms.make12(); if (hms.hours() < hours{10}) os << CharT{'0'}; os << hms.hours().count(); } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { const CharT f[] = {'%', modified, *fmt}; tm.tm_hour = static_cast(hms.hours().count()); facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'j': if (command) { if (modified == CharT{}) { if (fds.ymd.ok() || fds.has_tod) { days doy; if (fds.ymd.ok()) { auto ld = local_days(fds.ymd); auto y = fds.ymd.year(); doy = ld - local_days(y/January/1) + days{1}; } else { doy = duration_cast(fds.tod.to_duration()); } save_ostream _(os); os.fill('0'); os.flags(std::ios::dec | std::ios::right); os.width(3); os << doy.count(); } else { os.setstate(std::ios::failbit); } } else { os << CharT{'%'} << modified << *fmt; modified = CharT{}; } command = nullptr; } else os << *fmt; break; case 'm': if (command) { if (modified == CharT{'E'}) os << CharT{'%'} << modified << *fmt; else { if (!fds.ymd.month().ok()) os.setstate(std::ios::failbit); auto m = static_cast(fds.ymd.month()); #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { if (m < 10) os << CharT{'0'}; os << m; } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { const CharT f[] = {'%', modified, *fmt}; tm.tm_mon = static_cast(m-1); facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'M': if (command) { if (modified == CharT{'E'}) os << CharT{'%'} << modified << *fmt; else { if (!fds.has_tod) os.setstate(std::ios::failbit); if (insert_negative) { os << '-'; insert_negative = false; } #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { if (fds.tod.minutes() < minutes{10}) os << CharT{'0'}; os << fds.tod.minutes().count(); } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { const CharT f[] = {'%', modified, *fmt}; tm.tm_min = static_cast(fds.tod.minutes().count()); facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'n': if (command) { if (modified == CharT{}) os << CharT{'\n'}; else { os << CharT{'%'} << modified << *fmt; modified = CharT{}; } command = nullptr; } else os << *fmt; break; case 'p': if (command) { if (modified == CharT{}) { if (!fds.has_tod) os.setstate(std::ios::failbit); #if !ONLY_C_LOCALE const CharT f[] = {'%', *fmt}; tm.tm_hour = static_cast(fds.tod.hours().count()); facet.put(os, os, os.fill(), &tm, begin(f), end(f)); #else if (fds.tod.hours() < hours{12}) os << ampm_names().first[0]; else os << ampm_names().first[1]; #endif } else { os << CharT{'%'} << modified << *fmt; } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'r': if (command) { if (modified == CharT{}) { if (!fds.has_tod) os.setstate(std::ios::failbit); #if !ONLY_C_LOCALE const CharT f[] = {'%', *fmt}; tm.tm_hour = static_cast(fds.tod.hours().count()); tm.tm_min = static_cast(fds.tod.minutes().count()); tm.tm_sec = static_cast(fds.tod.seconds().count()); facet.put(os, os, os.fill(), &tm, begin(f), end(f)); #else time_of_day tod(duration_cast(fds.tod.to_duration())); tod.make12(); save_ostream _(os); os.fill('0'); os.width(2); os << tod.hours().count() << CharT{':'}; os.width(2); os << tod.minutes().count() << CharT{':'}; os.width(2); os << tod.seconds().count() << CharT{' '}; tod.make24(); if (tod.hours() < hours{12}) os << ampm_names().first[0]; else os << ampm_names().first[1]; #endif } else { os << CharT{'%'} << modified << *fmt; } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'R': if (command) { if (modified == CharT{}) { if (!fds.has_tod) os.setstate(std::ios::failbit); if (fds.tod.hours() < hours{10}) os << CharT{'0'}; os << fds.tod.hours().count() << CharT{':'}; if (fds.tod.minutes() < minutes{10}) os << CharT{'0'}; os << fds.tod.minutes().count(); } else { os << CharT{'%'} << modified << *fmt; modified = CharT{}; } command = nullptr; } else os << *fmt; break; case 'S': if (command) { if (modified == CharT{'E'}) os << CharT{'%'} << modified << *fmt; else { if (!fds.has_tod) os.setstate(std::ios::failbit); if (insert_negative) { os << '-'; insert_negative = false; } #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { os << fds.tod.s_; } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { const CharT f[] = {'%', modified, *fmt}; tm.tm_sec = static_cast(fds.tod.s_.seconds().count()); facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 't': if (command) { if (modified == CharT{}) os << CharT{'\t'}; else { os << CharT{'%'} << modified << *fmt; modified = CharT{}; } command = nullptr; } else os << *fmt; break; case 'T': if (command) { if (modified == CharT{}) { if (!fds.has_tod) os.setstate(std::ios::failbit); os << fds.tod; } else { os << CharT{'%'} << modified << *fmt; modified = CharT{}; } command = nullptr; } else os << *fmt; break; case 'u': if (command) { if (modified == CharT{'E'}) os << CharT{'%'} << modified << *fmt; else { auto wd = extract_weekday(os, fds); #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { os << (wd != 0 ? wd : 7u); } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { const CharT f[] = {'%', modified, *fmt}; tm.tm_wday = static_cast(wd); facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'U': if (command) { if (modified == CharT{'E'}) os << CharT{'%'} << modified << *fmt; else { auto const& ymd = fds.ymd; if (!ymd.ok()) os.setstate(std::ios::failbit); auto ld = local_days(ymd); #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { auto st = local_days(Sunday[1]/January/ymd.year()); if (ld < st) os << CharT{'0'} << CharT{'0'}; else { auto wn = duration_cast(ld - st).count() + 1; if (wn < 10) os << CharT{'0'}; os << wn; } } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { const CharT f[] = {'%', modified, *fmt}; tm.tm_year = static_cast(ymd.year()) - 1900; tm.tm_wday = static_cast(extract_weekday(os, fds)); if (os.fail()) return os; tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'V': if (command) { if (modified == CharT{'E'}) os << CharT{'%'} << modified << *fmt; else { if (!fds.ymd.ok()) os.setstate(std::ios::failbit); auto ld = local_days(fds.ymd); #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { auto y = year_month_day{ld + days{3}}.year(); auto st = local_days((y-years{1})/12/Thursday[last]) + (Monday-Thursday); if (ld < st) { --y; st = local_days((y - years{1})/12/Thursday[last]) + (Monday-Thursday); } auto wn = duration_cast(ld - st).count() + 1; if (wn < 10) os << CharT{'0'}; os << wn; } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { const CharT f[] = {'%', modified, *fmt}; auto const& ymd = fds.ymd; tm.tm_year = static_cast(ymd.year()) - 1900; tm.tm_wday = static_cast(extract_weekday(os, fds)); if (os.fail()) return os; tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'w': if (command) { auto wd = extract_weekday(os, fds); if (os.fail()) return os; #if !ONLY_C_LOCALE if (modified == CharT{}) #else if (modified != CharT{'E'}) #endif { os << wd; } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { const CharT f[] = {'%', modified, *fmt}; tm.tm_wday = static_cast(wd); facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif else { os << CharT{'%'} << modified << *fmt; } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'W': if (command) { if (modified == CharT{'E'}) os << CharT{'%'} << modified << *fmt; else { auto const& ymd = fds.ymd; if (!ymd.ok()) os.setstate(std::ios::failbit); auto ld = local_days(ymd); #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { auto st = local_days(Monday[1]/January/ymd.year()); if (ld < st) os << CharT{'0'} << CharT{'0'}; else { auto wn = duration_cast(ld - st).count() + 1; if (wn < 10) os << CharT{'0'}; os << wn; } } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { const CharT f[] = {'%', modified, *fmt}; tm.tm_year = static_cast(ymd.year()) - 1900; tm.tm_wday = static_cast(extract_weekday(os, fds)); if (os.fail()) return os; tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'X': if (command) { if (modified == CharT{'O'}) os << CharT{'%'} << modified << *fmt; else { if (!fds.has_tod) os.setstate(std::ios::failbit); #if !ONLY_C_LOCALE tm = std::tm{}; tm.tm_sec = static_cast(fds.tod.seconds().count()); tm.tm_min = static_cast(fds.tod.minutes().count()); tm.tm_hour = static_cast(fds.tod.hours().count()); CharT f[3] = {'%'}; auto fe = begin(f) + 1; if (modified == CharT{'E'}) *fe++ = modified; *fe++ = *fmt; facet.put(os, os, os.fill(), &tm, begin(f), fe); #else os << fds.tod; #endif } command = nullptr; modified = CharT{}; } else os << *fmt; break; case 'y': if (command) { if (!fds.ymd.year().ok()) os.setstate(std::ios::failbit); auto y = static_cast(fds.ymd.year()); #if !ONLY_C_LOCALE if (modified == CharT{}) { #endif y = std::abs(y) % 100; if (y < 10) os << CharT{'0'}; os << y; #if !ONLY_C_LOCALE } else { const CharT f[] = {'%', modified, *fmt}; tm.tm_year = y - 1900; facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'Y': if (command) { if (modified == CharT{'O'}) os << CharT{'%'} << modified << *fmt; else { if (!fds.ymd.year().ok()) os.setstate(std::ios::failbit); auto y = fds.ymd.year(); #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { os << y; } #if !ONLY_C_LOCALE else if (modified == CharT{'E'}) { const CharT f[] = {'%', modified, *fmt}; tm.tm_year = static_cast(y) - 1900; facet.put(os, os, os.fill(), &tm, begin(f), end(f)); } #endif } modified = CharT{}; command = nullptr; } else os << *fmt; break; case 'z': if (command) { if (offset_sec == nullptr) { // Can not format %z with unknown offset os.setstate(ios::failbit); return os; } auto m = duration_cast(*offset_sec); auto neg = m < minutes{0}; m = date::abs(m); auto h = duration_cast(m); m -= h; if (neg) os << CharT{'-'}; else os << CharT{'+'}; if (h < hours{10}) os << CharT{'0'}; os << h.count(); if (modified != CharT{}) os << CharT{':'}; if (m < minutes{10}) os << CharT{'0'}; os << m.count(); command = nullptr; modified = CharT{}; } else os << *fmt; break; case 'Z': if (command) { if (modified == CharT{}) { if (abbrev == nullptr) { // Can not format %Z with unknown time_zone os.setstate(ios::failbit); return os; } for (auto c : *abbrev) os << CharT(c); } else { os << CharT{'%'} << modified << *fmt; modified = CharT{}; } command = nullptr; } else os << *fmt; break; case 'E': case 'O': if (command) { if (modified == CharT{}) { modified = *fmt; } else { os << CharT{'%'} << modified << *fmt; command = nullptr; modified = CharT{}; } } else os << *fmt; break; case '%': if (command) { if (modified == CharT{}) { os << CharT{'%'}; command = nullptr; } else { os << CharT{'%'} << modified << CharT{'%'}; command = nullptr; modified = CharT{}; } } else command = fmt; break; default: if (command) { os << CharT{'%'}; command = nullptr; } if (modified != CharT{}) { os << modified; modified = CharT{}; } os << *fmt; break; } } if (command) os << CharT{'%'}; if (modified != CharT{}) os << modified; return os; } template inline std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const year& y) { using CT = std::chrono::seconds; fields fds{y/0/0}; return to_stream(os, fmt, fds); } template inline std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const month& m) { using CT = std::chrono::seconds; fields fds{m/0/nanyear}; return to_stream(os, fmt, fds); } template inline std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const day& d) { using CT = std::chrono::seconds; fields fds{d/0/nanyear}; return to_stream(os, fmt, fds); } template inline std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const weekday& wd) { using CT = std::chrono::seconds; fields fds{wd}; return to_stream(os, fmt, fds); } template inline std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const year_month& ym) { using CT = std::chrono::seconds; fields fds{ym/0}; return to_stream(os, fmt, fds); } template inline std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const month_day& md) { using CT = std::chrono::seconds; fields fds{md/nanyear}; return to_stream(os, fmt, fds); } template inline std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const year_month_day& ymd) { using CT = std::chrono::seconds; fields fds{ymd}; return to_stream(os, fmt, fds); } template inline std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const std::chrono::duration& d) { using Duration = std::chrono::duration; using CT = typename std::common_type::type; fields fds{time_of_day{d}}; return to_stream(os, fmt, fds); } template std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const local_time& tp, const std::string* abbrev = nullptr, const std::chrono::seconds* offset_sec = nullptr) { using CT = typename std::common_type::type; auto ld = floor(tp); fields fds{year_month_day{ld}, time_of_day{tp-local_seconds{ld}}}; return to_stream(os, fmt, fds, abbrev, offset_sec); } template std::basic_ostream& to_stream(std::basic_ostream& os, const CharT* fmt, const sys_time& tp) { using namespace std::chrono; using CT = typename std::common_type::type; const std::string abbrev("UTC"); CONSTDATA seconds offset{0}; auto sd = floor(tp); fields fds{year_month_day{sd}, time_of_day{tp-sys_seconds{sd}}}; return to_stream(os, fmt, fds, &abbrev, &offset); } // format template auto format(const std::locale& loc, const CharT* fmt, const Streamable& tp) -> decltype(to_stream(std::declval&>(), fmt, tp), std::basic_string{}) { std::basic_ostringstream os; os.exceptions(std::ios::failbit | std::ios::badbit); os.imbue(loc); to_stream(os, fmt, tp); return os.str(); } template auto format(const CharT* fmt, const Streamable& tp) -> decltype(to_stream(std::declval&>(), fmt, tp), std::basic_string{}) { std::basic_ostringstream os; os.exceptions(std::ios::failbit | std::ios::badbit); to_stream(os, fmt, tp); return os.str(); } template auto format(const std::locale& loc, const std::basic_string& fmt, const Streamable& tp) -> decltype(to_stream(std::declval&>(), fmt.c_str(), tp), std::basic_string{}) { std::basic_ostringstream os; os.exceptions(std::ios::failbit | std::ios::badbit); os.imbue(loc); to_stream(os, fmt.c_str(), tp); return os.str(); } template auto format(const std::basic_string& fmt, const Streamable& tp) -> decltype(to_stream(std::declval&>(), fmt.c_str(), tp), std::basic_string{}) { std::basic_ostringstream os; os.exceptions(std::ios::failbit | std::ios::badbit); to_stream(os, fmt.c_str(), tp); return os.str(); } // parse namespace detail { template bool read_char(std::basic_istream& is, CharT fmt, std::ios::iostate& err) { auto ic = is.get(); if (Traits::eq_int_type(ic, Traits::eof()) || !Traits::eq(Traits::to_char_type(ic), fmt)) { err |= std::ios::failbit; is.setstate(std::ios::failbit); return false; } return true; } template unsigned read_unsigned(std::basic_istream& is, unsigned m = 1, unsigned M = 10) { unsigned x = 0; unsigned count = 0; while (true) { auto ic = is.peek(); if (Traits::eq_int_type(ic, Traits::eof())) break; auto c = static_cast(Traits::to_char_type(ic)); if (!('0' <= c && c <= '9')) break; (void)is.get(); ++count; x = 10*x + static_cast(c - '0'); if (count == M) break; } if (count < m) is.setstate(std::ios::failbit); return x; } template int read_signed(std::basic_istream& is, unsigned m = 1, unsigned M = 10) { auto ic = is.peek(); if (!Traits::eq_int_type(ic, Traits::eof())) { auto c = static_cast(Traits::to_char_type(ic)); if (('0' <= c && c <= '9') || c == '-' || c == '+') { if (c == '-' || c == '+') (void)is.get(); auto x = static_cast(read_unsigned(is, std::max(m, 1u), M)); if (!is.fail()) { if (c == '-') x = -x; return x; } } } if (m > 0) is.setstate(std::ios::failbit); return 0; } template long double read_long_double(std::basic_istream& is, unsigned m = 1, unsigned M = 10) { using namespace std; unsigned count = 0; auto decimal_point = Traits::to_int_type( use_facet>(is.getloc()).decimal_point()); std::string buf; while (true) { auto ic = is.peek(); if (Traits::eq_int_type(ic, Traits::eof())) break; if (Traits::eq_int_type(ic, decimal_point)) { buf += '.'; decimal_point = Traits::eof(); is.get(); } else { auto c = static_cast(Traits::to_char_type(ic)); if (!('0' <= c && c <= '9')) break; buf += c; (void)is.get(); } if (++count == M) break; } if (count < m) { is.setstate(std::ios::failbit); return 0; } return std::stold(buf); } struct rs { int& i; unsigned m; unsigned M; }; struct ru { int& i; unsigned m; unsigned M; }; struct rld { long double& i; unsigned m; unsigned M; }; template void read(std::basic_istream&) { } template void read(std::basic_istream& is, CharT a0, Args&& ...args); template void read(std::basic_istream& is, rs a0, Args&& ...args); template void read(std::basic_istream& is, ru a0, Args&& ...args); template void read(std::basic_istream& is, int a0, Args&& ...args); template void read(std::basic_istream& is, rld a0, Args&& ...args); template void read(std::basic_istream& is, CharT a0, Args&& ...args) { // No-op if a0 == CharT{} if (a0 != CharT{}) { auto ic = is.peek(); if (Traits::eq_int_type(ic, Traits::eof())) { is.setstate(std::ios::failbit | std::ios::eofbit); return; } if (!Traits::eq(Traits::to_char_type(ic), a0)) { is.setstate(std::ios::failbit); return; } (void)is.get(); } read(is, std::forward(args)...); } template void read(std::basic_istream& is, rs a0, Args&& ...args) { auto x = read_signed(is, a0.m, a0.M); if (is.fail()) return; a0.i = x; read(is, std::forward(args)...); } template void read(std::basic_istream& is, ru a0, Args&& ...args) { auto x = read_unsigned(is, a0.m, a0.M); if (is.fail()) return; a0.i = static_cast(x); read(is, std::forward(args)...); } template void read(std::basic_istream& is, int a0, Args&& ...args) { if (a0 != -1) { auto u = static_cast(a0); CharT buf[std::numeric_limits::digits10+2] = {}; auto e = buf; do { *e++ = CharT(u % 10) + CharT{'0'}; u /= 10; } while (u > 0); std::reverse(buf, e); for (auto p = buf; p != e && is.rdstate() == std::ios::goodbit; ++p) read(is, *p); } if (is.rdstate() == std::ios::goodbit) read(is, std::forward(args)...); } template void read(std::basic_istream& is, rld a0, Args&& ...args) { auto x = read_long_double(is, a0.m, a0.M); if (is.fail()) return; a0.i = x; read(is, std::forward(args)...); } template inline void checked_set(T& value, T from, T not_a_value, std::basic_ios& is) { if (!is.fail()) { if (value == not_a_value) value = std::move(from); else if (value != from) is.setstate(std::ios::failbit); } } } // namespace detail; template > std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, fields& fds, std::basic_string* abbrev, std::chrono::minutes* offset) { using namespace std; using namespace std::chrono; typename basic_istream::sentry ok{is, true}; if (ok) { date::detail::save_istream ss(is); is.fill(' '); is.flags(std::ios::skipws | std::ios::dec); is.width(0); #if !ONLY_C_LOCALE auto& f = use_facet>(is.getloc()); std::tm tm{}; #endif const CharT* command = nullptr; auto modified = CharT{}; auto width = -1; CONSTDATA int not_a_year = numeric_limits::min(); CONSTDATA int not_a_2digit_year = 100; CONSTDATA int not_a_century = not_a_year / 100; CONSTDATA int not_a_month = 0; CONSTDATA int not_a_day = 0; CONSTDATA int not_a_hour = numeric_limits::min(); CONSTDATA int not_a_hour_12_value = 0; CONSTDATA int not_a_minute = not_a_hour; CONSTDATA Duration not_a_second = Duration::min(); CONSTDATA int not_a_doy = -1; CONSTDATA int not_a_weekday = 8; CONSTDATA int not_a_week_num = 100; CONSTDATA int not_a_ampm = -1; CONSTDATA minutes not_a_offset = minutes::min(); int Y = not_a_year; // c, F, Y * int y = not_a_2digit_year; // D, x, y * int g = not_a_2digit_year; // g * int G = not_a_year; // G * int C = not_a_century; // C * int m = not_a_month; // b, B, h, m, c, D, F, x * int d = not_a_day; // c, d, D, e, F, x * int j = not_a_doy; // j * int wd = not_a_weekday; // a, A, u, w * int H = not_a_hour; // c, H, R, T, X * int I = not_a_hour_12_value; // I, r * int p = not_a_ampm; // p, r * int M = not_a_minute; // c, M, r, R, T, X * Duration s = not_a_second; // c, r, S, T, X * int U = not_a_week_num; // U * int V = not_a_week_num; // V * int W = not_a_week_num; // W * std::basic_string temp_abbrev; // Z * minutes temp_offset = not_a_offset; // z * using detail::read; using detail::rs; using detail::ru; using detail::rld; using detail::checked_set; for (; *fmt && is.rdstate() == std::ios::goodbit; ++fmt) { switch (*fmt) { case 'a': case 'A': case 'u': case 'w': // wd: a, A, u, w if (command) { int trial_wd = not_a_weekday; if (*fmt == 'a' || *fmt == 'A') { if (modified == CharT{}) { #if !ONLY_C_LOCALE ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); is.setstate(err); if (!is.fail()) trial_wd = tm.tm_wday; #else auto nm = detail::weekday_names(); auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; if (!is.fail()) trial_wd = i % 7; #endif } else read(is, CharT{'%'}, width, modified, *fmt); } else // *fmt == 'u' || *fmt == 'w' { #if !ONLY_C_LOCALE if (modified == CharT{}) #else if (modified != CharT{'E'}) #endif { read(is, ru{trial_wd, 1, width == -1 ? 1u : static_cast(width)}); if (!is.fail()) { if (*fmt == 'u') { if (!(1 <= trial_wd && trial_wd <= 7)) { trial_wd = not_a_weekday; is.setstate(ios_base::failbit); } else if (trial_wd == 7) trial_wd = 0; } else // *fmt == 'w' { if (!(0 <= trial_wd && trial_wd <= 6)) { trial_wd = not_a_weekday; is.setstate(ios_base::failbit); } } } } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); is.setstate(err); if (!is.fail()) trial_wd = tm.tm_wday; } #endif else read(is, CharT{'%'}, width, modified, *fmt); } if (trial_wd != not_a_weekday) checked_set(wd, trial_wd, not_a_weekday, is); } else // !command read(is, *fmt); command = nullptr; width = -1; modified = CharT{}; break; case 'b': case 'B': case 'h': if (command) { if (modified == CharT{}) { int ttm = not_a_month; #if !ONLY_C_LOCALE ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) ttm = tm.tm_mon + 1; is.setstate(err); #else auto nm = detail::month_names(); auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; if (!is.fail()) ttm = i % 12 + 1; #endif checked_set(m, ttm, not_a_month, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'c': if (command) { if (modified != CharT{'O'}) { #if !ONLY_C_LOCALE ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) { checked_set(Y, tm.tm_year + 1900, not_a_year, is); checked_set(m, tm.tm_mon + 1, not_a_month, is); checked_set(d, tm.tm_mday, not_a_day, is); checked_set(H, tm.tm_hour, not_a_hour, is); checked_set(M, tm.tm_min, not_a_minute, is); checked_set(s, duration_cast(seconds{tm.tm_sec}), not_a_second, is); } is.setstate(err); #else // "%a %b %e %T %Y" auto nm = detail::weekday_names(); auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; checked_set(wd, static_cast(i % 7), not_a_weekday, is); ws(is); nm = detail::month_names(); i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; checked_set(m, static_cast(i % 12 + 1), not_a_month, is); ws(is); int td = not_a_day; read(is, rs{td, 1, 2}); checked_set(d, td, not_a_day, is); ws(is); using dfs = detail::decimal_format_seconds; CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; int tH; int tM; long double S; read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, CharT{':'}, rld{S, 1, w}); checked_set(H, tH, not_a_hour, is); checked_set(M, tM, not_a_minute, is); checked_set(s, round(duration{S}), not_a_second, is); ws(is); int tY = not_a_year; read(is, rs{tY, 1, 4u}); checked_set(Y, tY, not_a_year, is); #endif } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'x': if (command) { if (modified != CharT{'O'}) { #if !ONLY_C_LOCALE ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) { checked_set(Y, tm.tm_year + 1900, not_a_year, is); checked_set(m, tm.tm_mon + 1, not_a_month, is); checked_set(d, tm.tm_mday, not_a_day, is); } is.setstate(err); #else // "%m/%d/%y" int ty = not_a_2digit_year; int tm = not_a_month; int td = not_a_day; read(is, ru{tm, 1, 2}, CharT{'/'}, ru{td, 1, 2}, CharT{'/'}, rs{ty, 1, 2}); checked_set(y, ty, not_a_2digit_year, is); checked_set(m, tm, not_a_month, is); checked_set(d, td, not_a_day, is); #endif } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'X': if (command) { if (modified != CharT{'O'}) { #if !ONLY_C_LOCALE ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) { checked_set(H, tm.tm_hour, not_a_hour, is); checked_set(M, tm.tm_min, not_a_minute, is); checked_set(s, duration_cast(seconds{tm.tm_sec}), not_a_second, is); } is.setstate(err); #else // "%T" using dfs = detail::decimal_format_seconds; CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; int tH = not_a_hour; int tM = not_a_minute; long double S; read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, CharT{':'}, rld{S, 1, w}); checked_set(H, tH, not_a_hour, is); checked_set(M, tM, not_a_minute, is); checked_set(s, round(duration{S}), not_a_second, is); #endif } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'C': if (command) { int tC = not_a_century; #if !ONLY_C_LOCALE if (modified == CharT{}) { #endif read(is, rs{tC, 1, width == -1 ? 2u : static_cast(width)}); #if !ONLY_C_LOCALE } else { ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) { auto tY = tm.tm_year + 1900; tC = (tY >= 0 ? tY : tY-99) / 100; } is.setstate(err); } #endif checked_set(C, tC, not_a_century, is); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'D': if (command) { if (modified == CharT{}) { int tn = not_a_month; int td = not_a_day; int ty = not_a_2digit_year; read(is, ru{tn, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'}, ru{td, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'}, rs{ty, 1, 2}); checked_set(y, ty, not_a_2digit_year, is); checked_set(m, tn, not_a_month, is); checked_set(d, td, not_a_day, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'F': if (command) { if (modified == CharT{}) { int tY = not_a_year; int tn = not_a_month; int td = not_a_day; read(is, rs{tY, 1, width == -1 ? 4u : static_cast(width)}, CharT{'-'}, ru{tn, 1, 2}, CharT{'-'}, ru{td, 1, 2}); checked_set(Y, tY, not_a_year, is); checked_set(m, tn, not_a_month, is); checked_set(d, td, not_a_day, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'd': case 'e': if (command) { #if !ONLY_C_LOCALE if (modified == CharT{}) #else if (modified != CharT{'E'}) #endif { int td = not_a_day; read(is, rs{td, 1, width == -1 ? 2u : static_cast(width)}); checked_set(d, td, not_a_day, is); } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); command = nullptr; width = -1; modified = CharT{}; if ((err & ios::failbit) == 0) checked_set(d, tm.tm_mday, not_a_day, is); is.setstate(err); } #endif else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'H': if (command) { #if !ONLY_C_LOCALE if (modified == CharT{}) #else if (modified != CharT{'E'}) #endif { int tH = not_a_hour; read(is, ru{tH, 1, width == -1 ? 2u : static_cast(width)}); checked_set(H, tH, not_a_hour, is); } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) checked_set(H, tm.tm_hour, not_a_hour, is); is.setstate(err); } #endif else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'I': if (command) { if (modified == CharT{}) { int tI = not_a_hour_12_value; // reads in an hour into I, but most be in [1, 12] read(is, rs{tI, 1, width == -1 ? 2u : static_cast(width)}); if (!(1 <= tI && tI <= 12)) is.setstate(ios::failbit); checked_set(I, tI, not_a_hour_12_value, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'j': if (command) { if (modified == CharT{}) { int tj = not_a_doy; read(is, ru{tj, 1, width == -1 ? 3u : static_cast(width)}); checked_set(j, tj, not_a_doy, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'M': if (command) { #if !ONLY_C_LOCALE if (modified == CharT{}) #else if (modified != CharT{'E'}) #endif { int tM = not_a_minute; read(is, ru{tM, 1, width == -1 ? 2u : static_cast(width)}); checked_set(M, tM, not_a_minute, is); } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) checked_set(M, tm.tm_min, not_a_minute, is); is.setstate(err); } #endif else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'm': if (command) { #if !ONLY_C_LOCALE if (modified == CharT{}) #else if (modified != CharT{'E'}) #endif { int tn = not_a_month; read(is, rs{tn, 1, width == -1 ? 2u : static_cast(width)}); checked_set(m, tn, not_a_month, is); } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) checked_set(m, tm.tm_mon + 1, not_a_month, is); is.setstate(err); } #endif else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'n': case 't': if (command) { if (modified == CharT{}) { // %n matches a single white space character // %t matches 0 or 1 white space characters auto ic = is.peek(); if (Traits::eq_int_type(ic, Traits::eof())) { ios_base::iostate err = ios_base::eofbit; if (*fmt == 'n') err |= ios_base::failbit; is.setstate(err); break; } if (isspace(ic)) { (void)is.get(); } else if (*fmt == 'n') is.setstate(ios_base::failbit); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'p': if (command) { if (modified == CharT{}) { int tp = not_a_ampm; #if !ONLY_C_LOCALE tm = std::tm{}; tm.tm_hour = 1; ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); is.setstate(err); if (tm.tm_hour == 1) tp = 0; else if (tm.tm_hour == 13) tp = 1; else is.setstate(err); #else auto nm = detail::ampm_names(); auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; tp = i; #endif checked_set(p, tp, not_a_ampm, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'r': if (command) { if (modified == CharT{}) { #if !ONLY_C_LOCALE ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) { checked_set(H, tm.tm_hour, not_a_hour, is); checked_set(M, tm.tm_min, not_a_hour, is); checked_set(s, duration_cast(seconds{tm.tm_sec}), not_a_second, is); } is.setstate(err); #else // "%I:%M:%S %p" using dfs = detail::decimal_format_seconds; CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; long double S; int tI = not_a_hour_12_value; int tM = not_a_minute; read(is, ru{tI, 1, 2}, CharT{':'}, ru{tM, 1, 2}, CharT{':'}, rld{S, 1, w}); checked_set(I, tI, not_a_hour_12_value, is); checked_set(M, tM, not_a_minute, is); checked_set(s, round(duration{S}), not_a_second, is); ws(is); auto nm = detail::ampm_names(); auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; checked_set(p, static_cast(i), not_a_ampm, is); #endif } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'R': if (command) { if (modified == CharT{}) { int tH = not_a_hour; int tM = not_a_minute; read(is, ru{tH, 1, 2}, CharT{'\0'}, CharT{':'}, CharT{'\0'}, ru{tM, 1, 2}, CharT{'\0'}); checked_set(H, tH, not_a_hour, is); checked_set(M, tM, not_a_minute, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'S': if (command) { #if !ONLY_C_LOCALE if (modified == CharT{}) #else if (modified != CharT{'E'}) #endif { using dfs = detail::decimal_format_seconds; CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; long double S; read(is, rld{S, 1, width == -1 ? w : static_cast(width)}); checked_set(s, round(duration{S}), not_a_second, is); } #if !ONLY_C_LOCALE else if (modified == CharT{'O'}) { ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) checked_set(s, duration_cast(seconds{tm.tm_sec}), not_a_second, is); is.setstate(err); } #endif else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'T': if (command) { if (modified == CharT{}) { using dfs = detail::decimal_format_seconds; CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; int tH = not_a_hour; int tM = not_a_minute; long double S; read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, CharT{':'}, rld{S, 1, w}); checked_set(H, tH, not_a_hour, is); checked_set(M, tM, not_a_minute, is); checked_set(s, round(duration{S}), not_a_second, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'Y': if (command) { #if !ONLY_C_LOCALE if (modified == CharT{}) #else if (modified != CharT{'O'}) #endif { int tY = not_a_year; read(is, rs{tY, 1, width == -1 ? 4u : static_cast(width)}); checked_set(Y, tY, not_a_year, is); } #if !ONLY_C_LOCALE else if (modified == CharT{'E'}) { ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) checked_set(Y, tm.tm_year + 1900, not_a_year, is); is.setstate(err); } #endif else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'y': if (command) { #if !ONLY_C_LOCALE if (modified == CharT{}) #endif { int ty = not_a_2digit_year; read(is, ru{ty, 1, width == -1 ? 2u : static_cast(width)}); checked_set(y, ty, not_a_2digit_year, is); } #if !ONLY_C_LOCALE else { ios_base::iostate err = ios_base::goodbit; f.get(is, nullptr, is, err, &tm, command, fmt+1); if ((err & ios::failbit) == 0) checked_set(Y, tm.tm_year + 1900, not_a_year, is); is.setstate(err); } #endif command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'g': if (command) { if (modified == CharT{}) { int tg = not_a_2digit_year; read(is, ru{tg, 1, width == -1 ? 2u : static_cast(width)}); checked_set(g, tg, not_a_2digit_year, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'G': if (command) { if (modified == CharT{}) { int tG = not_a_year; read(is, rs{tG, 1, width == -1 ? 4u : static_cast(width)}); checked_set(G, tG, not_a_year, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'U': if (command) { if (modified == CharT{}) { int tU = not_a_week_num; read(is, ru{tU, 1, width == -1 ? 2u : static_cast(width)}); checked_set(U, tU, not_a_week_num, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'V': if (command) { if (modified == CharT{}) { int tV = not_a_week_num; read(is, ru{tV, 1, width == -1 ? 2u : static_cast(width)}); checked_set(V, tV, not_a_week_num, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'W': if (command) { if (modified == CharT{}) { int tW = not_a_week_num; read(is, ru{tW, 1, width == -1 ? 2u : static_cast(width)}); checked_set(W, tW, not_a_week_num, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'E': case 'O': if (command) { if (modified == CharT{}) { modified = *fmt; } else { read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } } else read(is, *fmt); break; case '%': if (command) { if (modified == CharT{}) read(is, *fmt); else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else command = fmt; break; case 'z': if (command) { int tH, tM; minutes toff = not_a_offset; bool neg = false; auto ic = is.peek(); if (!Traits::eq_int_type(ic, Traits::eof())) { auto c = static_cast(Traits::to_char_type(ic)); if (c == '-') neg = true; } if (modified == CharT{}) { read(is, rs{tH, 2, 2}); if (!is.fail()) toff = hours{std::abs(tH)}; if (is.good()) { ic = is.peek(); if (!Traits::eq_int_type(ic, Traits::eof())) { auto c = static_cast(Traits::to_char_type(ic)); if ('0' <= c && c <= '9') { read(is, ru{tM, 2, 2}); if (!is.fail()) toff += minutes{tM}; } } } } else { read(is, rs{tH, 1, 2}); if (!is.fail()) toff = hours{std::abs(tH)}; if (is.good()) { ic = is.peek(); if (!Traits::eq_int_type(ic, Traits::eof())) { auto c = static_cast(Traits::to_char_type(ic)); if (c == ':') { (void)is.get(); read(is, ru{tM, 2, 2}); if (!is.fail()) toff += minutes{tM}; } } } } if (neg) toff = -toff; checked_set(temp_offset, toff, not_a_offset, is); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; case 'Z': if (command) { if (modified == CharT{}) { std::basic_string buf; while (is.rdstate() == std::ios::goodbit) { auto i = is.rdbuf()->sgetc(); if (Traits::eq_int_type(i, Traits::eof())) { is.setstate(ios::eofbit); break; } auto wc = Traits::to_char_type(i); auto c = static_cast(wc); // is c a valid time zone name or abbreviation character? if (!(CharT{1} < wc && wc < CharT{127}) || !(isalnum(c) || c == '_' || c == '/' || c == '-' || c == '+')) break; buf.push_back(c); is.rdbuf()->sbumpc(); } if (buf.empty()) is.setstate(ios::failbit); checked_set(temp_abbrev, buf, {}, is); } else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } else read(is, *fmt); break; default: if (command) { if (width == -1 && modified == CharT{} && '0' <= *fmt && *fmt <= '9') { width = static_cast(*fmt) - '0'; while ('0' <= fmt[1] && fmt[1] <= '9') width = 10*width + static_cast(*++fmt) - '0'; } else { if (modified == CharT{}) read(is, CharT{'%'}, width, *fmt); else read(is, CharT{'%'}, width, modified, *fmt); command = nullptr; width = -1; modified = CharT{}; } } else // !command { if (isspace(static_cast(*fmt))) ws(is); // space matches 0 or more white space characters else read(is, *fmt); } break; } } // is.rdstate() != ios::goodbit || *fmt == CharT{} if (is.rdstate() == ios::goodbit && command) { if (modified == CharT{}) read(is, CharT{'%'}, width); else read(is, CharT{'%'}, width, modified); } if (is.rdstate() != ios::goodbit && *fmt != CharT{} && !is.fail()) is.setstate(ios::failbit); if (!is.fail()) { if (y != not_a_2digit_year) { // Convert y and an optional C to Y if (!(0 <= y && y <= 99)) goto broken; if (C == not_a_century) { if (Y == not_a_year) { if (y >= 69) C = 19; else C = 20; } else { C = (Y >= 0 ? Y : Y-100) / 100; } } int tY; if (C >= 0) tY = 100*C + y; else tY = 100*(C+1) - (y == 0 ? 100 : y); if (Y != not_a_year && Y != tY) goto broken; Y = tY; } if (g != not_a_2digit_year) { // Convert g and an optional C to G if (!(0 <= g && g <= 99)) goto broken; if (C == not_a_century) { if (G == not_a_year) { if (g >= 69) C = 19; else C = 20; } else { C = (G >= 0 ? G : G-100) / 100; } } int tG; if (C >= 0) tG = 100*C + g; else tG = 100*(C+1) - (g == 0 ? 100 : g); if (G != not_a_year && G != tG) goto broken; G = tG; } if (Y < static_cast(year::min()) || Y > static_cast(year::max())) Y = not_a_year; bool computed = false; if (G != not_a_year && V != not_a_week_num && wd != not_a_weekday) { year_month_day ymd_trial = sys_days(year{G-1}/December/Thursday[last]) + (Monday-Thursday) + weeks{V-1} + (weekday{static_cast(wd)}-Monday); if (Y == not_a_year) Y = static_cast(ymd_trial.year()); else if (year{Y} != ymd_trial.year()) goto broken; if (m == not_a_month) m = static_cast(static_cast(ymd_trial.month())); else if (month(static_cast(m)) != ymd_trial.month()) goto broken; if (d == not_a_day) d = static_cast(static_cast(ymd_trial.day())); else if (day(static_cast(d)) != ymd_trial.day()) goto broken; computed = true; } if (Y != not_a_year && U != not_a_week_num && wd != not_a_weekday) { year_month_day ymd_trial = sys_days(year{Y}/January/Sunday[1]) + weeks{U-1} + (weekday{static_cast(wd)} - Sunday); if (Y == not_a_year) Y = static_cast(ymd_trial.year()); else if (year{Y} != ymd_trial.year()) goto broken; if (m == not_a_month) m = static_cast(static_cast(ymd_trial.month())); else if (month(static_cast(m)) != ymd_trial.month()) goto broken; if (d == not_a_day) d = static_cast(static_cast(ymd_trial.day())); else if (day(static_cast(d)) != ymd_trial.day()) goto broken; computed = true; } if (Y != not_a_year && W != not_a_week_num && wd != not_a_weekday) { year_month_day ymd_trial = sys_days(year{Y}/January/Monday[1]) + weeks{W-1} + (weekday{static_cast(wd)} - Monday); if (Y == not_a_year) Y = static_cast(ymd_trial.year()); else if (year{Y} != ymd_trial.year()) goto broken; if (m == not_a_month) m = static_cast(static_cast(ymd_trial.month())); else if (month(static_cast(m)) != ymd_trial.month()) goto broken; if (d == not_a_day) d = static_cast(static_cast(ymd_trial.day())); else if (day(static_cast(d)) != ymd_trial.day()) goto broken; computed = true; } if (j != not_a_doy && Y != not_a_year) { auto ymd_trial = year_month_day{local_days(year{Y}/1/1) + days{j-1}}; if (m == 0) m = static_cast(static_cast(ymd_trial.month())); else if (month(static_cast(m)) != ymd_trial.month()) goto broken; if (d == 0) d = static_cast(static_cast(ymd_trial.day())); else if (day(static_cast(d)) != ymd_trial.day()) goto broken; j = not_a_doy; } auto ymd = year{Y}/m/d; if (ymd.ok()) { if (wd == not_a_weekday) wd = static_cast((weekday(sys_days(ymd)) - Sunday).count()); else if (wd != static_cast((weekday(sys_days(ymd)) - Sunday).count())) goto broken; if (!computed) { if (G != not_a_year || V != not_a_week_num) { sys_days sd = ymd; auto G_trial = year_month_day{sd + days{3}}.year(); auto start = sys_days((G_trial - years{1})/December/Thursday[last]) + (Monday - Thursday); if (sd < start) { --G_trial; if (V != not_a_week_num) start = sys_days((G_trial - years{1})/December/Thursday[last]) + (Monday - Thursday); } if (G != not_a_year && G != static_cast(G_trial)) goto broken; if (V != not_a_week_num) { auto V_trial = duration_cast(sd - start).count() + 1; if (V != V_trial) goto broken; } } if (U != not_a_week_num) { auto start = sys_days(Sunday[1]/January/ymd.year()); auto U_trial = floor(sys_days(ymd) - start).count() + 1; if (U != U_trial) goto broken; } if (W != not_a_week_num) { auto start = sys_days(Monday[1]/January/ymd.year()); auto W_trial = floor(sys_days(ymd) - start).count() + 1; if (W != W_trial) goto broken; } } } fds.ymd = ymd; if (I != not_a_hour_12_value) { if (!(1 <= I && I <= 12)) goto broken; if (p != not_a_ampm) { // p is in [0, 1] == [AM, PM] // Store trial H in I if (I == 12) --p; I += p*12; // Either set H from I or make sure H and I are consistent if (H == not_a_hour) H = I; else if (I != H) goto broken; } else // p == not_a_ampm { // if H, make sure H and I could be consistent if (H != not_a_hour) { if (I == 12) { if (H != 0 && H != 12) goto broken; } else if (!(I == H || I == H+12)) { goto broken; } } } } if (H != not_a_hour) { fds.has_tod = true; fds.tod = time_of_day{hours{H}}; } if (M != not_a_minute) { fds.has_tod = true; fds.tod.m_ = minutes{M}; } if (s != not_a_second) { fds.has_tod = true; fds.tod.s_ = detail::decimal_format_seconds{s}; } if (j != not_a_doy) { fds.has_tod = true; fds.tod.h_ += hours{days{j}}; } if (wd != not_a_weekday) fds.wd = weekday{static_cast(wd)}; if (abbrev != nullptr) *abbrev = std::move(temp_abbrev); if (offset != nullptr && temp_offset != not_a_offset) *offset = temp_offset; } return is; } broken: is.setstate(ios_base::failbit); return is; } template > std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, year& y, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr) { using namespace std; using namespace std::chrono; using CT = seconds; fields fds{}; from_stream(is, fmt, fds, abbrev, offset); if (!fds.ymd.year().ok()) is.setstate(ios::failbit); if (!is.fail()) y = fds.ymd.year(); return is; } template > std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, month& m, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr) { using namespace std; using namespace std::chrono; using CT = seconds; fields fds{}; from_stream(is, fmt, fds, abbrev, offset); if (!fds.ymd.month().ok()) is.setstate(ios::failbit); if (!is.fail()) m = fds.ymd.month(); return is; } template > std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, day& d, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr) { using namespace std; using namespace std::chrono; using CT = seconds; fields fds{}; from_stream(is, fmt, fds, abbrev, offset); if (!fds.ymd.day().ok()) is.setstate(ios::failbit); if (!is.fail()) d = fds.ymd.day(); return is; } template > std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, weekday& wd, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr) { using namespace std; using namespace std::chrono; using CT = seconds; fields fds{}; from_stream(is, fmt, fds, abbrev, offset); if (!fds.wd.ok()) is.setstate(ios::failbit); if (!is.fail()) wd = fds.wd; return is; } template > std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, year_month& ym, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr) { using namespace std; using namespace std::chrono; using CT = seconds; fields fds{}; from_stream(is, fmt, fds, abbrev, offset); if (!fds.ymd.month().ok()) is.setstate(ios::failbit); if (!is.fail()) ym = fds.ymd.year()/fds.ymd.month(); return is; } template > std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, month_day& md, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr) { using namespace std; using namespace std::chrono; using CT = seconds; fields fds{}; from_stream(is, fmt, fds, abbrev, offset); if (!fds.ymd.month().ok() || !fds.ymd.day().ok()) is.setstate(ios::failbit); if (!is.fail()) md = fds.ymd.month()/fds.ymd.day(); return is; } template > std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, year_month_day& ymd, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr) { using namespace std; using namespace std::chrono; using CT = seconds; fields fds{}; from_stream(is, fmt, fds, abbrev, offset); if (!fds.ymd.ok()) is.setstate(ios::failbit); if (!is.fail()) ymd = fds.ymd; return is; } template > std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, sys_time& tp, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr) { using namespace std; using namespace std::chrono; using CT = typename common_type::type; minutes offset_local{}; auto offptr = offset ? offset : &offset_local; fields fds{}; fds.has_tod = true; from_stream(is, fmt, fds, abbrev, offptr); if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) is.setstate(ios::failbit); if (!is.fail()) tp = round(sys_days(fds.ymd) - *offptr + fds.tod.to_duration()); return is; } template > std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, local_time& tp, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr) { using namespace std; using namespace std::chrono; using CT = typename common_type::type; fields fds{}; fds.has_tod = true; from_stream(is, fmt, fds, abbrev, offset); if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) is.setstate(ios::failbit); if (!is.fail()) tp = round(local_seconds{local_days(fds.ymd)} + fds.tod.to_duration()); return is; } template > std::basic_istream& from_stream(std::basic_istream& is, const CharT* fmt, std::chrono::duration& d, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr) { using namespace std; using namespace std::chrono; using Duration = std::chrono::duration; using CT = typename common_type::type; fields fds{}; from_stream(is, fmt, fds, abbrev, offset); if (!fds.has_tod) is.setstate(ios::failbit); if (!is.fail()) d = duration_cast(fds.tod.to_duration()); return is; } template , class Alloc = std::allocator> struct parse_manip { const std::basic_string format_; Parsable& tp_; std::basic_string* abbrev_; std::chrono::minutes* offset_; public: parse_manip(std::basic_string format, Parsable& tp, std::basic_string* abbrev = nullptr, std::chrono::minutes* offset = nullptr) : format_(std::move(format)) , tp_(tp) , abbrev_(abbrev) , offset_(offset) {} }; template std::basic_istream& operator>>(std::basic_istream& is, const parse_manip& x) { return from_stream(is, x.format_.c_str(), x.tp_, x.abbrev_, x.offset_); } template inline auto parse(const std::basic_string& format, Parsable& tp) -> decltype(from_stream(std::declval&>(), format.c_str(), tp), parse_manip{format, tp}) { return {format, tp}; } template inline auto parse(const std::basic_string& format, Parsable& tp, std::basic_string& abbrev) -> decltype(from_stream(std::declval&>(), format.c_str(), tp, &abbrev), parse_manip{format, tp, &abbrev}) { return {format, tp, &abbrev}; } template inline auto parse(const std::basic_string& format, Parsable& tp, std::chrono::minutes& offset) -> decltype(from_stream(std::declval&>(), format.c_str(), tp, std::declval*>(), &offset), parse_manip{format, tp, nullptr, &offset}) { return {format, tp, nullptr, &offset}; } template inline auto parse(const std::basic_string& format, Parsable& tp, std::basic_string& abbrev, std::chrono::minutes& offset) -> decltype(from_stream(std::declval&>(), format.c_str(), tp, &abbrev, &offset), parse_manip{format, tp, &abbrev, &offset}) { return {format, tp, &abbrev, &offset}; } // const CharT* formats template inline auto parse(const CharT* format, Parsable& tp) -> decltype(from_stream(std::declval&>(), format, tp), parse_manip{format, tp}) { return {format, tp}; } template inline auto parse(const CharT* format, Parsable& tp, std::basic_string& abbrev) -> decltype(from_stream(std::declval&>(), format, tp, &abbrev), parse_manip{format, tp, &abbrev}) { return {format, tp, &abbrev}; } template inline auto parse(const CharT* format, Parsable& tp, std::chrono::minutes& offset) -> decltype(from_stream(std::declval&>(), format, tp, std::declval*>(), &offset), parse_manip{format, tp, nullptr, &offset}) { return {format, tp, nullptr, &offset}; } template inline auto parse(const CharT* format, Parsable& tp, std::basic_string& abbrev, std::chrono::minutes& offset) -> decltype(from_stream(std::declval&>(), format, tp, &abbrev, &offset), parse_manip{format, tp, &abbrev, &offset}) { return {format, tp, &abbrev, &offset}; } // duration streaming namespace detail { template class string_literal; template inline CONSTCD14 string_literal::type, N1 + N2 - 1> operator+(const string_literal& x, const string_literal& y) NOEXCEPT; template class string_literal { CharT p_[N]; CONSTCD11 string_literal() NOEXCEPT : p_{} {} public: using const_iterator = const CharT*; string_literal(string_literal const&) = default; string_literal& operator=(string_literal const&) = delete; template ::type> CONSTCD11 string_literal(CharT c) NOEXCEPT : p_{c} { } template ::type> CONSTCD11 string_literal(CharT c1, CharT c2) NOEXCEPT : p_{c1, c2} { } template ::type> CONSTCD11 string_literal(CharT c1, CharT c2, CharT c3) NOEXCEPT : p_{c1, c2, c3} { } CONSTCD14 string_literal(const CharT(&a)[N]) NOEXCEPT : p_{} { for (std::size_t i = 0; i < N; ++i) p_[i] = a[i]; } template ::type> CONSTCD14 string_literal(const char(&a)[N]) NOEXCEPT : p_{} { for (std::size_t i = 0; i < N; ++i) p_[i] = a[i]; } template ::value>::type> CONSTCD14 string_literal(string_literal const& a) NOEXCEPT : p_{} { for (std::size_t i = 0; i < N; ++i) p_[i] = a[i]; } CONSTCD11 const CharT* data() const NOEXCEPT {return p_;} CONSTCD11 std::size_t size() const NOEXCEPT {return N-1;} CONSTCD11 const_iterator begin() const NOEXCEPT {return p_;} CONSTCD11 const_iterator end() const NOEXCEPT {return p_ + N-1;} CONSTCD11 CharT const& operator[](std::size_t n) const NOEXCEPT { return p_[n]; } template friend std::basic_ostream& operator<<(std::basic_ostream& os, const string_literal& s) { return os << s.p_; } template friend CONSTCD14 string_literal::type, N1 + N2 - 1> operator+(const string_literal& x, const string_literal& y) NOEXCEPT; }; template CONSTCD11 inline string_literal operator+(const string_literal& x, const string_literal& y) NOEXCEPT { return string_literal(x[0], y[0]); } template CONSTCD11 inline string_literal operator+(const string_literal& x, const string_literal& y) NOEXCEPT { return string_literal(x[0], x[1], y[0]); } template CONSTCD14 inline string_literal::type, N1 + N2 - 1> operator+(const string_literal& x, const string_literal& y) NOEXCEPT { using CT = typename std::conditional::type; string_literal r; std::size_t i = 0; for (; i < N1-1; ++i) r.p_[i] = CT(x.p_[i]); for (std::size_t j = 0; j < N2; ++j, ++i) r.p_[i] = CT(y.p_[j]); return r; } template inline std::basic_string operator+(std::basic_string x, const string_literal& y) { x.append(y.data(), y.size()); return x; } #if __cplusplus >= 201402 && (!defined(__EDG_VERSION__) || __EDG_VERSION__ > 411) \ && (!defined(__SUNPRO_CC) || __SUNPRO_CC > 0x5150) template {} || std::is_same{} || std::is_same{} || std::is_same{}>> CONSTCD14 inline string_literal msl(CharT c) NOEXCEPT { return string_literal{c}; } CONSTCD14 inline std::size_t to_string_len(std::intmax_t i) { std::size_t r = 0; do { i /= 10; ++r; } while (i > 0); return r; } template CONSTCD14 inline std::enable_if_t < N < 10, string_literal > msl() NOEXCEPT { return msl(char(N % 10 + '0')); } template CONSTCD14 inline std::enable_if_t < 10 <= N, string_literal > msl() NOEXCEPT { return msl() + msl(char(N % 10 + '0')); } template CONSTCD14 inline std::enable_if_t < std::ratio::type::den != 1, string_literal::type::num) + to_string_len(std::ratio::type::den) + 4> > msl(std::ratio) NOEXCEPT { using R = typename std::ratio::type; return msl(CharT{'['}) + msl() + msl(CharT{'/'}) + msl() + msl(CharT{']'}); } template CONSTCD14 inline std::enable_if_t < std::ratio::type::den == 1, string_literal::type::num) + 3> > msl(std::ratio) NOEXCEPT { using R = typename std::ratio::type; return msl(CharT{'['}) + msl() + msl(CharT{']'}); } #else // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411) inline std::string to_string(std::uint64_t x) { return std::to_string(x); } template inline std::basic_string to_string(std::uint64_t x) { auto y = std::to_string(x); return std::basic_string(y.begin(), y.end()); } template inline typename std::enable_if < std::ratio::type::den != 1, std::basic_string >::type msl(std::ratio) { using R = typename std::ratio::type; return std::basic_string(1, '[') + to_string(R::num) + CharT{'/'} + to_string(R::den) + CharT{']'}; } template inline typename std::enable_if < std::ratio::type::den == 1, std::basic_string >::type msl(std::ratio) { using R = typename std::ratio::type; return std::basic_string(1, '[') + to_string(R::num) + CharT{']'}; } #endif // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411) template CONSTCD11 inline string_literal msl(std::atto) NOEXCEPT { return string_literal{'a'}; } template CONSTCD11 inline string_literal msl(std::femto) NOEXCEPT { return string_literal{'f'}; } template CONSTCD11 inline string_literal msl(std::pico) NOEXCEPT { return string_literal{'p'}; } template CONSTCD11 inline string_literal msl(std::nano) NOEXCEPT { return string_literal{'n'}; } template CONSTCD11 inline typename std::enable_if < std::is_same::value, string_literal >::type msl(std::micro) NOEXCEPT { return string_literal{'\xC2', '\xB5'}; } template CONSTCD11 inline typename std::enable_if < !std::is_same::value, string_literal >::type msl(std::micro) NOEXCEPT { return string_literal{CharT{static_cast('\xB5')}}; } template CONSTCD11 inline string_literal msl(std::milli) NOEXCEPT { return string_literal{'m'}; } template CONSTCD11 inline string_literal msl(std::centi) NOEXCEPT { return string_literal{'c'}; } template CONSTCD11 inline string_literal msl(std::deca) NOEXCEPT { return string_literal{'d', 'a'}; } template CONSTCD11 inline string_literal msl(std::deci) NOEXCEPT { return string_literal{'d'}; } template CONSTCD11 inline string_literal msl(std::hecto) NOEXCEPT { return string_literal{'h'}; } template CONSTCD11 inline string_literal msl(std::kilo) NOEXCEPT { return string_literal{'k'}; } template CONSTCD11 inline string_literal msl(std::mega) NOEXCEPT { return string_literal{'M'}; } template CONSTCD11 inline string_literal msl(std::giga) NOEXCEPT { return string_literal{'G'}; } template CONSTCD11 inline string_literal msl(std::tera) NOEXCEPT { return string_literal{'T'}; } template CONSTCD11 inline string_literal msl(std::peta) NOEXCEPT { return string_literal{'P'}; } template CONSTCD11 inline string_literal msl(std::exa) NOEXCEPT { return string_literal{'E'}; } template CONSTCD11 inline auto get_units(Period p) -> decltype(msl(p) + string_literal{'s'}) { return msl(p) + string_literal{'s'}; } template CONSTCD11 inline string_literal get_units(std::ratio<1>) { return string_literal{'s'}; } template CONSTCD11 inline string_literal get_units(std::ratio<3600>) { return string_literal{'h'}; } template CONSTCD11 inline string_literal get_units(std::ratio<60>) { return string_literal{'m', 'i', 'n'}; } template CONSTCD11 inline string_literal get_units(std::ratio<86400>) { return string_literal{'d'}; } template > struct make_string; template <> struct make_string { template static std::string from(Rep n) { return std::to_string(n); } }; template struct make_string { template static std::basic_string from(Rep n) { auto s = std::to_string(n); return std::basic_string(s.begin(), s.end()); } }; template <> struct make_string { template static std::wstring from(Rep n) { return std::to_wstring(n); } }; template struct make_string { template static std::basic_string from(Rep n) { auto s = std::to_wstring(n); return std::basic_string(s.begin(), s.end()); } }; } // namespace detail template inline std::basic_ostream& operator<<(std::basic_ostream& os, const std::chrono::duration& d) { using namespace detail; return os << make_string::from(d.count()) + get_units(typename Period::type{}); } } // namespace date #ifdef __GNUC__ # pragma GCC diagnostic pop #endif #endif // DATE_H vcu-omx-il-xilinx-v2020.2/LICENSE.md000066400000000000000000000035401373706561700167230ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2017 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ vcu-omx-il-xilinx-v2020.2/Makefile000066400000000000000000000042311373706561700167550ustar00rootroot00000000000000define get-my-dir $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) endef THIS:=$(call get-my-dir) all: true_all PWD:=$(shell pwd) BIN?=$(PWD)/bin OMX_HEADERS?=$(PWD)/omx_header EXTERNAL_INCLUDE?=$(PWD)/../allegro-vcu-ctrl-sw/include EXTERNAL_CONFIG?=$(EXTERNAL_INCLUDE)/config.h ifndef BIN $(error BIN must be set) endif ifndef OMX_HEADERS $(error OMX_HEADERS must be set) endif ifndef EXTERNAL_INCLUDE $(error EXTERNAL_INCLUDE must be set) endif ifndef EXTERNAL_CONFIG $(error EXTERNAL_CONFIG must be set) endif EXTERNAL_SRC?= EXTERNAL_LIB?= ENABLE_VCU?=1 ENABLE_MCU?=1 ENABLE_64BIT?=1 ENABLE_DMA_COPY_ENC?=1 -include quirks.mk CROSS_COMPILE?= CXX:=$(CROSS_COMPILE)g++ CC:=$(CROSS_COMPILE)gcc AS:=$(CROSS_COMPILE)as AR:=$(CROSS_COMPILE)ar NM:=$(CROSS_COMPILE)nm LD:=$(CROSS_COMPILE)ld OBJDUMP:=$(CROSS_COMPILE)objdump OBJCOPY:=$(CROSS_COMPILE)objcopy RANLIB:=$(CROSS_COMPILE)ranlib STRIP:=$(CROSS_COMPILE)strip SIZE:=$(CROSS_COMPILE)size ifeq ($(ENABLE_DMA_COPY_ENC), 1) CFLAGS+=-DAL_ENABLE_DMA_COPY_ENC endif TARGET?=$(shell $(CC) -dumpmachine) ifeq ($(ENABLE_64BIT),0) # force 32 bit compilation ifneq (,$(findstring x86_64,$(TARGET))) CFLAGS+=-m32 LDFLAGS+=-m32 TARGET:=i686-linux-gnu endif endif include $(THIS)/builder.mk DEFAULT_CFLAGS:=$(CFLAGS) DEFAULT_CFLAGS+=-O3 DEFAULT_CFLAGS+=-pedantic DEFAULT_CFLAGS+=-g0 DEFAULT_CFLAGS+=-Wall DEFAULT_CFLAGS+=-Wextra DEFAULT_CFLAGS+=-Wno-missing-field-initializers DEFAULT_LDFLAGS:=$(LDFLAGS) INCLUDES+=-I$(THIS) INCLUDES+=-I$(OMX_HEADERS) INCLUDES+=-I$(EXTERNAL_INCLUDE) INCLUDES+=-include $(EXTERNAL_CONFIG) -include $(THIS)/get_external.mk include $(THIS)/utility/project.mk include $(THIS)/core/project.mk include $(THIS)/project_codec.mk -include $(THIS)/project_enc.mk -include $(THIS)/project_dec.mk include $(THIS)/exe_omx/project_codec.mk -include $(THIS)/exe_omx/project_enc.mk -include $(THIS)/exe_omx/project_dec.mk -include $(THIS)/conformance/project.mk -include $(THIS)/unittests.mk .PHONY: clean clean: $(Q)rm -rf $(BIN) @echo "CLEAN $(BIN)" .PHONY: distclean distclean: clean @echo "CLEAN $(EXTERNAL_LIB)" $(Q)rm -rf $(EXTERNAL_LIB) TARGETS: $(externals) true_all: $(TARGETS) vcu-omx-il-xilinx-v2020.2/README000066400000000000000000000016251373706561700162010ustar00rootroot00000000000000# OpenMax Integration Layer This repository contains the AllegroDVT2 OpenMax Integration Layer (OMXIL) implementation ## Installation *Linux x86 user* $ ctrlsw_include=/your_path_to_ctrlsw_include $ make EXTERNAL_INCLUDE=$ctrlsw_include *Linux other platforms (i.e. arm 32 bits) user* $ bin=/bin_path $ ctrlsw_include=/your_path_to_ctrlsw_include $ make EXTERNAL_INCLUDE=$ctrlsw_include BIN=$bin CROSS_COMPILE=arm-linux-gnueabihf- *Linux other platforms (i.e. arm 64 bits) user* $ bin=/bin_path $ ctrlsw_include=/your_path_to_ctrlsw_include $ make EXTERNAL_INCLUDE=$ctrlsw_include BIN=$bin CROSS_COMPILE=aarch64-linux-gnu- *Compile against lib_encode / lib_decode you built* $ ctrlsw_src=/your_path_to_ctrlsw_src $ ctrlsw_lib=/your_path_to_ctrlsw_lib $ ctrlsw_include=/your_path_to_ctrlsw_include $ bin=/bin_path $ make EXTERNAL_SRC=$ctrlsw_src EXTERNAL_LIB=$ctrlsw_lib EXTERNAL_INCLUDE=$ctrlsw_include BIN=$bin vcu-omx-il-xilinx-v2020.2/base/000077500000000000000000000000001373706561700162275ustar00rootroot00000000000000vcu-omx-il-xilinx-v2020.2/base/omx_checker/000077500000000000000000000000001373706561700205165ustar00rootroot00000000000000vcu-omx-il-xilinx-v2020.2/base/omx_checker/omx_checker.cpp000066400000000000000000000200121373706561700235040ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_checker.h" static inline bool isStateLoaded(OMX_STATETYPE curState) { return curState == OMX_StateLoaded; } static inline bool isStateIdle(OMX_STATETYPE curState) { return curState == OMX_StateIdle; } static inline bool isStateExecuting(OMX_STATETYPE curState) { return curState == OMX_StateExecuting; } static inline bool isStatePause(OMX_STATETYPE curState) { return curState == OMX_StatePause; } static inline bool isStateWaitForResources(OMX_STATETYPE curState) { return curState == OMX_StateWaitForResources; } static inline bool isStateInvalid(OMX_STATETYPE curState) { return curState == OMX_StateInvalid; } void OMXChecker::CheckStateOperation(ComponentMethods methodName, OMX_STATETYPE curState) { switch(methodName) { case ComponentMethods::GetComponentVersion: { if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::SendCommand: { if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::GetParameter: { if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::SetParameter: { if(isStateIdle(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateExecuting(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStatePause(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::GetConfig: { if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::SetConfig: { if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::GetExtensionIndex: { if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::GetState: { break; } case ComponentMethods::ComponentTunnelRequest: { if(isStateIdle(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateExecuting(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStatePause(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateWaitForResources(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::UseBuffer: { // if(isStateIdle(curState)) // throw OMX_ErrorIncorrectStateOperation; // if(isStateExecuting(curState)) // throw OMX_ErrorIncorrectStateOperation; if(isStatePause(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::AllocateBuffer: { // if(isStateIdle(curState)) // throw OMX_ErrorIncorrectStateOperation; // if(isStateExecuting(curState)) // throw OMX_ErrorIncorrectStateOperation; if(isStatePause(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::FreeBuffer: { break; } case ComponentMethods::EmptyThisBuffer: { if(isStateLoaded(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateWaitForResources(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::FillThisBuffer: { if(isStateLoaded(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateWaitForResources(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::SetCallbacks: { if(isStateIdle(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateExecuting(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStatePause(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateWaitForResources(curState)) throw OMX_ErrorIncorrectStateOperation; if(isStateInvalid(curState)) throw OMX_ErrorInvalidState; break; } case ComponentMethods::ComponentDeinit: { break; } case ComponentMethods::UseEGLImage: { break; } case ComponentMethods::ComponentRoleEnum: { break; } default: throw OMX_ErrorUndefined; } } void OMXChecker::CheckStateTransition(OMX_STATETYPE curState, OMX_STATETYPE newState) { if(newState == curState) throw OMX_ErrorSameState; switch(curState) { case OMX_StateLoaded: { if(isStateExecuting(newState)) throw OMX_ErrorIncorrectStateTransition; if(isStatePause(newState)) throw OMX_ErrorIncorrectStateTransition; if(isStateInvalid(newState)) throw OMX_ErrorInvalidState; break; } case OMX_StateWaitForResources: { if(isStateExecuting(newState)) throw OMX_ErrorIncorrectStateTransition; if(isStatePause(newState)) throw OMX_ErrorIncorrectStateTransition; if(isStateInvalid(newState)) throw OMX_ErrorInvalidState; break; } case OMX_StateIdle: { if(isStateWaitForResources(newState)) throw OMX_ErrorIncorrectStateTransition; if(isStateInvalid(newState)) throw OMX_ErrorInvalidState; break; } case OMX_StateExecuting: { if(isStateWaitForResources(newState)) throw OMX_ErrorIncorrectStateTransition; if(isStateLoaded(newState)) throw OMX_ErrorIncorrectStateTransition; if(isStateInvalid(newState)) throw OMX_ErrorInvalidState; break; } case OMX_StatePause: { if(isStateWaitForResources(newState)) throw OMX_ErrorIncorrectStateTransition; if(isStateLoaded(newState)) throw OMX_ErrorIncorrectStateTransition; if(isStateInvalid(newState)) throw OMX_ErrorInvalidState; break; } default: throw OMX_ErrorUndefined; } } void OMXChecker::CheckStateExistance(OMX_STATETYPE state) { switch(state) { case OMX_StateLoaded: case OMX_StateIdle: case OMX_StateWaitForResources: case OMX_StateExecuting: case OMX_StatePause: case OMX_StateInvalid: return; default: throw OMX_ErrorBadParameter; } } vcu-omx-il-xilinx-v2020.2/base/omx_checker/omx_checker.h000066400000000000000000000134131373706561700231600ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include #include #include /*****************************************************************************/ struct OMXChecker { enum class ComponentMethods { GetComponentVersion, SendCommand, GetParameter, SetParameter, GetConfig, SetConfig, GetExtensionIndex, GetState, ComponentTunnelRequest, UseBuffer, AllocateBuffer, FreeBuffer, EmptyThisBuffer, FillThisBuffer, SetCallbacks, ComponentDeinit, UseEGLImage, ComponentRoleEnum, }; /*************************************************************************//*! \brief The CheckStateOperation method test if the OMX_Method can be called in the current state \param[in] methodName Name of the OMX_Method \param[in] curState Current component's state \throw OMX_ErrorInvalidState if the current state is invalid OMX_ErrorIncorrectStateOperation otherwise *****************************************************************************/ static void CheckStateOperation(ComponentMethods methodName, OMX_STATETYPE curState); /*************************************************************************//*! \brief The CheckStateExistance method test if the state exist \param[in] state \throw OMX_ErrorBadParameter if the state doesn't exist *****************************************************************************/ static void CheckStateExistance(OMX_STATETYPE state); /*************************************************************************//*! \brief The CheckStateTransition method test if the transition between old state and new state can be done \param[in] curState Current component's state \param[in] newState New component's state \throw OMX_ErrorSameState if the new state equal the current state OMX_ErrorIncorrectStateTransition otherwise *****************************************************************************/ static void CheckStateTransition(OMX_STATETYPE curState, OMX_STATETYPE newState); /*************************************************************************//*! \brief The CheckNotNull method test if the parameter send is not null \param[in] ptr Pointer \throw OMX_ErrorBadParameter if ptr is null *****************************************************************************/ template static inline void CheckNotNull(T const ptr) { if(!ptr) throw OMX_ErrorBadParameter; } /*************************************************************************//*! \brief The CheckNull method test if the parameter send is null \param[in] ptr Pointer \throw OMX_ErrorBadParameter if ptr is not null *****************************************************************************/ template static inline void CheckNull(T const ptr) { if(ptr) throw OMX_ErrorBadParameter; } /*************************************************************************//*! \brief The SetHeaderVersion method set the omx-il version header used. It also set to 0 everything else. \param[in] header *****************************************************************************/ template static inline void SetHeaderVersion(T& header) { memset(&header, 0x0, sizeof(T)); header.nSize = sizeof(header); header.nVersion.nVersion = OMX_VERSION; } /*************************************************************************//*! \brief The CheckHeader method check if the header is at the omx-il version used \param[in] version \throw OMX_ErrorVersionMismatch if version != OMX_VERSION *****************************************************************************/ static inline void CheckHeaderVersion(OMX_VERSIONTYPE version) { if(version.nVersion != OMX_VERSION) throw OMX_ErrorVersionMismatch; }; }; vcu-omx-il-xilinx-v2020.2/base/omx_checker/project.mk000066400000000000000000000002121373706561700225100ustar00rootroot00000000000000THIS.omx_checker:=$(call get-my-dir) OMX_CHECKER_SRCS+=\ $(THIS.omx_checker)/omx_checker.cpp UNITTESTS+=$(OMX_CHECKER_SRCS) vcu-omx-il-xilinx-v2020.2/base/omx_component/000077500000000000000000000000001373706561700211145ustar00rootroot00000000000000vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_buffer_handle.cpp000066400000000000000000000042101373706561700252640ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_buffer_handle.h" OMXBufferHandle::OMXBufferHandle(OMX_BUFFERHEADERTYPE* header) : BufferHandleInterface((char*)header->pBuffer, header->nAllocLen), header(header) { offset = header->nOffset; payload = header->nFilledLen; } OMXBufferHandle::~OMXBufferHandle() = default; vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_buffer_handle.h000066400000000000000000000041541373706561700247400ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include "module/buffer_handle_interface.h" #include struct OMXBufferHandle : BufferHandleInterface { explicit OMXBufferHandle(OMX_BUFFERHEADERTYPE* header); ~OMXBufferHandle() override; OMX_BUFFERHEADERTYPE* const header; }; vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_component.cpp000066400000000000000000002277671373706561700245320ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_component.h" #include "base/omx_checker/omx_checker.h" #include #include #include #include #include #include using namespace std; #define OMX_CATCH_PARAMETER_OR_CONFIG() \ } \ catch(OMX_ERRORTYPE& e) \ { \ LOG_ERROR(ToStringOMXIndex(index) + string { ": " } +ToStringOMXError(e)); \ return e; \ } \ void FORCE_SEMICOLON() static void ClearPropagatedData(OMX_BUFFERHEADERTYPE* header) { header->hMarkTargetComponent = nullptr; header->pMarkData = nullptr; header->nFilledLen = 0; header->nTickCount = 0; header->nFlags = 0; } void Component::ReturnEmptiedBuffer(OMX_BUFFERHEADERTYPE* emptied) { assert(emptied); auto header = emptied; ClearPropagatedData(header); if(callbacks.EmptyBufferDone) callbacks.EmptyBufferDone(component, app, header); } void nullDeleter(void*) { } static Task CreateTask(Command cmd, OMX_U32 data, shared_ptr opt) { Task task {}; task.cmd = cmd; task.data = reinterpret_cast(data); task.opt = opt; return task; } void Component::EmptyThisBufferCallBack(BufferHandleInterface* handle) { auto emptied = ((OMXBufferHandle*)(handle))->header; ReturnEmptiedBuffer(emptied); delete handle; } void Component::AssociateCallBack(BufferHandleInterface* empty, BufferHandleInterface* fill) { auto emptyHeader = (OMX_BUFFERHEADERTYPE*)((OMXBufferHandle*)(empty))->header; assert(emptyHeader); auto fillHeader = (OMX_BUFFERHEADERTYPE*)((OMXBufferHandle*)(fill))->header; assert(fillHeader); PropagateHeaderData(*emptyHeader, *fillHeader); if(IsEOSDetected(emptyHeader->nFlags)) callbacks.EventHandler(component, app, OMX_EventBufferFlag, output.index, emptyHeader->nFlags, nullptr); if(IsCompMarked(emptyHeader->hMarkTargetComponent, component)) callbacks.EventHandler(component, app, OMX_EventMark, 0, 0, emptyHeader->pMarkData); } void Component::ReturnFilledBuffer(OMX_BUFFERHEADERTYPE* filled, int offset, int size) { assert(filled); auto header = filled; header->nOffset = offset; header->nFilledLen = size; if(callbacks.FillBufferDone) callbacks.FillBufferDone(component, app, header); } void Component::FillThisBufferCallBack(BufferHandleInterface* filled) { auto header = ((OMXBufferHandle*)filled)->header; auto offset = ((OMXBufferHandle*)filled)->offset; auto payload = ((OMXBufferHandle*)filled)->payload; delete filled; ReturnFilledBuffer(header, offset, payload); } void Component::ReleaseCallBack(bool isInput, BufferHandleInterface* released) { auto header = ((OMXBufferHandle*)released)->header; delete released; if(isInput) ReturnEmptiedBuffer(header); else ReturnFilledBuffer(header, 0, 0); } static OMX_ERRORTYPE ToOmxError(ModuleInterface::ErrorType error) { switch(error) { case ModuleInterface::CHANNEL_CREATION_NO_CHANNEL_AVAILABLE: return static_cast(OMX_ALG_ErrorNoChannelLeft); case ModuleInterface::CHANNEL_CREATION_RESOURCE_UNAVAILABLE: return static_cast(OMX_ALG_ErrorChannelResourceUnavailable); case ModuleInterface::CHANNEL_CREATION_RESOURCE_FRAGMENTED: return static_cast(OMX_ALG_ErrorChannelResourceFragmented); case ModuleInterface::NO_MEMORY: return OMX_ErrorInsufficientResources; case ModuleInterface::BAD_PARAMETER: return OMX_ErrorBadParameter; default: return OMX_ErrorUndefined; } return OMX_ErrorUndefined; } void Component::EventCallBack(Callbacks::Event type, void* data) { assert(type <= Callbacks::Event::MAX); switch(type) { case Callbacks::Event::RESOLUTION_DETECTED: { LOG_IMPORTANT(ToStringCallbackEvent.at(type)); callbacks.EventHandler(component, app, OMX_EventPortSettingsChanged, 1, 0, nullptr); break; } case Callbacks::Event::RESOLUTION_CHANGED: { LOG_IMPORTANT(ToStringCallbackEvent.at(type)); auto dimension = static_cast*>(data); callbacks.EventHandler(component, app, static_cast(OMX_ALG_EventResolutionChanged), dimension->horizontal, dimension->vertical, nullptr); break; } case Callbacks::Event::ERROR: { ModuleInterface::ErrorType errorCode = static_cast((uintptr_t)data); processorMain->queue(CreateTask(Command::SetState, OMX_StateInvalid, shared_ptr((uintptr_t*)ToOmxError(errorCode), nullDeleter))); break; } default: LOG_ERROR(ToStringCallbackEvent.at(type) + string { " is unsupported" }); } } void Component::CheckPortIndex(int index) { if(index < static_cast(videoPortParams.nStartPortNumber)) throw OMX_ErrorBadPortIndex; auto maxIndex = static_cast(videoPortParams.nStartPortNumber + videoPortParams.nPorts - 1); if(index > maxIndex) throw OMX_ErrorBadPortIndex; } Port* Component::GetPort(int index) { CheckPortIndex(index); return IsInputPort(index) ? &input : &output; } static void AssociateSpecVersion(OMX_VERSIONTYPE& spec) { spec.s.nVersionMajor = OMX_VERSION_MAJOR; spec.s.nVersionMinor = OMX_VERSION_MINOR; spec.s.nRevision = OMX_VERSION_REVISION; spec.s.nStep = OMX_VERSION_STEP; } static BufferCounts MinBufferCounts(shared_ptr media) { BufferCounts bufferCounts {}; assert(media); media->Get(SETTINGS_INDEX_BUFFER_COUNTS, &bufferCounts); return bufferCounts; } static void SetPortsParam(OMX_PORT_PARAM_TYPE& portParams) { portParams.nPorts = VIDEO_PORTS_COUNT; portParams.nStartPortNumber = VIDEO_START_PORT; } Component::Component(OMX_HANDLETYPE component, shared_ptr media, unique_ptr&& module, std::unique_ptr&& expertise, OMX_STRING name, OMX_STRING role) : component{component}, media{media}, module{move(module)}, expertise{move(expertise)}, input{0, MinBufferCounts(media).input}, output{1, MinBufferCounts(media).output} { assert(name); assert(role); CreateName(name); CreateRole(role); shouldPrealloc = true; shouldClearROI = false; shouldPushROI = false; shouldFireEventPortSettingsChanges = true; version.nVersion = ALLEGRODVT_OMX_VERSION; AssociateSpecVersion(spec); OMXChecker::SetHeaderVersion(videoPortParams); SetPortsParam(videoPortParams); auto deleteEmpty = bind(&Component::_DeleteEmpty, this, placeholders::_1); auto deleteFill = bind(&Component::_DeleteFill, this, placeholders::_1); auto p = bind(&Component::_ProcessMain, this, placeholders::_1); auto p2 = bind(&Component::_ProcessFillBuffer, this, placeholders::_1); auto p3 = bind(&Component::_ProcessEmptyBuffer, this, placeholders::_1); processorMain.reset(new ProcessorFifo { p, nullptr, "OMX - Sched" }); processorFill.reset(new ProcessorFifo { p2, deleteFill, "OMX - Out" }); processorEmpty.reset(new ProcessorFifo { p3, deleteEmpty, "OMX - In" }); pauseFillPromise = nullptr; pauseEmptyPromise = nullptr; eosHandles.input = nullptr; eosHandles.output = nullptr; transientState = TransientState::Max; state = OMX_StateLoaded; } Component::~Component() { if(pauseFillPromise || pauseEmptyPromise) UnblockFillEmptyBuffers(); } void Component::CreateName(OMX_STRING name) { this->name = (OMX_STRING)malloc(OMX_MAX_STRINGNAME_SIZE * sizeof(char)); strncpy(this->name, name, OMX_MAX_STRINGNAME_SIZE); } void Component::CreateRole(OMX_STRING role) { this->role = (OMX_STRING)malloc(OMX_MAX_STRINGNAME_SIZE * sizeof(char)); strncpy(this->role, role, OMX_MAX_STRINGNAME_SIZE); } static TransientState GetTransientState(OMX_STATETYPE const& curState, OMX_STATETYPE const& nextState) { if(curState == OMX_StateLoaded && nextState == OMX_StateIdle) return TransientState::LoadedToIdle; if(curState == OMX_StateIdle && nextState == OMX_StatePause) return TransientState::IdleToPause; if(curState == OMX_StateIdle && nextState == OMX_StateLoaded) return TransientState::IdleToLoaded; if(curState == OMX_StateIdle && nextState == OMX_StateExecuting) return TransientState::IdleToExecuting; if(curState == OMX_StatePause && nextState == OMX_StateExecuting) return TransientState::PauseToExecuting; if(curState == OMX_StatePause && nextState == OMX_StateIdle) return TransientState::PauseToIdle; if(curState == OMX_StateExecuting && nextState == OMX_StateIdle) return TransientState::ExecutingToIdle; if(curState == OMX_StateExecuting && nextState == OMX_StatePause) return TransientState::ExecutingToPause; return TransientState::Max; } void Component::CreateCommand(OMX_COMMANDTYPE command, OMX_U32 param, OMX_PTR data) { Command taskCommand; switch(command) { case OMX_CommandStateSet: { OMXChecker::CheckNull(data); auto nextState = static_cast(param); OMXChecker::CheckStateExistance(nextState); TransientState NewtransientState = GetTransientState(state, nextState); if(NewtransientState == TransientState::LoadedToIdle) if(media && !media->Check()) throw OMX_ErrorUndefined; transientState = NewtransientState; taskCommand = Command::SetState; break; } case OMX_CommandFlush: { OMXChecker::CheckNull(data); if(param == OMX_ALL) { for(auto i = videoPortParams.nStartPortNumber; i < videoPortParams.nPorts; i++) processorMain->queue(CreateTask(Command::Flush, i, shared_ptr(data, nullDeleter))); return; } CheckPortIndex(param); taskCommand = Command::Flush; break; } case OMX_CommandPortDisable: { OMXChecker::CheckNull(data); if(param == OMX_ALL) { for(auto i = videoPortParams.nStartPortNumber; i < videoPortParams.nPorts; i++) { GetPort(i)->enable = false; GetPort(i)->isTransientToDisable = true; shouldFireEventPortSettingsChanges = true; processorMain->queue(CreateTask(Command::DisablePort, i, shared_ptr(data, nullDeleter))); } return; } CheckPortIndex(param); GetPort(param)->enable = false; GetPort(param)->isTransientToDisable = true; taskCommand = Command::DisablePort; shouldFireEventPortSettingsChanges = true; break; } case OMX_CommandPortEnable: { OMXChecker::CheckNull(data); if(param == OMX_ALL) { for(auto i = videoPortParams.nStartPortNumber; i < videoPortParams.nPorts; i++) { GetPort(i)->enable = true; GetPort(i)->isTransientToEnable = true; shouldFireEventPortSettingsChanges = false; processorMain->queue(CreateTask(Command::EnablePort, i, shared_ptr(data, nullDeleter))); } return; } CheckPortIndex(param); GetPort(param)->enable = true; GetPort(param)->isTransientToEnable = true; taskCommand = Command::EnablePort; shouldFireEventPortSettingsChanges = false; break; } case OMX_CommandMarkBuffer: { OMXChecker::CheckNotNull(data); if(!IsInputPort(param)) throw OMX_ErrorBadPortIndex; taskCommand = Command::MarkBuffer; break; } default: throw OMX_ErrorBadParameter; } processorMain->queue(CreateTask(taskCommand, param, shared_ptr(data, nullDeleter))); } OMX_ERRORTYPE Component::SendCommand(OMX_IN OMX_COMMANDTYPE cmd, OMX_IN OMX_U32 param, OMX_IN OMX_PTR data) { OMX_TRY(); OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::SendCommand, state); CreateCommand(cmd, param, data); return OMX_ErrorNone; OMX_CATCH(); } OMX_ERRORTYPE Component::GetState(OMX_OUT OMX_STATETYPE* state) { OMX_TRY(); OMXChecker::CheckNotNull(state); *state = this->state; return OMX_ErrorNone; OMX_CATCH(); } static OMX_ERRORTYPE StubEventHandler(OMX_IN OMX_HANDLETYPE, OMX_IN OMX_PTR, OMX_IN OMX_EVENTTYPE, OMX_IN OMX_U32, OMX_IN OMX_U32, OMX_IN OMX_PTR) { return OMX_ErrorNone; } OMX_ERRORTYPE Component::SetCallbacks(OMX_IN OMX_CALLBACKTYPE* callbacks, OMX_IN OMX_PTR app) { OMX_TRY(); OMXChecker::CheckNotNull(callbacks); OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::SetCallbacks, state); auto empty = bind(&Component::EmptyThisBufferCallBack, this, placeholders::_1); auto associate = bind(&Component::AssociateCallBack, this, placeholders::_1, placeholders::_2); auto filled = bind(&Component::FillThisBufferCallBack, this, placeholders::_1); auto event = bind(&Component::EventCallBack, this, placeholders::_1, placeholders::_2); auto release = bind(&Component::ReleaseCallBack, this, placeholders::_1, placeholders::_2); Callbacks cbs {}; cbs.emptied = empty; cbs.associate = associate; cbs.filled = filled; cbs.release = release; cbs.event = event; auto success = module->SetCallbacks(cbs); if(!success) throw OMX_ErrorUndefined; this->callbacks = *callbacks; if(this->callbacks.EventHandler == nullptr) this->callbacks.EventHandler = &StubEventHandler; this->app = app; return OMX_ErrorNone; OMX_CATCH(); } static void CheckVersionExistance(OMX_PTR ptr) { auto size = *static_cast(ptr); if(size < (sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE))) throw OMX_ErrorBadParameter; } static OMX_VERSIONTYPE GetVersion(OMX_PTR ptr) { CheckVersionExistance(ptr); auto tmp = ptr; tmp = static_cast(tmp) + 1; // nVersion is always after nSize return *static_cast(tmp); } OMX_ERRORTYPE Component::GetParameter(OMX_IN OMX_INDEXTYPE index, OMX_INOUT OMX_PTR param) { OMX_TRY(); OMXChecker::CheckNotNull(param); OMXChecker::CheckHeaderVersion(GetVersion(param)); OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::GetParameter, state); auto getCurrentPort = [=](OMX_PTR param) -> Port* { auto index = *(((OMX_U32*)param) + 2); return GetPort(index); }; switch(static_cast(index)) // all indexes are 32u { case OMX_IndexParamVideoInit: { *(OMX_PORT_PARAM_TYPE*)param = videoPortParams; return OMX_ErrorNone; } case OMX_IndexParamStandardComponentRole: { auto p = (OMX_PARAM_COMPONENTROLETYPE*)param; strncpy((char*)p->cRole, (char*)role, OMX_MAX_STRINGNAME_SIZE); return OMX_ErrorNone; } case OMX_IndexParamPortDefinition: { auto port = getCurrentPort(param); auto def = static_cast(param); return ConstructPortDefinition(*def, *port, media); } case OMX_IndexParamCompBufferSupplier: { auto port = getCurrentPort(param); auto s = static_cast(param); return ConstructPortSupplier(*s, *port); } case OMX_IndexParamVideoPortFormat: { auto p = (OMX_VIDEO_PARAM_PORTFORMATTYPE*)param; return GetVideoPortFormatSupported(*p, media); } case OMX_IndexParamVideoProfileLevelCurrent: { auto port = getCurrentPort(param); return expertise->GetProfileLevel(param, *port, media); } case OMX_IndexParamVideoProfileLevelQuerySupported: // GetParameter only { return expertise->GetProfileLevelSupported(param, media); } case OMX_IndexParamVideoAvc: case OMX_ALG_IndexParamVideoHevc: { auto port = getCurrentPort(param); return expertise->GetExpertise(param, *port, media); } case OMX_ALG_IndexParamReportedLatency: // GetParameter only { auto lat = static_cast(param); return ConstructReportedLatency(*lat, media); } case OMX_ALG_IndexPortParamEarlyCallback: { auto earlyCB = static_cast(param); auto port = getCurrentPort(param); return ConstructPortEarlyCallback(*earlyCB, *port, media); } case OMX_ALG_IndexPortParamBufferMode: { auto port = getCurrentPort(param); auto mode = static_cast(param); return ConstructPortBufferMode(*mode, *port, media); } case OMX_ALG_IndexParamVideoSubframe: { auto port = getCurrentPort(param); auto subframe = static_cast(param); return ConstructVideoSubframe(*subframe, *port, media); } // only encoder case OMX_IndexParamVideoQuantization: { auto port = getCurrentPort(param); auto q = static_cast(param); return ConstructVideoQuantization(*q, *port, media); } case OMX_IndexParamVideoBitrate: { auto port = getCurrentPort(param); auto b = static_cast(param); return ConstructVideoBitrate(*b, *port, media); } case OMX_ALG_IndexParamVideoInterlaceFormatSupported: // GetParameter only { auto port = getCurrentPort(param); auto interlace = static_cast(param); return ConstructVideoModesSupported(*interlace, *port, media); } case OMX_ALG_IndexParamVideoInterlaceFormatCurrent: { auto port = getCurrentPort(param); auto interlace = static_cast(param); return ConstructVideoModeCurrent(*interlace, *port, media); } case OMX_ALG_IndexParamVideoQuantizationControl: { auto port = getCurrentPort(param); auto q = static_cast(param); return ConstructVideoQuantizationControl(*q, *port, media); } case OMX_ALG_IndexParamVideoQuantizationExtension: { auto port = getCurrentPort(param); auto q = static_cast(param); return ConstructVideoQuantizationExtension(*q, *port, media); } case OMX_ALG_IndexParamVideoAspectRatio: { auto port = getCurrentPort(param); auto a = static_cast(param); return ConstructVideoAspectRatio(*a, *port, media); } case OMX_ALG_IndexParamVideoMaxBitrate: { auto port = getCurrentPort(param); auto b = static_cast(param); return ConstructVideoMaxBitrate(*b, *port, media); } case OMX_ALG_IndexParamVideoLowBandwidth: { auto port = getCurrentPort(param); auto bw = static_cast(param); return ConstructVideoLowBandwidth(*bw, *port, media); } case OMX_ALG_IndexParamVideoGopControl: { auto port = getCurrentPort(param); auto gc = static_cast(param); return ConstructVideoGopControl(*gc, *port, media); } case OMX_ALG_IndexParamVideoSceneChangeResilience: { auto port = getCurrentPort(param); auto r = static_cast(param); return ConstructVideoSceneChangeResilience(*r, *port, media); } case OMX_ALG_IndexParamVideoInstantaneousDecodingRefresh: { auto port = getCurrentPort(param); auto idr = static_cast(param); return ConstructVideoInstantaneousDecodingRefresh(*idr, *port, media); } case OMX_ALG_IndexParamVideoCodedPictureBuffer: { auto port = getCurrentPort(param); auto cpb = static_cast(param); return ConstructVideoCodedPictureBuffer(*cpb, *port, media); } case OMX_ALG_IndexParamVideoPrefetchBuffer: { auto port = getCurrentPort(param); auto pb = static_cast(param); return ConstructVideoPrefetchBuffer(*pb, *port, media); } case OMX_ALG_IndexParamVideoScalingList: { auto port = getCurrentPort(param); auto scl = static_cast(param); return ConstructVideoScalingList(*scl, *port, media); } case OMX_ALG_IndexParamVideoFillerData: { auto port = getCurrentPort(param); auto f = static_cast(param); return ConstructVideoFillerData(*f, *port, media); } case OMX_ALG_IndexParamVideoSlices: { auto port = getCurrentPort(param); auto s = static_cast(param); return ConstructVideoSlices(*s, *port, media); } case OMX_ALG_IndexParamVideoLongTerm: { auto port = getCurrentPort(param); auto longTerm = static_cast(param); return ConstructVideoLongTerm(*longTerm, *port, media); } case OMX_ALG_IndexParamVideoLookAhead: { auto port = getCurrentPort(param); auto la = static_cast(param); return ConstructVideoLookAhead(*la, *port, media); } case OMX_ALG_IndexParamVideoTwoPass: { auto port = getCurrentPort(param); auto tp = static_cast(param); return ConstructVideoTwoPass(*tp, *port, media); } case OMX_ALG_IndexParamVideoSkipFrame: { auto port = getCurrentPort(param); auto skip = static_cast(param); return ConstructVideoSkipFrame(*skip, *port, media); } case OMX_ALG_IndexParamVideoColorPrimaries: { auto port = getCurrentPort(param); auto c = static_cast(param); return ConstructVideoColorPrimaries(*c, *port, media); } case OMX_ALG_IndexParamVideoTransferCharacteristics: { auto port = getCurrentPort(param); auto tc = static_cast(param); return ConstructVideoTransferCharacteristics(*tc, *port, media); } case OMX_ALG_IndexParamVideoColorMatrix: { auto port = getCurrentPort(param); auto cm = static_cast(param); return ConstructVideoColorMatrix(*cm, *port, media); } case OMX_ALG_IndexParamVideoMaxPictureSize: { auto port = getCurrentPort(param); auto mps = static_cast(param); return ConstructVideoMaxPictureSize(*mps, *port, media); } case OMX_ALG_IndexParamVideoMaxPictureSizes: { auto port = getCurrentPort(param); auto mps = static_cast(param); return ConstructVideoMaxPictureSizes(*mps, *port, media); } // only decoder case OMX_ALG_IndexParamPreallocation: { auto prealloc = static_cast(param); return ConstructPreallocation(*prealloc, this->shouldPrealloc); } case OMX_ALG_IndexParamVideoDecodedPictureBuffer: { auto port = getCurrentPort(param); auto dpb = static_cast(param); return ConstructVideoDecodedPictureBuffer(*dpb, *port, media); } case OMX_ALG_IndexParamVideoInternalEntropyBuffers: { auto port = getCurrentPort(param); auto ieb = static_cast(param); return ConstructVideoInternalEntropyBuffers(*ieb, *port, media); } case OMX_ALG_IndexParamCommonSequencePictureModeQuerySupported: { auto mode = (OMX_ALG_COMMON_PARAM_SEQUENCE_PICTURE_MODE*)param; return ConstructCommonSequencePictureModesSupported(mode, media); } case OMX_ALG_IndexParamCommonSequencePictureModeCurrent: { auto port = getCurrentPort(param); auto mode = static_cast(param); return ConstructCommonSequencePictureMode(*mode, *port, media); } case OMX_ALG_IndexParamVideoInputParsed: { auto port = getCurrentPort(param); auto ip = static_cast(param); return ConstructVideoInputParsed(*ip, *port, media); } case OMX_ALG_IndexParamVideoLoopFilterBeta: { auto port = getCurrentPort(param); auto beta = static_cast(param); return ConstructVideoLoopFilterBeta(*beta, *port, media); } case OMX_ALG_IndexParamVideoLoopFilterTc: { auto port = getCurrentPort(param); auto tc = static_cast(param); return ConstructVideoLoopFilterTc(*tc, *port, media); } case OMX_ALG_IndexParamVideoQuantizationTable: { auto port = getCurrentPort(param); auto qpTable = static_cast(param); return ConstructVideoQuantizationTable(*qpTable, *port, media); } case OMX_ALG_IndexParamVideoAccessUnitDelimiter: { auto port = getCurrentPort(param); auto aud = static_cast(param); return ConstructVideoAccessUnitDelimiter(*aud, *port, media); } case OMX_ALG_IndexParamVideoBufferingPeriodSEI: { auto port = getCurrentPort(param); auto bpSEI = static_cast(param); return ConstructVideoBufferingPeriodSEI(*bpSEI, *port, media); } case OMX_ALG_IndexParamVideoPictureTimingSEI: { auto port = getCurrentPort(param); auto ptSEI = static_cast(param); return ConstructVideoPictureTimingSEI(*ptSEI, *port, media); } case OMX_ALG_IndexParamVideoRecoveryPointSEI: { auto port = getCurrentPort(param); auto rpSEI = static_cast(param); return ConstructVideoRecoveryPointSEI(*rpSEI, *port, media); } case OMX_ALG_IndexParamVideoMasteringDisplayColourVolumeSEI: { auto port = getCurrentPort(param); auto mdcvSEI = static_cast(param); return ConstructVideoMasteringDisplayColourVolumeSEI(*mdcvSEI, *port, media); } case OMX_ALG_IndexParamVideoContentLightLevelSEI: { auto port = getCurrentPort(param); auto cllSEI = static_cast(param); return ConstructVideoContentLightLevelSEI(*cllSEI, *port, media); } case OMX_ALG_IndexParamVideoST209410SEI: { auto port = getCurrentPort(param); auto st209410SEI = static_cast(param); return ConstructVideoST209410SEI(*st209410SEI, *port, media); } case OMX_ALG_IndexParamVideoST209440SEI: { auto port = getCurrentPort(param); auto st209440SEI = static_cast(param); return ConstructVideoST209440SEI(*st209440SEI, *port, media); } case OMX_ALG_IndexParamVideoRateControlPlugin: { auto port = getCurrentPort(param); auto rcp = static_cast(param); return ConstructVideoRateControlPlugin(*rcp, *port, media); } case OMX_ALG_IndexParamVideoCrop: { auto port = getCurrentPort(param); auto crop = static_cast(param); return ConstructVideoCrop(*crop, *port, media); } case OMX_ALG_IndexParamVideoMaxPictureSizesInBits: { auto port = getCurrentPort(param); auto mps = static_cast(param); return ConstructVideoMaxPictureSizesInBits(*mps, *port, media); } default: LOG_ERROR(ToStringOMXIndex(index) + string { " is unsupported" }); return OMX_ErrorUnsupportedIndex; } LOG_ERROR(ToStringOMXIndex(index) + string { " is unsupported" }); return OMX_ErrorUnsupportedIndex; OMX_CATCH_PARAMETER_OR_CONFIG(); } OMX_ERRORTYPE Component::SetParameter(OMX_IN OMX_INDEXTYPE index, OMX_IN OMX_PTR param) { OMX_TRY(); OMXChecker::CheckNotNull(param); OMXChecker::CheckHeaderVersion(GetVersion(param)); auto getCurrentPort = [=](OMX_PTR param) -> Port* { auto index = *(((OMX_U32*)param) + 2); return GetPort(index); }; Port* port = nullptr; shouldFireEventPortSettingsChanges = true; if(OMX_U32(index) != OMX_IndexParamStandardComponentRole) { port = getCurrentPort(param); if(!port->isTransientToDisable && port->enable) OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::SetParameter, state); } switch(static_cast(index)) // all indexes are 32u { case OMX_IndexParamStandardComponentRole: { OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::SetParameter, state); auto p = (OMX_PARAM_COMPONENTROLETYPE*)param; if(!strncmp((char*)role, (char*)p->cRole, strlen((char*)role))) { bool shouldUseLLP2EarlyCallback {}; media->Get(SETTINGS_INDEX_LLP2_EARLY_CB, &shouldUseLLP2EarlyCallback); media->Reset(); media->Set(SETTINGS_INDEX_LLP2_EARLY_CB, &shouldUseLLP2EarlyCallback); return OMX_ErrorNone; } throw OMX_ErrorBadParameter; } case OMX_IndexParamPortDefinition: { auto settings = static_cast(param); SetPortExpectedBuffer(*settings, const_cast(*port), media); return SetPortDefinition(*settings, *port, *module, media); } case OMX_IndexParamCompBufferSupplier: { // Do nothing return OMX_ErrorNone; } case OMX_ALG_IndexPortParamEarlyCallback: { auto earlyCB = static_cast(param); return SetPortEarlyCallback(*earlyCB, *port, media); } case OMX_IndexParamVideoPortFormat: { auto format = static_cast(param); return SetVideoPortFormat(*format, *port, media); } case OMX_IndexParamVideoProfileLevelCurrent: { return expertise->SetProfileLevel(param, *port, media); } case OMX_IndexParamVideoAvc: case OMX_ALG_IndexParamVideoHevc: { return expertise->SetExpertise(param, *port, media); } case OMX_ALG_IndexParamVideoSubframe: { auto subframe = static_cast(param); return SetVideoSubframe(*subframe, *port, media); } case OMX_ALG_IndexPortParamBufferMode: { auto portBufferMode = static_cast(param); return SetPortBufferMode(*portBufferMode, *port, media); } // only encoder case OMX_IndexParamVideoQuantization: { auto quantization = static_cast(param); return SetVideoQuantization(*quantization, *port, media); } case OMX_IndexParamVideoBitrate: { auto bitrate = static_cast(param); return SetVideoBitrate(*bitrate, *port, media); } case OMX_ALG_IndexParamVideoInterlaceFormatCurrent: { auto interlaced = static_cast(param); return SetVideoModeCurrent(*interlaced, *port, media); } case OMX_ALG_IndexParamVideoQuantizationControl: { auto quantizationControl = static_cast(param); return SetVideoQuantizationControl(*quantizationControl, *port, media); } case OMX_ALG_IndexParamVideoQuantizationExtension: { auto quantizationExtension = static_cast(param); return SetVideoQuantizationExtension(*quantizationExtension, *port, media); } case OMX_ALG_IndexParamVideoAspectRatio: { auto aspectRatio = static_cast(param); return SetVideoAspectRatio(*aspectRatio, *port, media); } case OMX_ALG_IndexParamVideoMaxBitrate: { auto maxBitrate = static_cast(param); return SetVideoMaxBitrate(*maxBitrate, *port, media); } case OMX_ALG_IndexParamVideoLowBandwidth: { auto lowBandwidth = static_cast(param); return SetVideoLowBandwidth(*lowBandwidth, *port, media); } case OMX_ALG_IndexParamVideoGopControl: { auto gopControl = static_cast(param); return SetVideoGopControl(*gopControl, *port, media); } case OMX_ALG_IndexParamVideoSceneChangeResilience: { auto sceneChangeResilience = static_cast(param); return SetVideoSceneChangeResilience(*sceneChangeResilience, *port, media); } case OMX_ALG_IndexParamVideoInstantaneousDecodingRefresh: { auto instantaneousDecodingRefresh = static_cast(param); return SetVideoInstantaneousDecodingRefresh(*instantaneousDecodingRefresh, *port, media); } case OMX_ALG_IndexParamVideoCodedPictureBuffer: { auto codedPictureBuffer = static_cast(param); return SetVideoCodedPictureBuffer(*codedPictureBuffer, *port, media); } case OMX_ALG_IndexParamVideoPrefetchBuffer: { auto prefetchBuffer = static_cast(param); return SetVideoPrefetchBuffer(*prefetchBuffer, *port, media); } case OMX_ALG_IndexParamVideoScalingList: { auto scalingList = static_cast(param); return SetVideoScalingList(*scalingList, *port, media); } case OMX_ALG_IndexParamVideoFillerData: { auto fillerData = static_cast(param); return SetVideoFillerData(*fillerData, *port, media); } case OMX_ALG_IndexParamVideoSlices: { auto slices = static_cast(param); return SetVideoSlices(*slices, *port, media); } case OMX_ALG_IndexParamVideoLongTerm: { auto longTerm = static_cast(param); return SetVideoLongTerm(*longTerm, *port, media); } case OMX_ALG_IndexParamVideoLookAhead: { auto la = static_cast(param); return SetVideoLookAhead(*la, *port, media); } case OMX_ALG_IndexParamVideoTwoPass: { auto tp = static_cast(param); return SetVideoTwoPass(*tp, *port, media); } case OMX_ALG_IndexParamVideoSkipFrame: { auto skipFrame = static_cast(param); return SetVideoSkipFrame(*skipFrame, *port, media); } case OMX_ALG_IndexParamVideoColorPrimaries: { auto c = static_cast(param); return SetVideoColorPrimaries(*c, *port, media); } case OMX_ALG_IndexParamVideoTransferCharacteristics: { auto c = static_cast(param); return SetVideoTransferCharacteristics(*c, *port, media); } case OMX_ALG_IndexParamVideoColorMatrix: { auto c = static_cast(param); return SetVideoColorMatrix(*c, *port, media); } case OMX_ALG_IndexParamVideoMaxPictureSize: { auto mps = static_cast(param); return SetVideoMaxPictureSize(*mps, *port, media); } case OMX_ALG_IndexParamVideoMaxPictureSizes: { auto mps = static_cast(param); return SetVideoMaxPictureSizes(*mps, *port, media); } case OMX_ALG_IndexParamVideoLoopFilterBeta: { auto lfb = static_cast(param); return SetVideoLoopFilterBeta(*lfb, *port, media); } case OMX_ALG_IndexParamVideoLoopFilterTc: { auto lftc = static_cast(param); return SetVideoLoopFilterTc(*lftc, *port, media); } // only decoder case OMX_ALG_IndexParamPreallocation: { auto p = (OMX_ALG_PARAM_PREALLOCATION*)param; this->shouldPrealloc = (p->bDisablePreallocation == OMX_FALSE); return OMX_ErrorNone; } case OMX_ALG_IndexParamVideoDecodedPictureBuffer: { auto dpb = static_cast(param); return SetVideoDecodedPictureBuffer(*dpb, *port, media); } case OMX_ALG_IndexParamVideoInternalEntropyBuffers: { auto ieb = static_cast(param); return SetVideoInternalEntropyBuffers(*ieb, *port, media); } case OMX_ALG_IndexParamCommonSequencePictureModeCurrent: { auto spm = static_cast(param); return SetCommonSequencePictureMode(*spm, *port, media); } case OMX_ALG_IndexParamVideoInputParsed: { auto ip = static_cast(param); return SetVideoInputParsed(*ip, *port, media); } case OMX_ALG_IndexParamVideoQuantizationTable: { auto table = static_cast(param); return SetVideoQuantizationTable(*table, *port, media); } case OMX_ALG_IndexParamVideoAccessUnitDelimiter: { auto aud = static_cast(param); return SetVideoAccessUnitDelimiter(*aud, *port, media); } case OMX_ALG_IndexParamVideoBufferingPeriodSEI: { auto bpSEI = static_cast(param); return SetVideoBufferingPeriodSEI(*bpSEI, *port, media); } case OMX_ALG_IndexParamVideoPictureTimingSEI: { auto ptSEI = static_cast(param); return SetVideoPictureTimingSEI(*ptSEI, *port, media); } case OMX_ALG_IndexParamVideoRecoveryPointSEI: { auto rpSEI = static_cast(param); return SetVideoRecoveryPointSEI(*rpSEI, *port, media); } case OMX_ALG_IndexParamVideoMasteringDisplayColourVolumeSEI: { auto mdcvSEI = static_cast(param); return SetVideoMasteringDisplayColourVolumeSEI(*mdcvSEI, *port, media); } case OMX_ALG_IndexParamVideoContentLightLevelSEI: { auto cllSEI = static_cast(param); return SetVideoContentLightLevelSEI(*cllSEI, *port, media); } case OMX_ALG_IndexParamVideoST209410SEI: { auto st209410 = static_cast(param); return SetVideoST209410SEI(*st209410, *port, media); } case OMX_ALG_IndexParamVideoST209440SEI: { auto st209440 = static_cast(param); return SetVideoST209440SEI(*st209440, *port, media); } case OMX_ALG_IndexParamVideoRateControlPlugin: { auto rcPlugin = static_cast(param); return SetVideoRateControlPlugin(*rcPlugin, *port, media); } case OMX_ALG_IndexParamVideoCrop: { auto crop = static_cast(param); return SetVideoCrop(*crop, *port, media); } case OMX_ALG_IndexParamVideoMaxPictureSizesInBits: { auto mps = static_cast(param); return SetVideoMaxPictureSizesInBits(*mps, *port, media); } default: LOG_ERROR(ToStringOMXIndex(index) + string { " is unsupported" }); return OMX_ErrorUnsupportedIndex; } LOG_ERROR(ToStringOMXIndex(index) + string { " is unsupported" }); return OMX_ErrorUnsupportedIndex; OMX_CATCH_PARAMETER_OR_CONFIG(); } static OMX_BUFFERHEADERTYPE* AllocateHeader(OMX_PTR app, int size, OMX_U8* buffer, bool isBufferAllocatedByModule, int index) { auto header = new OMX_BUFFERHEADERTYPE; OMXChecker::SetHeaderVersion(*header); header->pBuffer = buffer; header->nAllocLen = size; header->pAppPrivate = app; header->pInputPortPrivate = new bool(isBufferAllocatedByModule); header->pOutputPortPrivate = new bool(isBufferAllocatedByModule); auto& p = IsInputPort(index) ? header->nInputPortIndex : header->nOutputPortIndex; p = index; return header; } static inline bool isBufferAllocatedByModule(OMX_BUFFERHEADERTYPE const* header) { if(!header->pInputPortPrivate || !header->pOutputPortPrivate) return false; auto isInputAllocated = *(bool*)(header->pInputPortPrivate); auto isOutputAllocated = *(bool*)(header->pOutputPortPrivate); return isInputAllocated || isOutputAllocated; } static void DeleteHeader(OMX_BUFFERHEADERTYPE* header) { delete (bool*)header->pInputPortPrivate; delete (bool*)header->pOutputPortPrivate; delete header; } OMX_ERRORTYPE Component::UseBuffer(OMX_OUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN OMX_U32 size, OMX_IN OMX_U8* buffer) { OMX_TRY(); OMXChecker::CheckNotNull(header); OMXChecker::CheckNotNull(size); CheckPortIndex(index); auto port = GetPort(index); if(transientState != TransientState::LoadedToIdle && !(port->isTransientToEnable)) throw OMX_ErrorIncorrectStateOperation; *header = AllocateHeader(app, size, buffer, false, index); assert(*header); port->Add(*header); return OMX_ErrorNone; OMX_CATCH_L([&](OMX_ERRORTYPE& e) { if(e != OMX_ErrorBadPortIndex) GetPort(index)->ErrorOccured(); }); } OMX_ERRORTYPE Component::AllocateBuffer(OMX_INOUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN OMX_U32 size) { OMX_TRY(); OMXChecker::CheckNotNull(header); OMXChecker::CheckNotNull(size); CheckPortIndex(index); auto port = GetPort(index); if(transientState != TransientState::LoadedToIdle && !(port->isTransientToEnable)) throw OMX_ErrorIncorrectStateOperation; auto buffer = static_cast(module->Allocate(size * sizeof(OMX_U8))); if(!buffer) throw OMX_ErrorInsufficientResources; *header = AllocateHeader(app, size, buffer, true, index); assert(*header); port->Add(*header); return OMX_ErrorNone; OMX_CATCH_L([&](OMX_ERRORTYPE& e) { if(e != OMX_ErrorBadPortIndex) GetPort(index)->ErrorOccured(); }); } OMX_ERRORTYPE Component::FreeBuffer(OMX_IN OMX_U32 index, OMX_IN OMX_BUFFERHEADERTYPE* header) { OMX_TRY(); OMXChecker::CheckNotNull(header); CheckPortIndex(index); auto port = GetPort(index); if((transientState != TransientState::IdleToLoaded) && (!port->isTransientToDisable)) callbacks.EventHandler(component, app, OMX_EventError, OMX_ErrorPortUnpopulated, 0, nullptr); if(isBufferAllocatedByModule(header)) module->Free(header->pBuffer); port->Remove(header); DeleteHeader(header); return OMX_ErrorNone; OMX_CATCH_L([&](OMX_ERRORTYPE& e) { if(e != OMX_ErrorBadPortIndex) GetPort(index)->ErrorOccured(); }); } void Component::AttachMark(OMX_BUFFERHEADERTYPE* header) { assert(header); if(marks.empty()) return; if(header->hMarkTargetComponent) return; auto mark = marks.front(); header->hMarkTargetComponent = mark->hMarkTargetComponent; header->pMarkData = mark->pMarkData; marks.pop(); if(header->hMarkTargetComponent == component) callbacks.EventHandler(component, app, OMX_EventCmdComplete, OMX_CommandMarkBuffer, input.index, mark); } OMX_ERRORTYPE Component::EmptyThisBuffer(OMX_IN OMX_BUFFERHEADERTYPE* header) { OMX_TRY(); OMXChecker::CheckNotNull(header); OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::EmptyThisBuffer, state); CheckPortIndex(header->nInputPortIndex); processorMain->queue(CreateTask(Command::EmptyBuffer, static_cast(input.index), shared_ptr(header, nullDeleter))); return OMX_ErrorNone; OMX_CATCH(); } OMX_ERRORTYPE Component::FillThisBuffer(OMX_IN OMX_BUFFERHEADERTYPE* header) { OMX_TRY(); OMXChecker::CheckNotNull(header); OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::FillThisBuffer, state); CheckPortIndex(header->nOutputPortIndex); header->nTimeStamp = 0; header->hMarkTargetComponent = nullptr; header->pMarkData = nullptr; header->nFlags = 0; processorMain->queue(CreateTask(Command::FillBuffer, static_cast(output.index), shared_ptr(header, nullDeleter))); return OMX_ErrorNone; OMX_CATCH(); } void Component::ComponentDeInit() { if(eosHandles.input) { delete eosHandles.input; eosHandles.input = nullptr; } if(eosHandles.output) { delete eosHandles.output; eosHandles.output = nullptr; } free(role); free(name); } OMX_ERRORTYPE Component::GetComponentVersion(OMX_OUT OMX_STRING name, OMX_OUT OMX_VERSIONTYPE* version, OMX_OUT OMX_VERSIONTYPE* spec) { OMX_TRY(); OMXChecker::CheckNotNull(name); OMXChecker::CheckNotNull(version); OMXChecker::CheckNotNull(spec); OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::GetComponentVersion, state); strncpy(name, this->name, OMX_MAX_STRINGNAME_SIZE); *version = this->version; *spec = this->spec; return OMX_ErrorNone; OMX_CATCH(); } OMX_ERRORTYPE Component::GetConfig(OMX_IN OMX_INDEXTYPE index, OMX_INOUT OMX_PTR config) { OMX_TRY(); OMXChecker::CheckNotNull(config); OMXChecker::CheckHeaderVersion(GetVersion(config)); OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::GetConfig, state); switch(static_cast(index)) { case OMX_IndexConfigVideoBitrate: { auto& bitrate = *(static_cast(config)); module->GetDynamic(DYNAMIC_INDEX_BITRATE, &bitrate.nEncodeBitrate); return OMX_ErrorNone; } case OMX_IndexConfigVideoFramerate: { Clock clock; module->GetDynamic(DYNAMIC_INDEX_CLOCK, &clock); auto& framerate = *(static_cast(config)); framerate.xEncodeFramerate = ConvertMediaToOMXFramerate(clock); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoGroupOfPictures: { Gop moduleGop; module->GetDynamic(DYNAMIC_INDEX_GOP, &moduleGop); auto& gop = *(static_cast(config)); gop.nBFrames = ConvertMediaToOMXBFrames(moduleGop); gop.nPFrames = ConvertMediaToOMXPFrames(moduleGop); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoTransferCharacteristics: { TransferCharacteristicsType modTC; module->GetDynamic(DYNAMIC_INDEX_TRANSFER_CHARACTERISTICS, &modTC); auto& tc = *(static_cast(config)); tc.eTransferCharac = ConvertMediaToOMXTransferCharacteristics(modTC); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoColorMatrix: { ColourMatrixType modCM; module->GetDynamic(DYNAMIC_INDEX_COLOUR_MATRIX, &modCM); auto& cm = *(static_cast(config)); cm.eColorMatrix = ConvertMediaToOMXColourMatrix(modCM); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoColorPrimaries: { ColorPrimariesType modCP; module->GetDynamic(DYNAMIC_INDEX_COLOR_PRIMARIES, &modCP); auto& cp = *(static_cast(config)); cp.eColorPrimaries = ConvertMediaToOMXColorPrimaries(modCP); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoHighDynamicRangeSEI: { HighDynamicRangeSeis modHDRSEIs; module->GetDynamic(DYNAMIC_INDEX_HIGH_DYNAMIC_RANGE_SEIS, &modHDRSEIs); auto& hdrSEIs = *(static_cast(config)); hdrSEIs = ConvertMediaToOMXHDRSEI(modHDRSEIs); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoMaxResolutionChange: { Dimension maxDimensionSupported; module->GetDynamic(DYNAMIC_INDEX_MAX_RESOLUTION_CHANGE_SUPPORTED, &maxDimensionSupported); auto& dimension = *(static_cast(config)); dimension.nWidth = maxDimensionSupported.horizontal; dimension.nHeight = maxDimensionSupported.vertical; return OMX_ErrorNone; } default: LOG_ERROR(ToStringOMXIndex(index) + string { " is unsupported" }); return OMX_ErrorUnsupportedIndex; } LOG_ERROR(ToStringOMXIndex(index) + string { " is unsupported" }); return OMX_ErrorUnsupportedIndex; OMX_CATCH_PARAMETER_OR_CONFIG(); } OMX_ERRORTYPE Component::SetConfig(OMX_IN OMX_INDEXTYPE index, OMX_IN OMX_PTR config) { OMX_TRY(); OMXChecker::CheckNotNull(config); OMXChecker::CheckHeaderVersion(GetVersion(config)); OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::SetConfig, state); switch(static_cast(index)) { case OMX_IndexConfigVideoBitrate: { OMX_VIDEO_CONFIG_BITRATETYPE* bitrate = new OMX_VIDEO_CONFIG_BITRATETYPE; memcpy(bitrate, static_cast(config), sizeof(OMX_VIDEO_CONFIG_BITRATETYPE)); if(bitrate->nEncodeBitrate == 0) throw OMX_ErrorBadParameter; processorMain->queue(CreateTask(Command::SetDynamic, OMX_IndexConfigVideoBitrate, shared_ptr(bitrate))); return OMX_ErrorNone; } case OMX_IndexConfigVideoFramerate: { OMX_CONFIG_FRAMERATETYPE* framerate = new OMX_CONFIG_FRAMERATETYPE; memcpy(framerate, static_cast(config), sizeof(OMX_CONFIG_FRAMERATETYPE)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_IndexConfigVideoFramerate, shared_ptr(framerate))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoInsertInstantaneousDecodingRefresh: { OMX_ALG_VIDEO_CONFIG_INSERT* idr = new OMX_ALG_VIDEO_CONFIG_INSERT; memcpy(idr, static_cast(config), sizeof(OMX_ALG_VIDEO_CONFIG_INSERT)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoInsertInstantaneousDecodingRefresh, shared_ptr(idr))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoGroupOfPictures: { OMX_ALG_VIDEO_CONFIG_GROUP_OF_PICTURES* gop = new OMX_ALG_VIDEO_CONFIG_GROUP_OF_PICTURES; memcpy(gop, static_cast(config), sizeof(OMX_ALG_VIDEO_CONFIG_GROUP_OF_PICTURES)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoGroupOfPictures, shared_ptr(gop))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoRegionOfInterest: { OMX_ALG_VIDEO_CONFIG_REGION_OF_INTEREST* roi = new OMX_ALG_VIDEO_CONFIG_REGION_OF_INTEREST; memcpy(roi, static_cast(config), sizeof(OMX_ALG_VIDEO_CONFIG_REGION_OF_INTEREST)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoRegionOfInterest, shared_ptr(roi))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoRegionOfInterestByValue: { OMX_ALG_VIDEO_CONFIG_REGION_OF_INTEREST_BY_VALUE* roi = new OMX_ALG_VIDEO_CONFIG_REGION_OF_INTEREST_BY_VALUE; memcpy(roi, static_cast(config), sizeof(OMX_ALG_VIDEO_CONFIG_REGION_OF_INTEREST_BY_VALUE)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoRegionOfInterestByValue, shared_ptr(roi))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoNotifySceneChange: { OMX_ALG_VIDEO_CONFIG_NOTIFY_SCENE_CHANGE* notifySceneChange = new OMX_ALG_VIDEO_CONFIG_NOTIFY_SCENE_CHANGE; memcpy(notifySceneChange, static_cast(config), sizeof(OMX_ALG_VIDEO_CONFIG_NOTIFY_SCENE_CHANGE)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoNotifySceneChange, shared_ptr(notifySceneChange))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoInsertLongTerm: { OMX_ALG_VIDEO_CONFIG_INSERT* lt = new OMX_ALG_VIDEO_CONFIG_INSERT; memcpy(lt, static_cast(config), sizeof(OMX_ALG_VIDEO_CONFIG_INSERT)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoInsertLongTerm, shared_ptr(lt))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoUseLongTerm: { OMX_ALG_VIDEO_CONFIG_INSERT* lt = new OMX_ALG_VIDEO_CONFIG_INSERT; memcpy(lt, static_cast(config), sizeof(OMX_ALG_VIDEO_CONFIG_INSERT)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoUseLongTerm, shared_ptr(lt))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoInsertPrefixSEI: { OMX_ALG_VIDEO_CONFIG_SEI* userPrefixSei = static_cast(config); OMX_ALG_VIDEO_CONFIG_SEI* seiPrefix = new OMX_ALG_VIDEO_CONFIG_SEI {}; memcpy(seiPrefix, userPrefixSei, sizeof(OMX_ALG_VIDEO_CONFIG_SEI)); seiPrefix->pBuffer = new OMX_U8[userPrefixSei->nAllocLen] {}; memcpy(seiPrefix->pBuffer, userPrefixSei->pBuffer, userPrefixSei->nAllocLen); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoInsertPrefixSEI, shared_ptr(seiPrefix))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoInsertSuffixSEI: { OMX_ALG_VIDEO_CONFIG_SEI* userSuffixSei = static_cast(config); OMX_ALG_VIDEO_CONFIG_SEI* seiSuffix = new OMX_ALG_VIDEO_CONFIG_SEI {}; memcpy(seiSuffix, userSuffixSei, sizeof(OMX_ALG_VIDEO_CONFIG_SEI)); seiSuffix->pBuffer = new OMX_U8[userSuffixSei->nAllocLen] {}; memcpy(seiSuffix->pBuffer, userSuffixSei->pBuffer, userSuffixSei->nAllocLen); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoInsertSuffixSEI, shared_ptr(seiSuffix))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoHighDynamicRangeSEI: { OMX_ALG_VIDEO_CONFIG_HIGH_DYNAMIC_RANGE_SEI* hdrSEIS = new OMX_ALG_VIDEO_CONFIG_HIGH_DYNAMIC_RANGE_SEI {}; memcpy(hdrSEIS, static_cast(config), sizeof(OMX_ALG_VIDEO_CONFIG_HIGH_DYNAMIC_RANGE_SEI)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoHighDynamicRangeSEI, shared_ptr(hdrSEIS))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoNotifyResolutionChange: { OMX_ALG_VIDEO_CONFIG_NOTIFY_RESOLUTION_CHANGE* drc = new OMX_ALG_VIDEO_CONFIG_NOTIFY_RESOLUTION_CHANGE; memcpy(drc, static_cast(config), sizeof(OMX_ALG_VIDEO_CONFIG_NOTIFY_RESOLUTION_CHANGE)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoNotifyResolutionChange, shared_ptr(drc))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoQuantizationParameterTable: { QPs qps; media->Get(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &qps); OMX_ALG_VIDEO_CONFIG_DATA* userData = static_cast(config); OMX_ALG_VIDEO_CONFIG_DATA* data = new OMX_ALG_VIDEO_CONFIG_DATA {}; memcpy(data, userData, sizeof(OMX_ALG_VIDEO_CONFIG_DATA)); data->pBuffer = new OMX_U8[userData->nAllocLen] {}; memcpy(data->pBuffer, userData->pBuffer, userData->nAllocLen); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoQuantizationParameterTable, shared_ptr(data))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoLoopFilterBeta: { OMX_ALG_VIDEO_CONFIG_LOOP_FILTER_BETA* lfb = new OMX_ALG_VIDEO_CONFIG_LOOP_FILTER_BETA; memcpy(lfb, static_cast(config), sizeof(OMX_ALG_VIDEO_CONFIG_LOOP_FILTER_BETA)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoLoopFilterBeta, shared_ptr(lfb))); return OMX_ErrorNone; } case OMX_ALG_IndexConfigVideoLoopFilterTc: { OMX_ALG_VIDEO_CONFIG_LOOP_FILTER_TC* lftc = new OMX_ALG_VIDEO_CONFIG_LOOP_FILTER_TC; memcpy(lftc, static_cast(config), sizeof(OMX_ALG_VIDEO_CONFIG_LOOP_FILTER_TC)); processorMain->queue(CreateTask(Command::SetDynamic, OMX_ALG_IndexConfigVideoLoopFilterTc, shared_ptr(lftc))); return OMX_ErrorNone; } default: LOG_ERROR(ToStringOMXIndex(index) + string { " is unsupported" }); return OMX_ErrorUnsupportedIndex; } LOG_ERROR(ToStringOMXIndex(index) + string { " is unsupported" }); return OMX_ErrorUnsupportedIndex; OMX_CATCH_PARAMETER_OR_CONFIG(); } OMX_ERRORTYPE Component::GetExtensionIndex(OMX_IN OMX_STRING name, OMX_OUT OMX_INDEXTYPE* index) { OMX_TRY(); OMXChecker::CheckNotNull(name); OMXChecker::CheckNotNull(index); OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::GetExtensionIndex, state); return OMX_ErrorNoMore; OMX_CATCH(); } OMX_ERRORTYPE Component::ComponentTunnelRequest(OMX_IN OMX_U32 index, OMX_IN OMX_HANDLETYPE comp, OMX_IN OMX_U32 tunneledIndex, OMX_INOUT OMX_TUNNELSETUPTYPE* setup) { (void)index, (void)tunneledIndex, (void)comp, (void)setup; return OMX_ErrorNotImplemented; } OMX_ERRORTYPE Component::UseEGLImage(OMX_INOUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN void* eglImage) { (void)header, (void)index, (void)app, (void)eglImage; return OMX_ErrorNotImplemented; } OMX_ERRORTYPE Component::ComponentRoleEnum(OMX_OUT OMX_U8* role, OMX_IN OMX_U32 index) { OMX_TRY(); OMXChecker::CheckNotNull(role); OMXChecker::CheckStateOperation(OMXChecker::ComponentMethods::ComponentRoleEnum, state); if(index != 0) return OMX_ErrorNoMore; strncpy((OMX_STRING)role, this->role, OMX_MAX_STRINGNAME_SIZE); return OMX_ErrorNone; OMX_CATCH(); } static inline bool isTransitionToIdleFromLoadedOrWaitRessource(OMX_STATETYPE previousState, OMX_STATETYPE state) { if(state != OMX_StateIdle) return false; if((previousState != OMX_StateLoaded) && (previousState != OMX_StateWaitForResources)) return false; return true; } static inline bool isTransitionToLoaded(OMX_STATETYPE previousState, OMX_STATETYPE state) { if(state != OMX_StateLoaded) return false; if((previousState != OMX_StateIdle) && (previousState != OMX_StateWaitForResources)) return false; return true; } static inline bool isTransitionToExecutingOrPause(OMX_STATETYPE previousState, OMX_STATETYPE state) { if(state != OMX_StateExecuting && state != OMX_StatePause) return false; if(previousState != OMX_StateIdle) return false; return true; } static inline bool isTransitionToIdleFromExecutingOrPause(OMX_STATETYPE previousState, OMX_STATETYPE state) { if(state != OMX_StateIdle) return false; if((previousState != OMX_StateExecuting) && (previousState != OMX_StatePause)) return false; return true; } static inline bool isTransitionFromPause(OMX_STATETYPE previousState) { return previousState == OMX_StatePause; } static inline bool isTransitionToPause(OMX_STATETYPE previousState, OMX_STATETYPE state) { if(state != OMX_StatePause) return false; if((previousState != OMX_StateExecuting) && (previousState != OMX_StateIdle)) return false; return true; } void Component::PopulatingPorts() { for(auto i = videoPortParams.nStartPortNumber; i < videoPortParams.nPorts; i++) { auto port = GetPort(i); if(port->enable) port->WaitFull(); if(port->error) { port->ResetError(); throw OMX_ErrorInsufficientResources; } } } void Component::UnpopulatingPorts() { for(auto i = videoPortParams.nStartPortNumber; i < videoPortParams.nPorts; i++) { auto port = GetPort(i); port->WaitEmpty(); if(port->error) { port->ResetError(); throw OMX_ErrorUndefined; } } } void Component::FlushFillEmptyBuffers(bool fill, bool empty) { auto buffersFillBlocked = (pauseFillPromise != nullptr); auto buffersEmptyBlocked = (pauseEmptyPromise != nullptr); if(buffersFillBlocked || buffersEmptyBlocked) UnblockFillEmptyBuffers(); if(fill) { auto deleteFill = bind(&Component::_DeleteFill, this, placeholders::_1); auto processFill = bind(&Component::_ProcessFillBuffer, this, placeholders::_1); processorFill.reset(new ProcessorFifo { processFill, deleteFill, "OMX - Out" }); } if(empty) { auto deleteEmpty = bind(&Component::_DeleteEmpty, this, placeholders::_1); auto processEmpty = bind(&Component::_ProcessEmptyBuffer, this, placeholders::_1); processorEmpty.reset(new ProcessorFifo { processEmpty, deleteEmpty, "OMX - In" }); } if(buffersFillBlocked || buffersEmptyBlocked) BlockFillEmptyBuffers(buffersFillBlocked, buffersEmptyBlocked); } void Component::CleanFlushFillEmptyBuffers() { shared_ptr> signalPromise; signalPromise.reset(new promise ); processorFill->queue(CreateTask(Command::Signal, state, signalPromise)); signalPromise->get_future().wait(); signalPromise.reset(new promise ); processorEmpty->queue(CreateTask(Command::Signal, state, signalPromise)); signalPromise->get_future().wait(); } void Component::BlockFillEmptyBuffers(bool fill, bool empty) { if(fill && !pauseFillPromise) { pauseFillPromise.reset(new promise ); auto pauseFillFuture = make_shared>(pauseFillPromise->get_future()); processorFill->queue(CreateTask(Command::SharedFence, state, pauseFillFuture)); } if(empty && !pauseEmptyPromise) { pauseEmptyPromise.reset(new promise ); auto pauseEmptyFuture = make_shared>(pauseEmptyPromise->get_future()); processorEmpty->queue(CreateTask(Command::SharedFence, state, pauseEmptyFuture)); } } void Component::UnblockFillEmptyBuffers() { if(pauseFillPromise) { pauseFillPromise->set_value(); pauseFillPromise = nullptr; } if(pauseEmptyPromise) { pauseEmptyPromise->set_value(); pauseEmptyPromise = nullptr; } } void Component::FlushComponent() { FlushFillEmptyBuffers(true, true); } void Component::FlushEosHandles() { if(eosHandles.input) ReleaseCallBack(true, eosHandles.input); if(eosHandles.output) ReleaseCallBack(false, eosHandles.output); eosHandles.input = nullptr; eosHandles.output = nullptr; } static bool isFlushingRequired(OMX_STATETYPE prevState, OMX_STATETYPE newState) { try { OMXChecker::CheckStateExistance(prevState); OMXChecker::CheckStateExistance(newState); OMXChecker::CheckStateTransition(prevState, newState); auto transientState = GetTransientState(prevState, newState); if(transientState == TransientState::ExecutingToPause || transientState == TransientState::ExecutingToIdle || newState == OMX_StateInvalid) return true; return false; } catch(OMX_ERRORTYPE& e) { return false; } } void Component::TreatSetStateCommand(Task task) { try { assert(task.cmd == Command::SetState); auto newState = (OMX_STATETYPE)((uintptr_t)task.data); LOG_IMPORTANT(string { "Set State: " } +ToStringOMXState(newState)); OMXChecker::CheckStateTransition(state, newState); if(isTransitionToIdleFromLoadedOrWaitRessource(state, newState)) PopulatingPorts(); if(isTransitionToLoaded(state, newState) && (state != OMX_StateWaitForResources)) { UnpopulatingPorts(); transientState = TransientState::Max; } if(isTransitionToExecutingOrPause(state, newState)) { auto error = module->Start(shouldPrealloc); if(error) throw ToOmxError(error); if(shouldPrealloc && shouldFireEventPortSettingsChanges) { callbacks.EventHandler(component, app, static_cast(OMX_EventPortSettingsChanged), 1, 0, nullptr); shouldFireEventPortSettingsChanges = false; } } if(isTransitionToIdleFromExecutingOrPause(state, newState)) module->Stop(); if(isTransitionToPause(state, newState)) BlockFillEmptyBuffers(true, true); if(isTransitionFromPause(state) && input.enable && output.enable && !input.isTransientToEnable && !output.isTransientToEnable) UnblockFillEmptyBuffers(); state = newState; callbacks.EventHandler(component, app, OMX_EventCmdComplete, OMX_CommandStateSet, newState, nullptr); } catch(OMX_ERRORTYPE& e) { if(e == OMX_ErrorInvalidState) { module->Stop(); state = OMX_StateInvalid; } if(task.opt.get() != nullptr) e = (OMX_ERRORTYPE)((uintptr_t)task.opt.get()); LOG_ERROR(ToStringOMXError(e)); callbacks.EventHandler(component, app, OMX_EventError, e, 0, nullptr); } } void Component::TreatFlushCommand(Task task) { assert(task.cmd == Command::Flush); assert(task.opt.get() == nullptr); auto index = static_cast((uintptr_t)task.data); LOG_IMPORTANT(string { "Flush port: " } +to_string(index)); if(module->Stop()) module->Start(true); FlushEosHandles(); callbacks.EventHandler(component, app, OMX_EventCmdComplete, OMX_CommandFlush, index, nullptr); } void Component::TreatDisablePortCommand(Task task) { assert(task.cmd == Command::DisablePort); assert(task.opt.get() == nullptr); auto index = static_cast((uintptr_t)task.data); auto port = GetPort(index); if(!port->isTransientToDisable) { callbacks.EventHandler(component, app, OMX_EventCmdComplete, OMX_CommandPortDisable, index, nullptr); return; } bool isInput = IsInputPort(index); FlushFillEmptyBuffers(!isInput, isInput); BlockFillEmptyBuffers(true, shouldPrealloc); if(shouldPrealloc && shouldFireEventPortSettingsChanges && (state == OMX_StateExecuting || state == OMX_StatePause)) { if(module->Stop()) module->Start(true); if(shouldFireEventPortSettingsChanges) { callbacks.EventHandler(component, app, static_cast(OMX_EventPortSettingsChanged), 1, 0, nullptr); shouldFireEventPortSettingsChanges = false; } } port->WaitEmpty(); if(port->error) return; port->isTransientToDisable = false; callbacks.EventHandler(component, app, OMX_EventCmdComplete, OMX_CommandPortDisable, index, nullptr); } void Component::TreatEnablePortCommand(Task task) { assert(task.cmd == Command::EnablePort); assert(task.opt.get() == nullptr); auto index = static_cast((uintptr_t)task.data); auto port = GetPort(index); if(!port->isTransientToEnable) { callbacks.EventHandler(component, app, OMX_EventCmdComplete, OMX_CommandPortEnable, index, nullptr); return; } if(state != OMX_StateLoaded && state != OMX_StateWaitForResources) port->WaitFull(); if(port->error) return; port->isTransientToEnable = false; if(shouldPrealloc && shouldFireEventPortSettingsChanges && (state == OMX_StateExecuting || state == OMX_StatePause)) { if(module->Stop()) module->Start(true); if(shouldFireEventPortSettingsChanges) { callbacks.EventHandler(component, app, static_cast(OMX_EventPortSettingsChanged), 1, 0, nullptr); shouldFireEventPortSettingsChanges = false; } } if(input.enable && output.enable && !input.isTransientToEnable && !output.isTransientToEnable && state != OMX_StatePause) UnblockFillEmptyBuffers(); callbacks.EventHandler(component, app, OMX_EventCmdComplete, OMX_CommandPortEnable, index, nullptr); } void Component::TreatMarkBufferCommand(Task task) { assert(task.cmd == Command::MarkBuffer); assert(static_cast((uintptr_t)task.data) == input.index); auto mark = static_cast(task.opt.get()); assert(mark); marks.push(mark); } void Component::TreatEmptyBufferCommand(Task* task) { assert(task); assert(task->cmd == Command::EmptyBuffer); assert(static_cast((uintptr_t)task->data) == input.index); auto header = static_cast(task->opt.get()); assert(header); if(state == OMX_StateInvalid) { callbacks.EmptyBufferDone(component, app, header); return; } AttachMark(header); if(header->nFilledLen == 0) { if(header->nFlags & OMX_BUFFERFLAG_EOS) { auto handle = new OMXBufferHandle(header); eosHandles.input = handle; auto success = module->Empty(handle); assert(success); return; } callbacks.EmptyBufferDone(component, app, header); return; } auto handle = new OMXBufferHandle(header); auto success = module->Empty(handle); assert(success); if(header->nFlags & OMX_BUFFERFLAG_EOS) { success = module->Empty(nullptr); assert(success); return; } } void Component::TreatFillBufferCommand(Task task) { assert(task.cmd == Command::FillBuffer); assert(static_cast((uintptr_t)task.data) == output.index); auto header = static_cast(task.opt.get()); assert(header); if(state == OMX_StateInvalid) { callbacks.FillBufferDone(component, app, header); return; } auto handle = new OMXBufferHandle(header); if(!eosHandles.output) { eosHandles.output = handle; return; } auto success = module->Fill(handle); assert(success); } static RegionQuality CreateRegionQualityByPreset(OMX_ALG_VIDEO_CONFIG_REGION_OF_INTEREST const& roi) { RegionQuality rq {}; rq.region.point.x = roi.nLeft; rq.region.point.y = roi.nTop; rq.region.dimension.horizontal = roi.nWidth; rq.region.dimension.vertical = roi.nHeight; rq.quality.byPreset = ConvertOMXToMediaQualityPreset(roi.eQuality); return rq; } static RegionQuality CreateRegionQualityByValue(OMX_ALG_VIDEO_CONFIG_REGION_OF_INTEREST_BY_VALUE const& roi) { RegionQuality rq {}; rq.region.point.x = roi.nLeft; rq.region.point.y = roi.nTop; rq.region.dimension.horizontal = roi.nWidth; rq.region.dimension.vertical = roi.nHeight; rq.quality.byValue = ConvertOMXToMediaQualityValue(roi.nQuality); return rq; } void Component::TreatDynamicCommand(Task task) { assert(task.cmd == Command::SetDynamic); auto index = static_cast((uintptr_t)task.data); void* opt = task.opt.get(); assert(opt); if(state == OMX_StateInvalid) return; switch(index) { case OMX_IndexConfigVideoBitrate: { auto bitrate = static_cast(opt); module->SetDynamic(DYNAMIC_INDEX_BITRATE, (void*)(static_cast(bitrate->nEncodeBitrate))); return; } case OMX_IndexConfigVideoFramerate: { auto framerate = static_cast(opt); auto clock = ConvertOMXToMediaClock(framerate->xEncodeFramerate); Clock moduleClock {}; media->Get(SETTINGS_INDEX_CLOCK, &moduleClock); moduleClock.framerate = clock.framerate; moduleClock.clockratio = clock.clockratio; module->SetDynamic(DYNAMIC_INDEX_CLOCK, &moduleClock); return; } case OMX_ALG_IndexConfigVideoInsertInstantaneousDecodingRefresh: { module->SetDynamic(DYNAMIC_INDEX_INSERT_IDR, nullptr); return; } case OMX_ALG_IndexConfigVideoGroupOfPictures: { auto gop = static_cast(opt); Gop moduleGop {}; media->Get(SETTINGS_INDEX_GROUP_OF_PICTURES, &moduleGop); moduleGop.b = ConvertOMXToMediaBFrames(gop->nBFrames, gop->nPFrames); moduleGop.length = ConvertOMXToMediaGopLength(gop->nBFrames, gop->nPFrames); module->SetDynamic(DYNAMIC_INDEX_GOP, &moduleGop); return; } case OMX_ALG_IndexConfigVideoRegionOfInterest: { auto roi = static_cast(opt); if(shouldClearROI) { module->SetDynamic(DYNAMIC_INDEX_REGION_OF_INTEREST_QUALITY_CLEAR, nullptr); shouldClearROI = false; } auto rq = CreateRegionQualityByPreset(*roi); module->SetDynamic(DYNAMIC_INDEX_REGION_OF_INTEREST_QUALITY_ADD_BY_PRESET, &rq); shouldPushROI = true; return; } case OMX_ALG_IndexConfigVideoRegionOfInterestByValue: { auto roi = static_cast(opt); if(shouldClearROI) { module->SetDynamic(DYNAMIC_INDEX_REGION_OF_INTEREST_QUALITY_CLEAR, nullptr); shouldClearROI = false; } auto rq = CreateRegionQualityByValue(*roi); module->SetDynamic(DYNAMIC_INDEX_REGION_OF_INTEREST_QUALITY_ADD_BY_VALUE, &rq); shouldPushROI = true; return; } case OMX_ALG_IndexConfigVideoNotifySceneChange: { auto notifySceneChange = static_cast(opt); module->SetDynamic(DYNAMIC_INDEX_NOTIFY_SCENE_CHANGE, (void*)(static_cast(notifySceneChange->nLookAhead))); return; } case OMX_ALG_IndexConfigVideoInsertLongTerm: { module->SetDynamic(DYNAMIC_INDEX_IS_LONG_TERM, nullptr); return; } case OMX_ALG_IndexConfigVideoUseLongTerm: { module->SetDynamic(DYNAMIC_INDEX_USE_LONG_TERM, nullptr); return; } case OMX_ALG_IndexConfigVideoInsertPrefixSEI: { OMXSei prefix { *static_cast(opt), true }; tmpSeis.push_back(prefix); return; } case OMX_ALG_IndexConfigVideoInsertSuffixSEI: { OMXSei suffix { *static_cast(opt), false }; tmpSeis.push_back(suffix); return; } case OMX_ALG_IndexConfigVideoHighDynamicRangeSEI: { auto hdrSEIs = ConvertOMXToMediaHDRSEI(*static_cast(opt)); module->SetDynamic(DYNAMIC_INDEX_HIGH_DYNAMIC_RANGE_SEIS, &hdrSEIs); return; } case OMX_ALG_IndexConfigVideoNotifyResolutionChange: { Resolution resolution {}; auto ret = media->Get(SETTINGS_INDEX_RESOLUTION, &resolution); assert(ret == MediatypeInterface::SUCCESS); auto drc = static_cast(opt); resolution.dimension.horizontal = drc->nWidth; resolution.dimension.vertical = drc->nHeight; module->SetDynamic(DYNAMIC_INDEX_RESOLUTION, (void*)(&resolution)); return; } case OMX_ALG_IndexConfigVideoQuantizationParameterTable: { auto data = static_cast(opt); module->SetDynamic(DYNAMIC_INDEX_INSERT_QUANTIZATION_PARAMETER_BUFFER, data->pBuffer + data->nOffset); delete[] data->pBuffer; return; } case OMX_ALG_IndexConfigVideoLoopFilterBeta: { auto beta = static_cast(opt); module->SetDynamic(DYNAMIC_INDEX_LOOP_FILTER_BETA, (void*)(static_cast(beta->nLoopFilterBeta))); return; } case OMX_ALG_IndexConfigVideoLoopFilterTc: { auto tc = static_cast(opt); module->SetDynamic(DYNAMIC_INDEX_LOOP_FILTER_TC, (void*)(static_cast(tc->nLoopFilterTc))); return; } default: return; } } static void TreatSharedFenceCommand(Task* task) { auto p = (shared_future*)task->opt.get(); p->wait(); } static void TreatSignalCommand(Task* task) { auto p = (promise*)task->opt.get(); p->set_value(); } void Component::_ProcessMain(Task task) { switch(task.cmd) { case Command::SetState: { auto newState = (OMX_STATETYPE)((uintptr_t)task.data); if(isFlushingRequired(state, newState)) FlushFillEmptyBuffers(true, true); TreatSetStateCommand(task); break; } case Command::Flush: { FlushComponent(); TreatFlushCommand(task); break; } case Command::DisablePort: { TreatDisablePortCommand(task); break; } case Command::EnablePort: { TreatEnablePortCommand(task); break; } case Command::MarkBuffer: { TreatMarkBufferCommand(task); break; } case Command::EmptyBuffer: { auto index = static_cast((uintptr_t)task.data); assert(IsInputPort(index)); processorEmpty->queue(task); break; } case Command::FillBuffer: { auto index = static_cast((uintptr_t)task.data); assert(!IsInputPort(index)); processorFill->queue(task); break; } case Command::SetDynamic: { processorEmpty->queue(task); break; } default: assert(0 == "bad command"); } } void Component::_DeleteEmpty(Task task) { if(task.cmd != Command::EmptyBuffer) return; assert(static_cast((uintptr_t)task.data) == input.index); auto header = static_cast(task.opt.get()); assert(header); callbacks.EmptyBufferDone(component, app, header); } void Component::_DeleteFill(Task task) { if(task.cmd != Command::FillBuffer) return; assert(static_cast((uintptr_t)task.data) == output.index); auto header = static_cast(task.opt.get()); assert(header); callbacks.FillBufferDone(component, app, header); } void Component::_ProcessFillBuffer(Task task) { if(task.cmd == Command::FillBuffer) TreatFillBufferCommand(task); else if(task.cmd == Command::SharedFence) TreatSharedFenceCommand(&task); else if(task.cmd == Command::Signal) TreatSignalCommand(&task); else assert(0 == "bad command"); } void Component::_ProcessEmptyBuffer(Task task) { if(task.cmd == Command::EmptyBuffer) TreatEmptyBufferCommand(&task); else if(task.cmd == Command::SharedFence) TreatSharedFenceCommand(&task); else if(task.cmd == Command::Signal) TreatSignalCommand(&task); else if(task.cmd == Command::SetDynamic) TreatDynamicCommand(task); else assert(0 == "bad command"); } vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_component.h000066400000000000000000000202421373706561700241520ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include "omx_component_structs.h" #include "omx_component_interface.h" #include "module/module_interface.h" #include "module/mediatype_interface.h" #include #include "omx_buffer_handle.h" #include "omx_convert_omx_media.h" #include "omx_component_getset.h" #include "omx_expertise_interface.h" #include #include #include #include #include #include #include #include static OMX_U32 constexpr ALLEGRODVT_OMX_VERSION = 3; #define OMX_TRY() \ try \ { \ void FORCE_SEMICOLON() #define OMX_CATCH_L(f) \ } \ catch(OMX_ERRORTYPE& e) \ { \ LOG_ERROR(ToStringOMXError(e)); \ f(e); \ return e; \ } \ void FORCE_SEMICOLON() #define OMX_CATCH() \ } \ catch(OMX_ERRORTYPE& e) \ { \ LOG_ERROR(ToStringOMXError(e)); \ return e; \ } \ void FORCE_SEMICOLON() struct OMXSei { OMX_ALG_VIDEO_CONFIG_SEI configSei; bool isPrefix; }; struct Component : public OMXComponentInterface { Component(OMX_HANDLETYPE component, std::shared_ptr media, std::unique_ptr&& module, std::unique_ptr&& expertise, OMX_STRING name, OMX_STRING role); ~Component() override; OMX_ERRORTYPE SendCommand(OMX_IN OMX_COMMANDTYPE cmd, OMX_IN OMX_U32 param, OMX_IN OMX_PTR data) override; OMX_ERRORTYPE EmptyThisBuffer(OMX_IN OMX_BUFFERHEADERTYPE* header) override; OMX_ERRORTYPE FillThisBuffer(OMX_IN OMX_BUFFERHEADERTYPE* header) override; OMX_ERRORTYPE GetState(OMX_OUT OMX_STATETYPE* state) override; OMX_ERRORTYPE SetCallbacks(OMX_IN OMX_CALLBACKTYPE* callbacks, OMX_IN OMX_PTR app) override; virtual OMX_ERRORTYPE UseBuffer(OMX_OUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN OMX_U32 size, OMX_IN OMX_U8* buffer) override; virtual OMX_ERRORTYPE AllocateBuffer(OMX_INOUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN OMX_U32 size) override; virtual OMX_ERRORTYPE FreeBuffer(OMX_IN OMX_U32 index, OMX_IN OMX_BUFFERHEADERTYPE* header) override; void ComponentDeInit() override; OMX_ERRORTYPE GetComponentVersion(OMX_OUT OMX_STRING name, OMX_OUT OMX_VERSIONTYPE* version, OMX_OUT OMX_VERSIONTYPE* spec) override; OMX_ERRORTYPE GetParameter(OMX_IN OMX_INDEXTYPE index, OMX_INOUT OMX_PTR param) override; OMX_ERRORTYPE SetParameter(OMX_IN OMX_INDEXTYPE index, OMX_IN OMX_PTR param) override; OMX_ERRORTYPE GetExtensionIndex(OMX_IN OMX_STRING name, OMX_OUT OMX_INDEXTYPE* index) override; OMX_ERRORTYPE GetConfig(OMX_IN OMX_INDEXTYPE index, OMX_INOUT OMX_PTR config) override; OMX_ERRORTYPE SetConfig(OMX_IN OMX_INDEXTYPE index, OMX_IN OMX_PTR config) override; OMX_ERRORTYPE ComponentTunnelRequest(OMX_IN OMX_U32 index, OMX_IN OMX_HANDLETYPE comp, OMX_IN OMX_U32 tunneledIndex, OMX_INOUT OMX_TUNNELSETUPTYPE* setup) override; OMX_ERRORTYPE UseEGLImage(OMX_INOUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN void* eglImage) override; OMX_ERRORTYPE ComponentRoleEnum(OMX_OUT OMX_U8* role, OMX_IN OMX_U32 index) override; protected: OMX_HANDLETYPE const component; std::shared_ptr media; std::unique_ptr module; std::unique_ptr expertise; Port input; Port output; bool shouldPrealloc; bool shouldClearROI; bool shouldPushROI; bool shouldFireEventPortSettingsChanges; std::vector tmpSeis; OMX_STRING name; OMX_STRING role; OMX_STATETYPE state; TransientState transientState; OMX_CALLBACKTYPE callbacks; OMX_PTR app; OMX_VERSIONTYPE version; OMX_VERSIONTYPE spec; OMX_PORT_PARAM_TYPE videoPortParams; std::queue marks; struct EOSHandles { BufferHandleInterface* input {}; BufferHandleInterface* output {}; }; EOSHandles eosHandles; std::unique_ptr> processorMain; std::unique_ptr> processorEmpty; std::unique_ptr> processorFill; std::shared_ptr> pauseFillPromise; std::shared_ptr> pauseEmptyPromise; void _ProcessMain(Task task); void _ProcessEmptyBuffer(Task task); void _DeleteEmpty(Task task); void _ProcessFillBuffer(Task task); void _DeleteFill(Task task); void CreateName(OMX_STRING name); void CreateRole(OMX_STRING role); void CheckPortIndex(int index); Port* GetPort(int index); void PopulatingPorts(); void UnpopulatingPorts(); void FlushFillEmptyBuffers(bool fill, bool empty); void CleanFlushFillEmptyBuffers(); void BlockFillEmptyBuffers(bool fill, bool empty); void UnblockFillEmptyBuffers(); void FlushEosHandles(); virtual void FlushComponent(); void CreateCommand(OMX_COMMANDTYPE command, OMX_U32 param, OMX_PTR data); void TreatSetStateCommand(Task task); void TreatFlushCommand(Task task); void TreatDisablePortCommand(Task task); void TreatEnablePortCommand(Task task); void TreatMarkBufferCommand(Task task); virtual void TreatEmptyBufferCommand(Task* task); void TreatFillBufferCommand(Task task); void TreatDynamicCommand(Task task); void AttachMark(OMX_BUFFERHEADERTYPE* header); virtual void EmptyThisBufferCallBack(BufferHandleInterface* emptied); virtual void AssociateCallBack(BufferHandleInterface* empty, BufferHandleInterface* fill); virtual void FillThisBufferCallBack(BufferHandleInterface* filled); virtual void ReleaseCallBack(bool isInput, BufferHandleInterface* buf); virtual void EventCallBack(Callbacks::Event type, void* data); void ReturnFilledBuffer(OMX_BUFFERHEADERTYPE* filled, int offset, int size); void ReturnEmptiedBuffer(OMX_BUFFERHEADERTYPE* emptied); }; static inline bool IsEOSDetected(OMX_U32 flags) { return flags & OMX_BUFFERFLAG_EOS; } static inline bool IsCompMarked(OMX_HANDLETYPE mark, OMX_HANDLETYPE component) { return mark == component; } static inline void PropagateHeaderData(OMX_BUFFERHEADERTYPE const& src, OMX_BUFFERHEADERTYPE& dst) { dst.hMarkTargetComponent = src.hMarkTargetComponent; dst.pMarkData = src.pMarkData; dst.nTickCount = src.nTickCount; dst.nTimeStamp = src.nTimeStamp; dst.nFlags = src.nFlags; } static int constexpr VIDEO_START_PORT = 0; static int constexpr VIDEO_PORTS_COUNT = 2; static inline bool IsInputPort(int index) { return index == VIDEO_START_PORT; } vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_component_dec.cpp000066400000000000000000000273411373706561700253270ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_component_dec.h" #include "omx_component_getset.h" #include #include #include #include #include #include #include "base/omx_checker/omx_checker.h" using namespace std; static DecModule& ToDecModule(ModuleInterface& module) { return dynamic_cast(module); } DecComponent::DecComponent(OMX_HANDLETYPE component, shared_ptr media, std::unique_ptr&& module, OMX_STRING name, OMX_STRING role, std::unique_ptr&& expertise) : Component{component, media, std::move(module), std::move(expertise), name, role}, shouldPropagateData{true}, oldTimeStamp{-1} { } DecComponent::~DecComponent() = default; void DecComponent::EmptyThisBufferCallBack(BufferHandleInterface* handle) { assert(handle); auto header = (OMX_BUFFERHEADERTYPE*)((OMXBufferHandle*)handle)->header; ReturnEmptiedBuffer(header); delete handle; } void DecComponent::FlushComponent() { FlushFillEmptyBuffers(true, true); std::unique_lock lock(mutex); transmit.clear(); lock.unlock(); shouldPropagateData = true; } void DecComponent::AssociateCallBack(BufferHandleInterface* empty_, BufferHandleInterface* fill_) { std::lock_guard lock(mutex); if(empty_ == nullptr) { if(transmit.empty()) return; auto emptyHeader = transmit.front(); auto fill = (OMXBufferHandle*)(fill_); auto fillHeader = (OMX_BUFFERHEADERTYPE*)((OMXBufferHandle*)fill)->header; assert(fillHeader); fillHeader->hMarkTargetComponent = emptyHeader.hMarkTargetComponent; fillHeader->pMarkData = emptyHeader.pMarkData; fillHeader->nTickCount = emptyHeader.nTickCount; fillHeader->nTimeStamp = emptyHeader.nTimeStamp; transmit.pop_front(); if(IsEOSDetected(emptyHeader.nFlags)) { callbacks.EventHandler(component, app, OMX_EventBufferFlag, output.index, emptyHeader.nFlags, nullptr); transmit.clear(); shouldPropagateData = true; oldTimeStamp = -1; } if(IsCompMarked(emptyHeader.hMarkTargetComponent, component)) callbacks.EventHandler(component, app, OMX_EventMark, 0, 0, emptyHeader.pMarkData); return; } auto empty = (OMXBufferHandle*)(empty_); auto fill = (OMXBufferHandle*)(fill_); auto emptyHeader = empty->header; auto fillHeader = fill->header; PropagateHeaderData(*emptyHeader, *fillHeader); if(IsEOSDetected(emptyHeader->nFlags)) callbacks.EventHandler(component, app, OMX_EventBufferFlag, output.index, emptyHeader->nFlags, nullptr); if(IsCompMarked(emptyHeader->hMarkTargetComponent, component)) callbacks.EventHandler(component, app, OMX_EventMark, 0, 0, emptyHeader->pMarkData); } void DecComponent::FillThisBufferCallBack(BufferHandleInterface* filled) { if(!filled) { if(eosHandles.input && eosHandles.output) AssociateCallBack(eosHandles.input, eosHandles.output); if(eosHandles.input) EmptyThisBufferCallBack(eosHandles.input); if(eosHandles.output) FillThisBufferCallBack(eosHandles.output); eosHandles.input = nullptr; eosHandles.output = nullptr; return; } assert(filled); auto header = (OMX_BUFFERHEADERTYPE*)((OMXBufferHandle*)filled)->header; auto offset = ((OMXBufferHandle*)filled)->offset; auto payload = ((OMXBufferHandle*)filled)->payload; DisplayPictureInfo displayPictureInfo {}; auto err = module->GetDynamic(DYNAMIC_INDEX_CURRENT_DISPLAY_PICTURE_INFO, &displayPictureInfo); assert(err == ModuleInterface::SUCCESS); if(displayPictureInfo.concealed) header->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; switch(displayPictureInfo.type) { case 0: { // Do nothing : PROGRESSIVE break; } case 1: { header->nFlags |= OMX_ALG_BUFFERFLAG_TOP_FIELD; break; } case 2: { header->nFlags |= OMX_ALG_BUFFERFLAG_BOT_FIELD; break; } default: break; } if(offset == 0 && payload == 0) header->nFlags = OMX_BUFFERFLAG_EOS; else header->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; delete filled; ReturnFilledBuffer(header, offset, payload); } void DecComponent::EventCallBack(Callbacks::Event type, void* data) { assert(type < Callbacks::Event::MAX); switch(type) { case Callbacks::Event::SEI_PREFIX_PARSED: { LOG_IMPORTANT(ToStringCallbackEvent.at(type)); auto sei = static_cast(data); callbacks.EventHandler(component, app, static_cast(OMX_ALG_EventSEIPrefixParsed), sei->type, sei->payload, sei->data); break; } case Callbacks::Event::SEI_SUFFIX_PARSED: { LOG_IMPORTANT(ToStringCallbackEvent.at(type)); auto sei = static_cast(data); callbacks.EventHandler(component, app, static_cast(OMX_ALG_EventSEISuffixParsed), sei->type, sei->payload, sei->data); break; } default: Component::EventCallBack(type, data); break; } } static OMX_BUFFERHEADERTYPE* AllocateHeader(OMX_PTR app, int size, OMX_U8* buffer, bool isBufferAllocatedByModule, int index) { auto header = new OMX_BUFFERHEADERTYPE; OMXChecker::SetHeaderVersion(*header); header->pBuffer = buffer; header->nAllocLen = size; header->pAppPrivate = app; header->pInputPortPrivate = new bool(isBufferAllocatedByModule); header->pOutputPortPrivate = new bool(isBufferAllocatedByModule); auto& p = IsInputPort(index) ? header->nInputPortIndex : header->nOutputPortIndex; p = index; return header; } static void DeleteHeader(OMX_BUFFERHEADERTYPE* header) { delete static_cast(header->pInputPortPrivate); delete static_cast(header->pOutputPortPrivate); delete header; } OMX_ERRORTYPE DecComponent::AllocateBuffer(OMX_INOUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN OMX_U32 size) { OMX_TRY(); OMXChecker::CheckNotNull(header); OMXChecker::CheckNotNull(size); CheckPortIndex(index); auto port = GetPort(index); if(transientState != TransientState::LoadedToIdle && !(port->isTransientToEnable)) throw OMX_ErrorIncorrectStateOperation; BufferHandles handles; media->Get(SETTINGS_INDEX_BUFFER_HANDLES, &handles); auto bufferHandlePort = IsInputPort(index) ? handles.input : handles.output; bool dmaOnPort = (bufferHandlePort == BufferHandleType::BUFFER_HANDLE_FD); auto buffer = dmaOnPort ? reinterpret_cast(ToDecModule(*module).AllocateDMA(size * sizeof(OMX_U8))) : static_cast(module->Allocate(size * sizeof(OMX_U8))); if(dmaOnPort ? (static_cast((intptr_t)buffer) < 0) : !buffer) throw OMX_ErrorInsufficientResources; *header = AllocateHeader(app, size, buffer, true, index); assert(*header); port->Add(*header); return OMX_ErrorNone; OMX_CATCH_L([&](OMX_ERRORTYPE& e) { if(e != OMX_ErrorBadPortIndex) GetPort(index)->ErrorOccured(); }); } OMX_ERRORTYPE DecComponent::FreeBuffer(OMX_IN OMX_U32 index, OMX_IN OMX_BUFFERHEADERTYPE* header) { OMX_TRY(); OMXChecker::CheckNotNull(header); CheckPortIndex(index); auto port = GetPort(index); if((transientState != TransientState::IdleToLoaded) && (!port->isTransientToDisable)) callbacks.EventHandler(component, app, OMX_EventError, OMX_ErrorPortUnpopulated, 0, nullptr); BufferHandles handles; media->Get(SETTINGS_INDEX_BUFFER_HANDLES, &handles); auto bufferHandlePort = IsInputPort(index) ? handles.input : handles.output; bool dmaOnPort = (bufferHandlePort == BufferHandleType::BUFFER_HANDLE_FD); dmaOnPort ? ToDecModule(*module).FreeDMA(static_cast((intptr_t)header->pBuffer)) : module->Free(header->pBuffer); port->Remove(header); DeleteHeader(header); return OMX_ErrorNone; OMX_CATCH_L([&](OMX_ERRORTYPE& e) { if(e != OMX_ErrorBadPortIndex) GetPort(index)->ErrorOccured(); }); } static Flags CreateFlags(OMX_U32 nFlags) { Flags flags {}; if(nFlags & OMX_BUFFERFLAG_ENDOFFRAME) flags.isEndOfFrame = true; if(nFlags & OMX_BUFFERFLAG_ENDOFSUBFRAME) flags.isEndOfSlice = true; if(nFlags & OMX_BUFFERFLAG_SYNCFRAME) flags.isSync = true; return flags; } void DecComponent::TreatEmptyBufferCommand(Task* task) { std::lock_guard lock(mutex); assert(task); assert(task->cmd == Command::EmptyBuffer); assert(static_cast((intptr_t)task->data) == input.index); auto header = static_cast(task->opt.get()); assert(header); if(state == OMX_StateInvalid) { callbacks.EmptyBufferDone(component, app, header); return; } AttachMark(header); if(header->nFilledLen == 0) { if(header->nFlags & OMX_BUFFERFLAG_EOS) { auto handle = new OMXBufferHandle(header); eosHandles.input = handle; auto success = module->Empty(handle); assert(success); return; } callbacks.EmptyBufferDone(component, app, header); return; } bool isInputParsed; media->Get(SETTINGS_INDEX_INPUT_PARSED, &isInputParsed); bool isEarlyCallbackUsed; media->Get(SETTINGS_INDEX_LLP2_EARLY_CB, &isEarlyCallbackUsed); if(!isInputParsed || isEarlyCallbackUsed) { bool isEndOfFrameFlagRaised = (header->nFlags & OMX_BUFFERFLAG_ENDOFFRAME); if(isEndOfFrameFlagRaised && !isEarlyCallbackUsed) transmit.push_back(PropagatedData { header->hMarkTargetComponent, header->pMarkData, header->nTickCount, header->nTimeStamp, header->nFlags }); else { if(oldTimeStamp != header->nTimeStamp || shouldPropagateData) { transmit.push_back(PropagatedData { header->hMarkTargetComponent, header->pMarkData, header->nTickCount, header->nTimeStamp, header->nFlags }); oldTimeStamp = header->nTimeStamp; } shouldPropagateData = isEndOfFrameFlagRaised; } } auto flags = CreateFlags(header->nFlags); module->SetDynamic(DYNAMIC_INDEX_STREAM_FLAGS, &flags); auto handle = new OMXBufferHandle(header); auto success = module->Empty(handle); assert(success); if(header->nFlags & OMX_BUFFERFLAG_EOS) { success = module->Empty(nullptr); assert(success); return; } } vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_component_dec.h000066400000000000000000000067451373706561700250010ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include // buffer mode #include "omx_component.h" #include "module/module_dec.h" #include struct DecComponent final : Component { DecComponent(OMX_HANDLETYPE component, std::shared_ptr, std::unique_ptr&& module, OMX_STRING name, OMX_STRING role, std::unique_ptr&& expertise); ~DecComponent() override; OMX_ERRORTYPE AllocateBuffer(OMX_INOUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN OMX_U32 size) override; OMX_ERRORTYPE FreeBuffer(OMX_IN OMX_U32 index, OMX_IN OMX_BUFFERHEADERTYPE* header) override; private: struct PropagatedData { PropagatedData(OMX_HANDLETYPE hMarkTargetComponent, OMX_PTR pMarkData, OMX_U32 nTickCount, OMX_TICKS nTimeStamp, OMX_U32 nFlags) : hMarkTargetComponent{hMarkTargetComponent}, pMarkData{pMarkData}, nTickCount{nTickCount}, nTimeStamp{nTimeStamp}, nFlags{nFlags} { }; OMX_HANDLETYPE const hMarkTargetComponent; OMX_PTR const pMarkData; OMX_U32 const nTickCount; OMX_TICKS const nTimeStamp; OMX_U32 const nFlags; }; void EmptyThisBufferCallBack(BufferHandleInterface* handle) override; void AssociateCallBack(BufferHandleInterface* empty, BufferHandleInterface* fill) override; void FillThisBufferCallBack(BufferHandleInterface* filled) override; void EventCallBack(Callbacks::Event type, void* data) override; void FlushComponent() override; void TreatEmptyBufferCommand(Task* task) override; std::list transmit; std::mutex mutex; bool shouldPropagateData; OMX_TICKS oldTimeStamp; }; vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_component_enc.cpp000066400000000000000000000274011373706561700253360ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_component_enc.h" #include #include #include #include #include #include "omx_component_getset.h" #include "base/omx_checker/omx_checker.h" using namespace std; static EncModule& ToEncModule(ModuleInterface& module) { return dynamic_cast(module); } static BufferHandleType GetBufferHandlePort(shared_ptr media, OMX_IN OMX_U32 index) { BufferHandles handles; media->Get(SETTINGS_INDEX_BUFFER_HANDLES, &handles); auto bufferHandlePort = IsInputPort(index) ? handles.input : handles.output; return bufferHandlePort; } EncComponent::EncComponent(OMX_HANDLETYPE component, shared_ptr media, std::unique_ptr&& module, OMX_STRING name, OMX_STRING role, std::unique_ptr&& expertise) : Component{component, media, std::move(module), std::move(expertise), name, role} { } EncComponent::~EncComponent() = default; void EncComponent::EmptyThisBufferCallBack(BufferHandleInterface* handle) { assert(handle); auto header = ((OMXBufferHandle*)(handle))->header; delete handle; if(roiMap.Exist(header)) { auto roiBuffer = roiMap.Pop(header); roiFreeBuffers.push(roiBuffer); } ReturnEmptiedBuffer(header); } static void AddEncoderFlags(OMX_BUFFERHEADERTYPE* header, shared_ptr media, EncModule& module) { Flags flags; auto success = module.GetDynamic(DYNAMIC_INDEX_STREAM_FLAGS, &flags); assert(success == ModuleInterface::SUCCESS); if(flags.isEndOfFrame) header->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; if(flags.isEndOfSlice) header->nFlags |= OMX_BUFFERFLAG_ENDOFSUBFRAME; bool isSeparateConfigurationFromDataEnabled; auto ret = media->Get(SETTINGS_INDEX_SEPARATE_CONFIGURATION_FROM_DATA, &isSeparateConfigurationFromDataEnabled); assert(ret == MediatypeInterface::SUCCESS); if(flags.isConfig && isSeparateConfigurationFromDataEnabled) { /* Remove previous added flags. They are not needed for codec config. Only sync may be used */ header->nFlags = OMX_BUFFERFLAG_CODECCONFIG; } if(flags.isSync) header->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; } void EncComponent::AssociateCallBack(BufferHandleInterface* empty_, BufferHandleInterface* fill_) { auto empty = (OMXBufferHandle*)(empty_); auto fill = (OMXBufferHandle*)(fill_); auto emptyHeader = empty->header; auto fillHeader = fill->header; PropagateHeaderData(*emptyHeader, *fillHeader); AddEncoderFlags(fillHeader, media, ToEncModule(*module)); if(seisMap.Exist(empty_) && ((fillHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == 0)) { auto seis = seisMap.Pop(empty_); for(auto sei : seis) { Sei moduleSei {}; moduleSei.type = sei.configSei.nType; moduleSei.data = sei.configSei.pBuffer + sei.configSei.nOffset; moduleSei.payload = sei.configSei.nFilledLen; sei.isPrefix ? module->SetDynamic(DYNAMIC_INDEX_INSERT_PREFIX_SEI, &moduleSei) : module->SetDynamic(DYNAMIC_INDEX_INSERT_SUFFIX_SEI, &moduleSei); delete[]sei.configSei.pBuffer; } } if(IsEOSDetected(emptyHeader->nFlags)) callbacks.EventHandler(component, app, OMX_EventBufferFlag, output.index, emptyHeader->nFlags, nullptr); if(IsCompMarked(emptyHeader->hMarkTargetComponent, component)) callbacks.EventHandler(component, app, OMX_EventMark, 0, 0, emptyHeader->pMarkData); } void EncComponent::FillThisBufferCallBack(BufferHandleInterface* filled) { if(!filled) { if(eosHandles.input && eosHandles.output) AssociateCallBack(eosHandles.input, eosHandles.output); if(eosHandles.input) EmptyThisBufferCallBack(eosHandles.input); if(eosHandles.output) FillThisBufferCallBack(eosHandles.output); eosHandles.input = nullptr; eosHandles.output = nullptr; return; } assert(filled); auto header = (OMX_BUFFERHEADERTYPE*)(((OMXBufferHandle*)(filled))->header); auto offset = ((OMXBufferHandle*)filled)->offset; auto payload = ((OMXBufferHandle*)filled)->payload; bool isSkipped; auto err = module->GetDynamic(DYNAMIC_INDEX_SKIP_PICTURE, &isSkipped); assert(err == ModuleInterface::SUCCESS); if(isSkipped) header->nFlags |= OMX_BUFFERFLAG_SKIPFRAME; delete filled; ReturnFilledBuffer(header, offset, payload); } static OMX_BUFFERHEADERTYPE* AllocateHeader(OMX_PTR app, int size, OMX_U8* buffer, bool isBufferAllocatedByModule, int index) { auto header = new OMX_BUFFERHEADERTYPE; OMXChecker::SetHeaderVersion(*header); header->pBuffer = buffer; header->nAllocLen = size; header->pAppPrivate = app; header->pInputPortPrivate = new bool(isBufferAllocatedByModule); header->pOutputPortPrivate = new bool(isBufferAllocatedByModule); auto& p = IsInputPort(index) ? header->nInputPortIndex : header->nOutputPortIndex; p = index; return header; } static inline bool isBufferAllocatedByModule(OMX_BUFFERHEADERTYPE const* header) { if(!header->pInputPortPrivate || !header->pOutputPortPrivate) return false; auto isInputAllocated = *(static_cast(header->pInputPortPrivate)); auto isOutputAllocated = *(static_cast(header->pOutputPortPrivate)); return isInputAllocated || isOutputAllocated; } static void DeleteHeader(OMX_BUFFERHEADERTYPE* header) { delete static_cast(header->pInputPortPrivate); delete static_cast(header->pOutputPortPrivate); delete header; } uint8_t* EncComponent::AllocateROIBuffer() { int roiSize; module->GetDynamic(DYNAMIC_INDEX_REGION_OF_INTEREST_QUALITY_BUFFER_SIZE, &roiSize); return static_cast(calloc(roiSize, sizeof(uint8_t))); } OMX_ERRORTYPE EncComponent::UseBuffer(OMX_OUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN OMX_U32 size, OMX_IN OMX_U8* buffer) { OMX_TRY(); OMXChecker::CheckNotNull(header); OMXChecker::CheckNotNull(size); CheckPortIndex(index); auto port = GetPort(index); if(transientState != TransientState::LoadedToIdle && !(port->isTransientToEnable)) throw OMX_ErrorIncorrectStateOperation; *header = AllocateHeader(app, size, buffer, false, index); assert(*header); port->Add(*header); if(IsInputPort(index)) { auto roiBuffer = AllocateROIBuffer(); roiFreeBuffers.push(roiBuffer); roiDestroyMap.Add(*header, roiBuffer); } return OMX_ErrorNone; OMX_CATCH_L([&](OMX_ERRORTYPE& e) { if(e != OMX_ErrorBadPortIndex) GetPort(index)->ErrorOccured(); }); } OMX_ERRORTYPE EncComponent::AllocateBuffer(OMX_INOUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN OMX_U32 size) { OMX_TRY(); OMXChecker::CheckNotNull(header); OMXChecker::CheckNotNull(size); CheckPortIndex(index); auto port = GetPort(index); if(transientState != TransientState::LoadedToIdle && !(port->isTransientToEnable)) throw OMX_ErrorIncorrectStateOperation; auto bufferHandlePort = GetBufferHandlePort(media, index); bool dmaOnPort = (bufferHandlePort == BufferHandleType::BUFFER_HANDLE_FD); auto buffer = dmaOnPort ? reinterpret_cast(ToEncModule(*module).AllocateDMA(size * sizeof(OMX_U8))) : static_cast(module->Allocate(size * sizeof(OMX_U8))); if(dmaOnPort ? (static_cast((intptr_t)buffer) < 0) : !buffer) throw OMX_ErrorInsufficientResources; *header = AllocateHeader(app, size, buffer, true, index); assert(*header); port->Add(*header); if(IsInputPort(index)) { auto roiBuffer = AllocateROIBuffer(); roiFreeBuffers.push(roiBuffer); roiDestroyMap.Add(*header, roiBuffer); } return OMX_ErrorNone; OMX_CATCH_L([&](OMX_ERRORTYPE& e) { if(e != OMX_ErrorBadPortIndex) GetPort(index)->ErrorOccured(); }); } void EncComponent::DestroyROIBuffer(uint8_t* roiBuffer) { free(roiBuffer); } OMX_ERRORTYPE EncComponent::FreeBuffer(OMX_IN OMX_U32 index, OMX_IN OMX_BUFFERHEADERTYPE* header) { OMX_TRY(); OMXChecker::CheckNotNull(header); CheckPortIndex(index); auto port = GetPort(index); if((transientState != TransientState::IdleToLoaded) && (!port->isTransientToDisable)) callbacks.EventHandler(component, app, OMX_EventError, OMX_ErrorPortUnpopulated, 0, nullptr); if(isBufferAllocatedByModule(header)) { auto bufferHandlePort = GetBufferHandlePort(media, index); bool dmaOnPort = (bufferHandlePort == BufferHandleType::BUFFER_HANDLE_FD); dmaOnPort ? ToEncModule(*module).FreeDMA(static_cast((intptr_t)header->pBuffer)) : module->Free(header->pBuffer); } if(IsInputPort(index)) { if(roiDestroyMap.Exist(header)) { auto roiBuffer = roiDestroyMap.Pop(header); DestroyROIBuffer(roiBuffer); } } port->Remove(header); DeleteHeader(header); return OMX_ErrorNone; OMX_CATCH(); } void EncComponent::TreatEmptyBufferCommand(Task* task) { assert(task); assert(task->cmd == Command::EmptyBuffer); assert(static_cast((intptr_t)task->data) == input.index); auto header = static_cast(task->opt.get()); assert(header); if(state == OMX_StateInvalid) { callbacks.EmptyBufferDone(component, app, header); return; } AttachMark(header); if(header->nFilledLen == 0) { if(header->nFlags & OMX_BUFFERFLAG_EOS) { auto handle = new OMXBufferHandle(header); eosHandles.input = handle; auto success = module->Empty(handle); assert(success); return; } callbacks.EmptyBufferDone(component, app, header); return; } if(shouldPushROI && header->nFilledLen) { auto roiBuffer = roiFreeBuffers.pop(); module->GetDynamic(DYNAMIC_INDEX_REGION_OF_INTEREST_QUALITY_BUFFER_FILL, roiBuffer); module->SetDynamic(DYNAMIC_INDEX_REGION_OF_INTEREST_QUALITY_BUFFER_EMPTY, roiBuffer); roiMap.Add(header, roiBuffer); } auto handle = new OMXBufferHandle(header); seisMap.Add(handle, move(tmpSeis)); auto success = module->Empty(handle); assert(success); if(header->nFlags & OMX_BUFFERFLAG_EOS) { success = module->Empty(nullptr); assert(success); return; } shouldClearROI = true; } vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_component_enc.h000066400000000000000000000063211373706561700250010ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include #include "omx_component.h" #include "module/module_enc.h" struct EncComponent final : public Component { EncComponent(OMX_HANDLETYPE component, std::shared_ptr media, std::unique_ptr&& module, OMX_STRING name, OMX_STRING role, std::unique_ptr&& expertise); ~EncComponent() override; OMX_ERRORTYPE AllocateBuffer(OMX_INOUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN OMX_U32 size) override; OMX_ERRORTYPE UseBuffer(OMX_OUT OMX_BUFFERHEADERTYPE** header, OMX_IN OMX_U32 index, OMX_IN OMX_PTR app, OMX_IN OMX_U32 size, OMX_IN OMX_U8* buffer) override; OMX_ERRORTYPE FreeBuffer(OMX_IN OMX_U32 index, OMX_IN OMX_BUFFERHEADERTYPE* header) override; private: uint8_t* AllocateROIBuffer(); void DestroyROIBuffer(uint8_t* roiBuffer); void EmptyThisBufferCallBack(BufferHandleInterface* handle) override; void AssociateCallBack(BufferHandleInterface* empty, BufferHandleInterface* fill) override; void FillThisBufferCallBack(BufferHandleInterface* filled) override; void TreatEmptyBufferCommand(Task* task) override; locked_queue roiFreeBuffers; ThreadSafeMap roiMap; ThreadSafeMap roiDestroyMap; ThreadSafeMap> seisMap; }; vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_component_getset.cpp000066400000000000000000002143351373706561700260700ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_component_getset.h" #include "base/omx_checker/omx_checker.h" #include // max using namespace std; // Common OMX_ERRORTYPE ConstructPortSupplier(OMX_PARAM_BUFFERSUPPLIERTYPE& s, Port const& port) { OMXChecker::SetHeaderVersion(s); s.nPortIndex = port.index; s.eBufferSupplier = OMX_BufferSupplyUnspecified; // We don't care return OMX_ErrorNone; } OMX_ERRORTYPE ConstructReportedLatency(OMX_ALG_PARAM_REPORTED_LATENCY& lat, shared_ptr media) { OMXChecker::SetHeaderVersion(lat); auto ret = media->Get(SETTINGS_INDEX_LATENCY, &lat.nLatency); OMX_CHECK_MEDIA_GET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetPortExpectedBuffer(OMX_PARAM_PORTDEFINITIONTYPE const& settings, Port& port, shared_ptr media) { BufferCounts bufferCounts {}; media->Get(SETTINGS_INDEX_BUFFER_COUNTS, &bufferCounts); int const eosBuffer = 1; auto min = IsInputPort(settings.nPortIndex) ? bufferCounts.input : bufferCounts.output + eosBuffer; auto actual = static_cast(settings.nBufferCountActual); if(actual < min) throw OMX_ErrorBadParameter; port.setExpected(actual); return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoSubframe(OMX_ALG_VIDEO_PARAM_SUBFRAME& subframe, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(subframe); subframe.nPortIndex = port.index; bool isSubframeEnabled; auto ret = media->Get(SETTINGS_INDEX_SUBFRAME, &isSubframeEnabled); OMX_CHECK_MEDIA_GET(ret); subframe.bEnableSubframe = ConvertMediaToOMXBool(isSubframeEnabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetSubframe(OMX_BOOL enableSubframe, shared_ptr media) { auto isSubframeEnabled = ConvertOMXToMediaBool(enableSubframe); auto ret = media->Set(SETTINGS_INDEX_SUBFRAME, &isSubframeEnabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoSubframe(OMX_ALG_VIDEO_PARAM_SUBFRAME const& subframe, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_SUBFRAME rollback; ConstructVideoSubframe(rollback, port, media); auto ret = SetSubframe(subframe.bEnableSubframe, media); if(ret != OMX_ErrorNone) { SetVideoSubframe(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructPortBufferMode(OMX_ALG_PORT_PARAM_BUFFER_MODE& mode, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(mode); mode.nPortIndex = port.index; BufferHandles handles; auto ret = media->Get(SETTINGS_INDEX_BUFFER_HANDLES, &handles); OMX_CHECK_MEDIA_GET(ret); mode.eMode = IsInputPort(port.index) ? ConvertMediaToOMXBufferHandle(handles.input) : ConvertMediaToOMXBufferHandle(handles.output); return OMX_ErrorNone; } OMX_ERRORTYPE SetInputBufferMode(OMX_ALG_BUFFER_MODE mode, shared_ptr media) { BufferHandles handles; auto ret = media->Get(SETTINGS_INDEX_BUFFER_HANDLES, &handles); OMX_CHECK_MEDIA_GET(ret); handles.input = ConvertOMXToMediaBufferHandle(mode); ret = media->Set(SETTINGS_INDEX_BUFFER_HANDLES, &handles); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetOutputBufferMode(OMX_ALG_BUFFER_MODE mode, shared_ptr media) { BufferHandles handles; auto ret = media->Get(SETTINGS_INDEX_BUFFER_HANDLES, &handles); OMX_CHECK_MEDIA_GET(ret); handles.output = ConvertOMXToMediaBufferHandle(mode); ret = media->Set(SETTINGS_INDEX_BUFFER_HANDLES, &handles); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetPortBufferMode(OMX_ALG_PORT_PARAM_BUFFER_MODE const& portBufferMode, Port const& port, shared_ptr media) { OMX_ALG_PORT_PARAM_BUFFER_MODE rollback; ConstructPortBufferMode(rollback, port, media); auto& setBufferMode = IsInputPort(portBufferMode.nPortIndex) ? SetInputBufferMode : SetOutputBufferMode; auto ret = setBufferMode(portBufferMode.eMode, media); if(ret != OMX_ErrorNone) { SetPortBufferMode(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE GetVideoPortFormatSupported(OMX_VIDEO_PARAM_PORTFORMATTYPE& format, shared_ptr media) { SupportedFormats supportedFormats; auto ret = media->Get(SETTINGS_INDEX_FORMATS_SUPPORTED, &supportedFormats); OMX_CHECK_MEDIA_GET(ret); vector supported = IsInputPort(format.nPortIndex) ? supportedFormats.input : supportedFormats.output; if(format.nIndex >= supported.size()) return OMX_ErrorNoMore; Clock clock; Mimes mimes; ret = media->Get(SETTINGS_INDEX_CLOCK, &clock); OMX_CHECK_MEDIA_GET(ret); ret = media->Get(SETTINGS_INDEX_MIMES, &mimes); OMX_CHECK_MEDIA_GET(ret); Mime mime = IsInputPort(format.nPortIndex) ? mimes.input : mimes.output; format.eCompressionFormat = ConvertMediaToOMXCompression(mime.compression); format.eColorFormat = ConvertMediaToOMXColor(supported[format.nIndex].color, supported[format.nIndex].bitdepth); format.xFramerate = ConvertMediaToOMXFramerate(clock); return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoPortCurrentFormat(OMX_VIDEO_PARAM_PORTFORMATTYPE& f, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(f); f.nPortIndex = port.index; f.nIndex = 0; Format format; Clock clock; Mimes mimes; auto ret = media->Get(SETTINGS_INDEX_FORMAT, &format); OMX_CHECK_MEDIA_GET(ret); ret = media->Get(SETTINGS_INDEX_CLOCK, &clock); OMX_CHECK_MEDIA_GET(ret); ret = media->Get(SETTINGS_INDEX_MIMES, &mimes); OMX_CHECK_MEDIA_GET(ret); Mime mime = IsInputPort(f.nPortIndex) ? mimes.input : mimes.output; f.eCompressionFormat = ConvertMediaToOMXCompression(mime.compression); f.eColorFormat = ConvertMediaToOMXColor(format.color, format.bitdepth); f.xFramerate = ConvertMediaToOMXFramerate(clock); return OMX_ErrorNone; } static OMX_ERRORTYPE SetFormat(OMX_COLOR_FORMATTYPE const& color, shared_ptr media) { Format format; auto ret = media->Get(SETTINGS_INDEX_FORMAT, &format); OMX_CHECK_MEDIA_GET(ret); format.color = ConvertOMXToMediaColor(color); format.bitdepth = ConvertOMXToMediaBitdepth(color); ret = media->Set(SETTINGS_INDEX_FORMAT, &format); OMX_CHECK_MEDIA_SET(ret) return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoPortFormat(OMX_VIDEO_PARAM_PORTFORMATTYPE const& format, Port const& port, shared_ptr media) { OMX_VIDEO_PARAM_PORTFORMATTYPE rollback; ConstructVideoPortCurrentFormat(rollback, port, media); auto ret = SetClock(format.xFramerate, media); if(ret != OMX_ErrorNone) { SetVideoPortFormat(rollback, port, media); throw ret; } ret = SetFormat(format.eColorFormat, media); if(ret != OMX_ErrorNone) { SetVideoPortFormat(rollback, port, media); throw ret; } return OMX_ErrorNone; } static OMX_ERRORTYPE SetResolution(OMX_VIDEO_PORTDEFINITIONTYPE const& definition, shared_ptr media) { Resolution resolution; auto ret = media->Get(SETTINGS_INDEX_RESOLUTION, &resolution); OMX_CHECK_MEDIA_GET(ret); resolution.dimension.horizontal = definition.nFrameWidth; resolution.dimension.vertical = definition.nFrameHeight; resolution.stride.horizontal = definition.nStride; resolution.stride.vertical = definition.nSliceHeight; ret = media->Set(SETTINGS_INDEX_RESOLUTION, &resolution); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetClock(OMX_U32 framerateInQ16, shared_ptr media) { Clock curClock; auto ret = media->Get(SETTINGS_INDEX_CLOCK, &curClock); OMX_CHECK_MEDIA_GET(ret); auto clock = ConvertOMXToMediaClock(framerateInQ16); curClock.framerate = clock.framerate; curClock.clockratio = clock.clockratio; ret = media->Set(SETTINGS_INDEX_CLOCK, &curClock); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE ConstructPortDefinition(OMX_PARAM_PORTDEFINITIONTYPE& def, Port& port, shared_ptr media) { OMXChecker::SetHeaderVersion(def); def.nPortIndex = port.index; def.eDir = IsInputPort(def.nPortIndex) ? OMX_DirInput : OMX_DirOutput; BufferCounts bufferCounts {}; media->Get(SETTINGS_INDEX_BUFFER_COUNTS, &bufferCounts); int const eosBuffer = 1; int min = IsInputPort(def.nPortIndex) ? bufferCounts.input : bufferCounts.output + eosBuffer; if(port.getExpected() < min) port.setExpected(min); def.nBufferCountActual = port.getExpected(); def.bEnabled = ConvertMediaToOMXBool(port.enable); def.bPopulated = ConvertMediaToOMXBool(port.playable); def.nBufferCountMin = min; BufferSizes bufferSizes {}; media->Get(SETTINGS_INDEX_BUFFER_SIZES, &bufferSizes); def.nBufferSize = IsInputPort(def.nPortIndex) ? bufferSizes.input : bufferSizes.output; BufferContiguities bufferContiguities {}; media->Get(SETTINGS_INDEX_BUFFER_CONTIGUITIES, &bufferContiguities); def.bBuffersContiguous = ConvertMediaToOMXBool(IsInputPort(def.nPortIndex) ? bufferContiguities.input : bufferContiguities.output); BufferBytesAlignments bufferBytesAlignments {}; media->Get(SETTINGS_INDEX_BUFFER_BYTES_ALIGNMENTS, &bufferBytesAlignments); def.nBufferAlignment = IsInputPort(def.nPortIndex) ? bufferBytesAlignments.input : bufferBytesAlignments.output; def.eDomain = OMX_PortDomainVideo; auto& v = def.format.video; Format format {}; Clock clock {}; Mimes mimes {}; Bitrate bitrate {}; Resolution resolution {}; auto ret = media->Get(SETTINGS_INDEX_RESOLUTION, &resolution); OMX_CHECK_MEDIA_GET(ret); ret = media->Get(SETTINGS_INDEX_FORMAT, &format); OMX_CHECK_MEDIA_GET(ret); ret = media->Get(SETTINGS_INDEX_CLOCK, &clock); OMX_CHECK_MEDIA_GET(ret); ret = media->Get(SETTINGS_INDEX_MIMES, &mimes); OMX_CHECK_MEDIA_GET(ret); ret = media->Get(SETTINGS_INDEX_BITRATE, &bitrate); // Get Bitrate is encoder only if(ret == MediatypeInterface::BAD_INDEX) bitrate.target = 0; // 0 by default for Decoder auto mime = IsInputPort(def.nPortIndex) ? mimes.input : mimes.output; v.pNativeRender = 0; // XXX v.nFrameWidth = resolution.dimension.horizontal; v.nFrameHeight = resolution.dimension.vertical; v.nStride = resolution.stride.horizontal; v.nSliceHeight = resolution.stride.vertical; v.nBitrate = bitrate.target; v.xFramerate = ConvertMediaToOMXFramerate(clock); v.bFlagErrorConcealment = ConvertMediaToOMXBool(false); // XXX v.eCompressionFormat = ConvertMediaToOMXCompression(mime.compression); v.eColorFormat = ConvertMediaToOMXColor(format.color, format.bitdepth); v.cMIMEType = const_cast(mime.mime.c_str()); v.pNativeWindow = 0; // XXX return OMX_ErrorNone; } static OMX_ERRORTYPE SetTargetBitrate(OMX_U32 bitrate, shared_ptr media) { Bitrate curBitrate; auto ret = media->Get(SETTINGS_INDEX_BITRATE, &curBitrate); if(ret == MediatypeInterface::BAD_INDEX) return OMX_ErrorUnsupportedIndex; assert(ret == MediatypeInterface::SUCCESS); curBitrate.target = bitrate; if(curBitrate.max < curBitrate.target) curBitrate.max = curBitrate.target; ret = media->Set(SETTINGS_INDEX_BITRATE, &curBitrate); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetPortDefinition(OMX_PARAM_PORTDEFINITIONTYPE const& settings, Port& port, ModuleInterface& module, shared_ptr media) { OMX_PARAM_PORTDEFINITIONTYPE rollback; ConstructPortDefinition(rollback, port, media); auto video = settings.format.video; auto ret = SetFormat(video.eColorFormat, media); if(ret != OMX_ErrorNone) { SetPortDefinition(rollback, port, module, media); throw ret; } ret = SetClock(video.xFramerate, media); if(ret != OMX_ErrorNone) { SetPortDefinition(rollback, port, module, media); throw ret; } ret = SetResolution(video, media); if(ret != OMX_ErrorNone) { SetPortDefinition(rollback, port, module, media); throw ret; } // Set Target is only used for encoder, ignored for decoder ret = SetTargetBitrate(video.nBitrate, media); if(ret != OMX_ErrorNone && ret != OMX_ErrorUnsupportedIndex) { SetPortDefinition(rollback, port, module, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoLookAhead(OMX_ALG_VIDEO_PARAM_LOOKAHEAD& la, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(la); la.nPortIndex = port.index; LookAhead lookAhead; auto ret = media->Get(SETTINGS_INDEX_LOOKAHEAD, &lookAhead); OMX_CHECK_MEDIA_GET(ret); la.nLookAhead = lookAhead.lookAhead; la.bEnableFirstPassSceneChangeDetection = ConvertMediaToOMXBool(lookAhead.isFirstPassSceneChangeDetectionEnabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetLookAhead(OMX_U32 nLookAhead, OMX_BOOL enableFirstPassSceneChangeDetection, shared_ptr media) { LookAhead lookAhead; auto ret = media->Get(SETTINGS_INDEX_LOOKAHEAD, &lookAhead); OMX_CHECK_MEDIA_GET(ret); lookAhead.lookAhead = nLookAhead; lookAhead.isFirstPassSceneChangeDetectionEnabled = ConvertOMXToMediaBool(enableFirstPassSceneChangeDetection); ret = media->Set(SETTINGS_INDEX_LOOKAHEAD, &lookAhead); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoLookAhead(OMX_ALG_VIDEO_PARAM_LOOKAHEAD const& la, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_LOOKAHEAD rollback; ConstructVideoLookAhead(rollback, port, media); auto ret = SetLookAhead(la.nLookAhead, la.bEnableFirstPassSceneChangeDetection, media); if(ret != OMX_ErrorNone) { SetVideoLookAhead(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoTwoPass(OMX_ALG_VIDEO_PARAM_TWOPASS& tp, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(tp); tp.nPortIndex = port.index; TwoPass twopass; auto ret = media->Get(SETTINGS_INDEX_TWOPASS, &twopass); OMX_CHECK_MEDIA_GET(ret); tp.nPass = twopass.nPass; strncpy((char*)tp.cLogFile, twopass.sLogFile.c_str(), OMX_MAX_STRINGNAME_SIZE); return OMX_ErrorNone; } OMX_ERRORTYPE SetTwoPass(OMX_U32 nPass, OMX_U8 const cLogFile[OMX_MAX_STRINGNAME_SIZE], std::shared_ptr media) { TwoPass twopass; auto ret = media->Get(SETTINGS_INDEX_TWOPASS, &twopass); OMX_CHECK_MEDIA_GET(ret); twopass.nPass = nPass; twopass.sLogFile = string { (char*)cLogFile }; ret = media->Set(SETTINGS_INDEX_TWOPASS, &twopass); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoTwoPass(OMX_ALG_VIDEO_PARAM_TWOPASS const& tp, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_TWOPASS rollback; ConstructVideoTwoPass(rollback, port, media); auto ret = SetTwoPass(tp.nPass, tp.cLogFile, media); if(ret != OMX_ErrorNone) { SetVideoTwoPass(rollback, port, media); throw ret; } return OMX_ErrorNone; } // Encoder OMX_ERRORTYPE ConstructVideoBitrate(OMX_VIDEO_PARAM_BITRATETYPE& b, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(b); b.nPortIndex = port.index; Bitrate bitrate; auto ret = media->Get(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_GET(ret); b.eControlRate = ConvertMediaToOMXControlRate(bitrate.rateControl.mode); b.nTargetBitrate = bitrate.target; return OMX_ErrorNone; } static OMX_ERRORTYPE SetModeBitrate(OMX_U32 target, OMX_VIDEO_CONTROLRATETYPE mode, shared_ptr media) { Bitrate bitrate; auto ret = media->Get(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_GET(ret); bitrate.rateControl.mode = ConvertOMXToMediaControlRate(mode); bitrate.target = target; if(bitrate.max < bitrate.target) bitrate.max = bitrate.target; ret = media->Set(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoBitrate(OMX_VIDEO_PARAM_BITRATETYPE const& bitrate, Port const& port, shared_ptr media) { OMX_VIDEO_PARAM_BITRATETYPE rollback; ConstructVideoBitrate(rollback, port, media); auto ret = SetModeBitrate(bitrate.nTargetBitrate, bitrate.eControlRate, media); if(ret != OMX_ErrorNone) { SetVideoBitrate(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoQuantization(OMX_VIDEO_PARAM_QUANTIZATIONTYPE& q, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(q); q.nPortIndex = port.index; QPs qps; auto ret = media->Get(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &qps); OMX_CHECK_MEDIA_GET(ret); q.nQpI = ConvertMediaToOMXQpI(qps); q.nQpP = ConvertMediaToOMXQpP(qps); q.nQpB = ConvertMediaToOMXQpB(qps); return OMX_ErrorNone; } static OMX_ERRORTYPE SetQuantization(OMX_U32 qpI, OMX_U32 qpP, OMX_U32 qpB, shared_ptr media) { QPs curQPs; auto ret = media->Get(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &curQPs); OMX_CHECK_MEDIA_GET(ret); curQPs.initial = ConvertOMXToMediaQpInitial(qpI); curQPs.deltaIP = ConvertOMXToMediaQpDeltaIP(qpI, qpP); curQPs.deltaPB = ConvertOMXToMediaQpDeltaPB(qpP, qpB); ret = media->Set(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &curQPs); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoQuantization(OMX_VIDEO_PARAM_QUANTIZATIONTYPE const& quantization, Port const& port, shared_ptr media) { OMX_VIDEO_PARAM_QUANTIZATIONTYPE rollback; ConstructVideoQuantization(rollback, port, media); auto ret = SetQuantization(quantization.nQpI, quantization.nQpP, quantization.nQpB, media); if(ret != OMX_ErrorNone) { SetVideoQuantization(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoQuantizationControl(OMX_ALG_VIDEO_PARAM_QUANTIZATION_CONTROL& q, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(q); q.nPortIndex = port.index; QPs qps; auto ret = media->Get(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &qps); OMX_CHECK_MEDIA_GET(ret); q.eQpControlMode = ConvertMediaToOMXQpCtrlMode(qps.mode.ctrl); return OMX_ErrorNone; } static OMX_ERRORTYPE SetQuantizationControl(OMX_ALG_EQpCtrlMode const& mode, shared_ptr media) { QPs curQPs; auto ret = media->Get(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &curQPs); OMX_CHECK_MEDIA_GET(ret); curQPs.mode.ctrl = ConvertOMXToMediaQpCtrlMode(mode); ret = media->Set(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &curQPs); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoQuantizationControl(OMX_ALG_VIDEO_PARAM_QUANTIZATION_CONTROL const& quantizationControl, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_QUANTIZATION_CONTROL rollback; ConstructVideoQuantizationControl(rollback, port, media); auto ret = SetQuantizationControl(quantizationControl.eQpControlMode, media); if(ret != OMX_ErrorNone) { SetVideoQuantizationControl(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoQuantizationExtension(OMX_ALG_VIDEO_PARAM_QUANTIZATION_EXTENSION& q, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(q); q.nPortIndex = port.index; QPs qps; auto ret = media->Get(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &qps); OMX_CHECK_MEDIA_GET(ret); q.nQpMin = ConvertMediaToOMXQpMin(qps); q.nQpMax = ConvertMediaToOMXQpMax(qps); return OMX_ErrorNone; } static OMX_ERRORTYPE SetQuantizationExtension(OMX_S32 qpMin, OMX_S32 qpMax, shared_ptr media) { QPs curQPs; auto ret = media->Get(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &curQPs); OMX_CHECK_MEDIA_GET(ret); curQPs.min = ConvertOMXToMediaQpMin(qpMin); curQPs.max = ConvertOMXToMediaQpMax(qpMax); ret = media->Set(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &curQPs); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoQuantizationExtension(OMX_ALG_VIDEO_PARAM_QUANTIZATION_EXTENSION const& quantizationExtension, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_QUANTIZATION_EXTENSION rollback; ConstructVideoQuantizationExtension(rollback, port, media); auto ret = SetQuantizationExtension(quantizationExtension.nQpMin, quantizationExtension.nQpMax, media); if(ret != OMX_ErrorNone) { SetVideoQuantizationExtension(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoAspectRatio(OMX_ALG_VIDEO_PARAM_ASPECT_RATIO& a, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(a); a.nPortIndex = port.index; AspectRatioType aspectRatio; auto ret = media->Get(SETTINGS_INDEX_ASPECT_RATIO, &aspectRatio); OMX_CHECK_MEDIA_GET(ret); a.eAspectRatio = ConvertMediaToOMXAspectRatio(aspectRatio); return OMX_ErrorNone; } static OMX_ERRORTYPE SetAspectRatio(OMX_ALG_EAspectRatio const& aspectRatio, shared_ptr media) { auto ratio = ConvertOMXToMediaAspectRatio(aspectRatio); auto ret = media->Set(SETTINGS_INDEX_ASPECT_RATIO, &ratio); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoAspectRatio(OMX_ALG_VIDEO_PARAM_ASPECT_RATIO const& aspectRatio, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_ASPECT_RATIO rollback; ConstructVideoAspectRatio(rollback, port, media); auto ret = SetAspectRatio(aspectRatio.eAspectRatio, media); if(ret != OMX_ErrorNone) { SetVideoAspectRatio(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoMaxBitrate(OMX_ALG_VIDEO_PARAM_MAX_BITRATE& b, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(b); b.nPortIndex = port.index; Bitrate bitrate; auto ret = media->Get(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_GET(ret); b.nMaxBitrate = bitrate.max; b.nMaxQuality = bitrate.quality; return OMX_ErrorNone; } static OMX_ERRORTYPE SetMaxBitrate(OMX_U32 max, OMX_U32 quality, shared_ptr media) { Bitrate bitrate; auto ret = media->Get(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_GET(ret); bitrate.max = max; bitrate.quality = quality; if(bitrate.target > bitrate.max) bitrate.target = bitrate.max; ret = media->Set(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoMaxBitrate(OMX_ALG_VIDEO_PARAM_MAX_BITRATE const& maxBitrate, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_MAX_BITRATE rollback; ConstructVideoMaxBitrate(rollback, port, media); auto ret = SetMaxBitrate(maxBitrate.nMaxBitrate, maxBitrate.nMaxQuality, media); if(ret != OMX_ErrorNone) { SetVideoMaxBitrate(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoLowBandwidth(OMX_ALG_VIDEO_PARAM_LOW_BANDWIDTH& bw, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(bw); bw.nPortIndex = port.index; bool isLowBandwidthEnabled; auto ret = media->Get(SETTINGS_INDEX_LOW_BANDWIDTH, &isLowBandwidthEnabled); OMX_CHECK_MEDIA_GET(ret); bw.bEnableLowBandwidth = ConvertMediaToOMXBool(isLowBandwidthEnabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetLowBandwidth(OMX_BOOL enableLowBandwidth, shared_ptr media) { auto enabled = ConvertOMXToMediaBool(enableLowBandwidth); auto ret = media->Set(SETTINGS_INDEX_LOW_BANDWIDTH, &enabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoLowBandwidth(OMX_ALG_VIDEO_PARAM_LOW_BANDWIDTH const& lowBandwidth, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_LOW_BANDWIDTH rollback; ConstructVideoLowBandwidth(rollback, port, media); auto ret = SetLowBandwidth(lowBandwidth.bEnableLowBandwidth, media); if(ret != OMX_ErrorNone) { SetVideoLowBandwidth(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoGopControl(OMX_ALG_VIDEO_PARAM_GOP_CONTROL& gc, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(gc); gc.nPortIndex = port.index; Gop gop; auto ret = media->Get(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); OMX_CHECK_MEDIA_GET(ret); gc.eGopControlMode = ConvertMediaToOMXGopControl(gop.mode); gc.eGdrMode = ConvertMediaToOMXGdr(gop.gdr); return OMX_ErrorNone; } static OMX_ERRORTYPE SetGopControl(OMX_ALG_EGopCtrlMode const& mode, OMX_ALG_EGdrMode const& gdr, shared_ptr media) { Gop gop; auto ret = media->Get(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); OMX_CHECK_MEDIA_GET(ret); gop.mode = ConvertOMXToMediaGopControl(mode); gop.gdr = ConvertOMXToMediaGdr(gdr); ret = media->Set(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoGopControl(OMX_ALG_VIDEO_PARAM_GOP_CONTROL const& gopControl, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_GOP_CONTROL rollback; ConstructVideoGopControl(rollback, port, media); auto ret = SetGopControl(gopControl.eGopControlMode, gopControl.eGdrMode, media); if(ret != OMX_ErrorNone) { SetVideoGopControl(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoSceneChangeResilience(OMX_ALG_VIDEO_PARAM_SCENE_CHANGE_RESILIENCE& scr, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(scr); scr.nPortIndex = port.index; Bitrate bitrate; auto ret = media->Get(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_GET(ret); scr.bDisableSceneChangeResilience = ConvertMediaToOMXBool(!bitrate.rateControl.options.isSceneChangeResilienceEnabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetSceneChangeResilience(OMX_BOOL disableSceneChangeResilience, shared_ptr media) { Bitrate bitrate; auto ret = media->Get(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_GET(ret); bitrate.rateControl.options.isSceneChangeResilienceEnabled = !ConvertOMXToMediaBool(disableSceneChangeResilience); ret = media->Set(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoSceneChangeResilience(OMX_ALG_VIDEO_PARAM_SCENE_CHANGE_RESILIENCE const& sceneChangeResilience, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_SCENE_CHANGE_RESILIENCE rollback; ConstructVideoSceneChangeResilience(rollback, port, media); auto ret = SetSceneChangeResilience(sceneChangeResilience.bDisableSceneChangeResilience, media); if(ret != OMX_ErrorNone) { SetVideoSceneChangeResilience(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoSkipFrame(OMX_ALG_VIDEO_PARAM_SKIP_FRAME& skipFrame, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(skipFrame); skipFrame.nPortIndex = port.index; Bitrate bitrate; auto ret = media->Get(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_GET(ret); skipFrame.bEnableSkipFrame = ConvertMediaToOMXBool(bitrate.rateControl.options.isSkipEnabled); skipFrame.nMaxConsecutiveSkipFrame = bitrate.maxConsecutiveSkipFrame; return OMX_ErrorNone; } static OMX_ERRORTYPE SetSkipFrame(OMX_BOOL enableSkipFrame, OMX_U32 maxConsecutiveSkipFrame, shared_ptr media) { Bitrate bitrate; auto ret = media->Get(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_GET(ret); bitrate.rateControl.options.isSkipEnabled = ConvertOMXToMediaBool(enableSkipFrame); bitrate.maxConsecutiveSkipFrame = maxConsecutiveSkipFrame; ret = media->Set(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoSkipFrame(OMX_ALG_VIDEO_PARAM_SKIP_FRAME const& skipFrame, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_SKIP_FRAME rollback; ConstructVideoSkipFrame(rollback, port, media); auto ret = SetSkipFrame(skipFrame.bEnableSkipFrame, skipFrame.nMaxConsecutiveSkipFrame, media); if(ret != OMX_ErrorNone) { SetVideoSkipFrame(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoInstantaneousDecodingRefresh(OMX_ALG_VIDEO_PARAM_INSTANTANEOUS_DECODING_REFRESH& idr, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(idr); idr.nPortIndex = port.index; Gop gop; auto ret = media->Get(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); OMX_CHECK_MEDIA_GET(ret); idr.nInstantaneousDecodingRefreshFrequency = gop.idrFrequency; return OMX_ErrorNone; } static OMX_ERRORTYPE SetInstantaneousDecodingRefresh(OMX_U32 instantaneousDecodingRefreshFrequency, shared_ptr media) { Gop gop; auto ret = media->Get(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); OMX_CHECK_MEDIA_GET(ret); gop.idrFrequency = instantaneousDecodingRefreshFrequency; ret = media->Set(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoInstantaneousDecodingRefresh(OMX_ALG_VIDEO_PARAM_INSTANTANEOUS_DECODING_REFRESH const& instantaneousDecodingRefresh, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_INSTANTANEOUS_DECODING_REFRESH rollback; ConstructVideoInstantaneousDecodingRefresh(rollback, port, media); auto ret = SetInstantaneousDecodingRefresh(instantaneousDecodingRefresh.nInstantaneousDecodingRefreshFrequency, media); if(ret != OMX_ErrorNone) { SetVideoInstantaneousDecodingRefresh(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoPrefetchBuffer(OMX_ALG_VIDEO_PARAM_PREFETCH_BUFFER& pb, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(pb); pb.nPortIndex = port.index; bool isCacheLevel2Enabled; auto ret = media->Get(SETTINGS_INDEX_CACHE_LEVEL2, &isCacheLevel2Enabled); OMX_CHECK_MEDIA_GET(ret); pb.bEnablePrefetchBuffer = ConvertMediaToOMXBool(isCacheLevel2Enabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetPrefetchBuffer(OMX_BOOL enablePrefetchBuffer, shared_ptr media) { auto enabled = ConvertOMXToMediaBool(enablePrefetchBuffer); auto ret = media->Set(SETTINGS_INDEX_CACHE_LEVEL2, &enabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoPrefetchBuffer(OMX_ALG_VIDEO_PARAM_PREFETCH_BUFFER const& prefetchBuffer, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_PREFETCH_BUFFER rollback; ConstructVideoPrefetchBuffer(rollback, port, media); auto ret = SetPrefetchBuffer(prefetchBuffer.bEnablePrefetchBuffer, media); if(ret != OMX_ErrorNone) { SetVideoPrefetchBuffer(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoCodedPictureBuffer(OMX_ALG_VIDEO_PARAM_CODED_PICTURE_BUFFER& cpb, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(cpb); cpb.nPortIndex = port.index; Bitrate bitrate; auto ret = media->Get(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_GET(ret); cpb.nCodedPictureBufferSize = bitrate.cpb; cpb.nInitialRemovalDelay = bitrate.ird; return OMX_ErrorNone; } static OMX_ERRORTYPE SetCodedPictureBuffer(OMX_U32 codedPictureBufferSize, OMX_U32 initialRemovalDelay, shared_ptr media) { Bitrate bitrate; auto ret = media->Get(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_GET(ret); bitrate.cpb = codedPictureBufferSize; bitrate.ird = initialRemovalDelay; ret = media->Set(SETTINGS_INDEX_BITRATE, &bitrate); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoCodedPictureBuffer(OMX_ALG_VIDEO_PARAM_CODED_PICTURE_BUFFER const& codedPictureBuffer, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_CODED_PICTURE_BUFFER rollback; ConstructVideoCodedPictureBuffer(rollback, port, media); auto ret = SetCodedPictureBuffer(codedPictureBuffer.nCodedPictureBufferSize, codedPictureBuffer.nInitialRemovalDelay, media); if(ret != OMX_ErrorNone) { SetVideoCodedPictureBuffer(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoScalingList(OMX_ALG_VIDEO_PARAM_SCALING_LIST& scl, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(scl); scl.nPortIndex = port.index; ScalingListType scalingList; auto ret = media->Get(SETTINGS_INDEX_SCALING_LIST, &scalingList); OMX_CHECK_MEDIA_GET(ret); scl.eScalingListMode = ConvertMediaToOMXScalingList(scalingList); return OMX_ErrorNone; } static OMX_ERRORTYPE SetScalingList(OMX_ALG_EScalingList const& scalingListMode, shared_ptr media) { auto scalingList = ConvertOMXToMediaScalingList(scalingListMode); auto ret = media->Set(SETTINGS_INDEX_SCALING_LIST, &scalingList); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoScalingList(OMX_ALG_VIDEO_PARAM_SCALING_LIST const& scalingList, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_SCALING_LIST rollback; ConstructVideoScalingList(rollback, port, media); auto ret = SetScalingList(scalingList.eScalingListMode, media); if(ret != OMX_ErrorNone) { SetVideoScalingList(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoFillerData(OMX_ALG_VIDEO_PARAM_FILLER_DATA& f, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(f); f.nPortIndex = port.index; bool isFillerDataEnabled; auto ret = media->Get(SETTINGS_INDEX_FILLER_DATA, &isFillerDataEnabled); OMX_CHECK_MEDIA_GET(ret); f.bDisableFillerData = ConvertMediaToOMXBool(!isFillerDataEnabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetFillerData(OMX_BOOL disableFillerData, shared_ptr media) { auto enableFillerData = !ConvertOMXToMediaBool(disableFillerData); auto ret = media->Set(SETTINGS_INDEX_FILLER_DATA, &enableFillerData); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoFillerData(OMX_ALG_VIDEO_PARAM_FILLER_DATA const& fillerData, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_FILLER_DATA rollback; ConstructVideoFillerData(rollback, port, media); auto ret = SetFillerData(fillerData.bDisableFillerData, media); if(ret != OMX_ErrorNone) { SetVideoFillerData(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoSlices(OMX_ALG_VIDEO_PARAM_SLICES& s, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(s); s.nPortIndex = port.index; Slices slices; auto ret = media->Get(SETTINGS_INDEX_SLICE_PARAMETER, &slices); OMX_CHECK_MEDIA_GET(ret); s.nNumSlices = slices.num; s.nSlicesSize = slices.size; s.bDependentSlices = ConvertMediaToOMXBool(slices.dependent); return OMX_ErrorNone; } static OMX_ERRORTYPE SetSlices(OMX_U32 numSlices, OMX_U32 slicesSize, OMX_BOOL dependentSlices, shared_ptr media) { Slices slices; auto ret = media->Get(SETTINGS_INDEX_SLICE_PARAMETER, &slices); OMX_CHECK_MEDIA_GET(ret); slices.num = numSlices; slices.size = slicesSize; slices.dependent = ConvertOMXToMediaBool(dependentSlices); ret = media->Set(SETTINGS_INDEX_SLICE_PARAMETER, &slices); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoSlices(OMX_ALG_VIDEO_PARAM_SLICES const& slices, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_SLICES rollback; ConstructVideoSlices(rollback, port, media); auto ret = SetSlices(slices.nNumSlices, slices.nSlicesSize, slices.bDependentSlices, media); if(ret != OMX_ErrorNone) { SetVideoSlices(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoModesSupported(OMX_INTERLACEFORMATTYPE& interlace, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(interlace); interlace.nPortIndex = port.index; vector modes; auto ret = media->Get(SETTINGS_INDEX_VIDEO_MODES_SUPPORTED, &modes); OMX_CHECK_MEDIA_GET(ret); for(auto mode : modes) interlace.nFormat |= ConvertMediaToOMXInterlaceFlag(mode); return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoModeCurrent(OMX_INTERLACEFORMATTYPE& interlace, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(interlace); interlace.nPortIndex = port.index; VideoModeType videoMode; auto ret = media->Get(SETTINGS_INDEX_VIDEO_MODE, &videoMode); OMX_CHECK_MEDIA_GET(ret); interlace.nFormat = ConvertMediaToOMXInterlaceFlag(videoMode); return OMX_ErrorNone; } static OMX_ERRORTYPE SetInterlaceMode(OMX_U32 flag, shared_ptr media) { auto videoMode = ConvertOMXToMediaVideoMode(flag); auto ret = media->Set(SETTINGS_INDEX_VIDEO_MODE, &videoMode); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoModeCurrent(OMX_INTERLACEFORMATTYPE const& interlace, Port const& port, shared_ptr media) { OMX_INTERLACEFORMATTYPE rollback; ConstructVideoModeCurrent(rollback, port, media); auto ret = SetInterlaceMode(interlace.nFormat, media); if(ret != OMX_ErrorNone) { SetVideoModeCurrent(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoLongTerm(OMX_ALG_VIDEO_PARAM_LONG_TERM& longTerm, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(longTerm); longTerm.nPortIndex = port.index; Gop gop; auto ret = media->Get(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); OMX_CHECK_MEDIA_GET(ret); longTerm.bEnableLongTerm = ConvertMediaToOMXBool(gop.isLongTermEnabled); longTerm.nLongTermFrequency = gop.ltFrequency; return OMX_ErrorNone; } static OMX_ERRORTYPE SetLongTerm(OMX_BOOL isLongTermEnabled, OMX_S32 ltFrequency, shared_ptr media) { Gop gop; auto ret = media->Get(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); OMX_CHECK_MEDIA_GET(ret); gop.isLongTermEnabled = ConvertOMXToMediaBool(isLongTermEnabled); gop.ltFrequency = ltFrequency; ret = media->Set(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoLongTerm(OMX_ALG_VIDEO_PARAM_LONG_TERM const& longTerm, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_LONG_TERM rollback; ConstructVideoLongTerm(rollback, port, media); auto ret = SetLongTerm(longTerm.bEnableLongTerm, longTerm.nLongTermFrequency, media); if(ret != OMX_ErrorNone) { SetVideoLongTerm(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoColorPrimaries(OMX_ALG_VIDEO_PARAM_COLOR_PRIMARIES& colorPrimaries, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(colorPrimaries); colorPrimaries.nPortIndex = port.index; ColorPrimariesType colorPrimariesType {}; auto ret = media->Get(SETTINGS_INDEX_COLOR_PRIMARIES, &colorPrimariesType); OMX_CHECK_MEDIA_GET(ret); colorPrimaries.eColorPrimaries = ConvertMediaToOMXColorPrimaries(colorPrimariesType); return OMX_ErrorNone; } static OMX_ERRORTYPE SetColorPrimaries(OMX_ALG_VIDEO_COLOR_PRIMARIESTYPE colorPrimaries, shared_ptr media) { ColorPrimariesType colorPrimariesType {}; auto ret = media->Get(SETTINGS_INDEX_COLOR_PRIMARIES, &colorPrimariesType); OMX_CHECK_MEDIA_GET(ret); colorPrimariesType = ConvertOMXToMediaColorPrimaries(colorPrimaries); ret = media->Set(SETTINGS_INDEX_COLOR_PRIMARIES, &colorPrimariesType); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoColorPrimaries(OMX_ALG_VIDEO_PARAM_COLOR_PRIMARIES const& colorPrimaries, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_COLOR_PRIMARIES rollback; ConstructVideoColorPrimaries(rollback, port, media); auto ret = SetColorPrimaries(colorPrimaries.eColorPrimaries, media); if(ret != OMX_ErrorNone) { SetVideoColorPrimaries(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoTransferCharacteristics(OMX_ALG_VIDEO_PARAM_TRANSFER_CHARACTERISTICS& transferCharac, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(transferCharac); transferCharac.nPortIndex = port.index; TransferCharacteristicsType transferCharacType {}; auto ret = media->Get(SETTINGS_INDEX_TRANSFER_CHARACTERISTICS, &transferCharacType); OMX_CHECK_MEDIA_GET(ret); transferCharac.eTransferCharac = ConvertMediaToOMXTransferCharacteristics(transferCharacType); return OMX_ErrorNone; } static OMX_ERRORTYPE SetTransferCharacteristics(OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS transferCharac, shared_ptr media) { TransferCharacteristicsType transferCharacteristicsType {}; auto ret = media->Get(SETTINGS_INDEX_TRANSFER_CHARACTERISTICS, &transferCharacteristicsType); OMX_CHECK_MEDIA_GET(ret); transferCharacteristicsType = ConvertOMXToMediaTransferCharacteristics(transferCharac); ret = media->Set(SETTINGS_INDEX_TRANSFER_CHARACTERISTICS, &transferCharacteristicsType); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoTransferCharacteristics(OMX_ALG_VIDEO_PARAM_TRANSFER_CHARACTERISTICS const& transferCharac, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_TRANSFER_CHARACTERISTICS rollback; ConstructVideoTransferCharacteristics(rollback, port, media); auto ret = SetTransferCharacteristics(transferCharac.eTransferCharac, media); if(ret != OMX_ErrorNone) { SetVideoTransferCharacteristics(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoColorMatrix(OMX_ALG_VIDEO_PARAM_COLOR_MATRIX& colorMatrix, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(colorMatrix); colorMatrix.nPortIndex = port.index; ColourMatrixType colourMatrixType {}; auto ret = media->Get(SETTINGS_INDEX_COLOUR_MATRIX, &colourMatrixType); OMX_CHECK_MEDIA_GET(ret); colorMatrix.eColorMatrix = ConvertMediaToOMXColourMatrix(colourMatrixType); return OMX_ErrorNone; } static OMX_ERRORTYPE SetColorMatrix(OMX_ALG_VIDEO_COLOR_MATRIX colorMatrix, shared_ptr media) { ColourMatrixType colourMatrixType {}; auto ret = media->Get(SETTINGS_INDEX_COLOUR_MATRIX, &colourMatrixType); OMX_CHECK_MEDIA_GET(ret); colourMatrixType = ConvertOMXToMediaColourMatrix(colorMatrix); ret = media->Set(SETTINGS_INDEX_COLOUR_MATRIX, &colourMatrixType); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoColorMatrix(OMX_ALG_VIDEO_PARAM_COLOR_MATRIX const& colorMatrix, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_COLOR_MATRIX rollback; ConstructVideoColorMatrix(rollback, port, media); auto ret = SetColorMatrix(colorMatrix.eColorMatrix, media); if(ret != OMX_ErrorNone) { SetVideoColorMatrix(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoMaxPictureSizes(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZES& maxPictureSize, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(maxPictureSize); maxPictureSize.nPortIndex = port.index; MaxPicturesSizes mps; auto ret = media->Get(SETTINGS_INDEX_MAX_PICTURE_SIZES, &mps); OMX_CHECK_MEDIA_GET(ret); maxPictureSize.nMaxPictureSizeI = mps.i; maxPictureSize.nMaxPictureSizeP = mps.p; maxPictureSize.nMaxPictureSizeB = mps.b; return OMX_ErrorNone; } static OMX_ERRORTYPE SetMaxPictureSizes(OMX_S32 mpsI, OMX_S32 mpsP, OMX_S32 mpsB, shared_ptr media) { MaxPicturesSizes mps; mps.i = static_cast(mpsI); mps.p = static_cast(mpsP); mps.b = static_cast(mpsB); auto ret = media->Set(SETTINGS_INDEX_MAX_PICTURE_SIZES, &mps); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoMaxPictureSizes(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZES const& maxPictureSize, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZES rollback; ConstructVideoMaxPictureSizes(rollback, port, media); auto ret = SetMaxPictureSizes(maxPictureSize.nMaxPictureSizeI, maxPictureSize.nMaxPictureSizeP, maxPictureSize.nMaxPictureSizeB, media); if(ret != OMX_ErrorNone) { SetVideoMaxPictureSizes(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoMaxPictureSize(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZE& maxPictureSize, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(maxPictureSize); maxPictureSize.nPortIndex = port.index; MaxPicturesSizes mps; auto ret = media->Get(SETTINGS_INDEX_MAX_PICTURE_SIZES, &mps); OMX_CHECK_MEDIA_GET(ret); maxPictureSize.nMaxPictureSize = max(max(mps.i, mps.p), mps.b); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoMaxPictureSize(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZE const& maxPictureSize, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZES rollback; ConstructVideoMaxPictureSizes(rollback, port, media); auto ret = SetMaxPictureSizes(maxPictureSize.nMaxPictureSize, maxPictureSize.nMaxPictureSize, maxPictureSize.nMaxPictureSize, media); if(ret != OMX_ErrorNone) { SetVideoMaxPictureSizes(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoLoopFilterBeta(OMX_ALG_VIDEO_PARAM_LOOP_FILTER_BETA& loopFilterBeta, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(loopFilterBeta); loopFilterBeta.nPortIndex = port.index; int beta; auto ret = media->Get(SETTINGS_INDEX_LOOP_FILTER_BETA, &beta); OMX_CHECK_MEDIA_GET(ret); loopFilterBeta.nLoopFilterBeta = beta; return OMX_ErrorNone; } static OMX_ERRORTYPE SetLoopFilterBeta(OMX_S8 beta, shared_ptr media) { auto ret = media->Set(SETTINGS_INDEX_LOOP_FILTER_BETA, &beta); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoLoopFilterBeta(OMX_ALG_VIDEO_PARAM_LOOP_FILTER_BETA const& loopFilterBeta, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_LOOP_FILTER_BETA rollback; ConstructVideoLoopFilterBeta(rollback, port, media); auto ret = SetLoopFilterBeta(loopFilterBeta.nLoopFilterBeta, media); if(ret != OMX_ErrorNone) { SetVideoLoopFilterBeta(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoLoopFilterTc(OMX_ALG_VIDEO_PARAM_LOOP_FILTER_TC& loopFilterTc, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(loopFilterTc); loopFilterTc.nPortIndex = port.index; int tc; auto ret = media->Get(SETTINGS_INDEX_LOOP_FILTER_TC, &tc); OMX_CHECK_MEDIA_GET(ret); loopFilterTc.nLoopFilterTc = tc; return OMX_ErrorNone; } static OMX_ERRORTYPE SetLoopFilterTc(OMX_S8 tc, shared_ptr media) { auto ret = media->Set(SETTINGS_INDEX_LOOP_FILTER_TC, &tc); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoLoopFilterTc(OMX_ALG_VIDEO_PARAM_LOOP_FILTER_TC const& loopFilterTc, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_LOOP_FILTER_TC rollback; ConstructVideoLoopFilterTc(rollback, port, media); auto ret = SetLoopFilterTc(loopFilterTc.nLoopFilterTc, media); if(ret != OMX_ErrorNone) { SetVideoLoopFilterTc(rollback, port, media); throw ret; } return OMX_ErrorNone; } // Decoder OMX_ERRORTYPE ConstructPreallocation(OMX_ALG_PARAM_PREALLOCATION& prealloc, bool isPreallocationEnabled) { OMXChecker::SetHeaderVersion(prealloc); prealloc.bDisablePreallocation = ConvertMediaToOMXBool(!isPreallocationEnabled); return OMX_ErrorNone; } OMX_ERRORTYPE ConstructCommonSequencePictureModesSupported(OMX_ALG_COMMON_PARAM_SEQUENCE_PICTURE_MODE* mode, shared_ptr media) { vector modes; auto ret = media->Get(SETTINGS_INDEX_SEQUENCE_PICTURE_MODES_SUPPORTED, &modes); OMX_CHECK_MEDIA_GET(ret); if(mode->nModeIndex >= modes.size()) return OMX_ErrorNoMore; mode->eMode = ConvertMediaToOMXSequencePictureMode(modes[mode->nModeIndex]); return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoDecodedPictureBuffer(OMX_ALG_VIDEO_PARAM_DECODED_PICTURE_BUFFER& dpb, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(dpb); dpb.nPortIndex = port.index; DecodedPictureBufferType pictureBuffer; auto ret = media->Get(SETTINGS_INDEX_DECODED_PICTURE_BUFFER, &pictureBuffer); OMX_CHECK_MEDIA_GET(ret); dpb.eDecodedPictureBufferMode = ConvertMediaToOMXDecodedPictureBuffer(pictureBuffer); return OMX_ErrorNone; } static OMX_ERRORTYPE SetDecodedPictureBuffer(OMX_ALG_EDpbMode mode, shared_ptr media) { DecodedPictureBufferType decodedPictureBuffer = ConvertOMXToMediaDecodedPictureBuffer(mode); auto ret = media->Set(SETTINGS_INDEX_DECODED_PICTURE_BUFFER, &decodedPictureBuffer); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoDecodedPictureBuffer(OMX_ALG_VIDEO_PARAM_DECODED_PICTURE_BUFFER const& dpb, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_DECODED_PICTURE_BUFFER rollback; ConstructVideoDecodedPictureBuffer(rollback, port, media); auto ret = SetDecodedPictureBuffer(dpb.eDecodedPictureBufferMode, media); if(ret != OMX_ErrorNone) { SetVideoDecodedPictureBuffer(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoInternalEntropyBuffers(OMX_ALG_VIDEO_PARAM_INTERNAL_ENTROPY_BUFFERS& ieb, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(ieb); int stack; auto ret = media->Get(SETTINGS_INDEX_INTERNAL_ENTROPY_BUFFER, &stack); OMX_CHECK_MEDIA_GET(ret); ieb.nPortIndex = port.index; ieb.nNumInternalEntropyBuffers = stack; return OMX_ErrorNone; } static OMX_ERRORTYPE SetInternalEntropyBuffers(OMX_U32 num, shared_ptr media) { auto ret = media->Set(SETTINGS_INDEX_INTERNAL_ENTROPY_BUFFER, &num); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoInternalEntropyBuffers(OMX_ALG_VIDEO_PARAM_INTERNAL_ENTROPY_BUFFERS const& ieb, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_INTERNAL_ENTROPY_BUFFERS rollback; ConstructVideoInternalEntropyBuffers(rollback, port, media); auto ret = SetInternalEntropyBuffers(ieb.nNumInternalEntropyBuffers, media); if(ret != OMX_ErrorNone) { SetVideoInternalEntropyBuffers(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructCommonSequencePictureMode(OMX_ALG_COMMON_PARAM_SEQUENCE_PICTURE_MODE& mode, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(mode); mode.nPortIndex = port.index; auto ret = media->Get(SETTINGS_INDEX_SEQUENCE_PICTURE_MODE, &mode.eMode); OMX_CHECK_MEDIA_GET(ret); return OMX_ErrorNone; } static OMX_ERRORTYPE SetSequencePictureMode(OMX_ALG_SEQUENCE_PICTURE_MODE mode, shared_ptr media) { auto ret = media->Set(SETTINGS_INDEX_SEQUENCE_PICTURE_MODE, &mode); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetCommonSequencePictureMode(OMX_ALG_COMMON_PARAM_SEQUENCE_PICTURE_MODE mode, Port const& port, shared_ptr media) { OMX_ALG_COMMON_PARAM_SEQUENCE_PICTURE_MODE rollback; ConstructCommonSequencePictureMode(rollback, port, media); auto ret = SetSequencePictureMode(mode.eMode, media); if(ret != OMX_ErrorNone) { SetCommonSequencePictureMode(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoInputParsed(OMX_ALG_VIDEO_PARAM_INPUT_PARSED& ip, Port const& port, shared_ptr media) { OMXChecker::SetHeaderVersion(ip); ip.nPortIndex = port.index; bool isInputParsedEnabled; auto ret = media->Get(SETTINGS_INDEX_INPUT_PARSED, &isInputParsedEnabled); ip.bDisableInputParsed = ConvertMediaToOMXBool(!isInputParsedEnabled); OMX_CHECK_MEDIA_GET(ret); return OMX_ErrorNone; } static OMX_ERRORTYPE SetInputParsed(OMX_BOOL bDisableInputParsed, shared_ptr media) { auto isInputParsedEnabled = !ConvertOMXToMediaBool(bDisableInputParsed); auto ret = media->Set(SETTINGS_INDEX_INPUT_PARSED, &isInputParsedEnabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoInputParsed(OMX_ALG_VIDEO_PARAM_INPUT_PARSED const& ip, Port const& port, shared_ptr media) { OMX_ALG_VIDEO_PARAM_INPUT_PARSED rollback; ConstructVideoInputParsed(rollback, port, media); auto ret = SetInputParsed(ip.bDisableInputParsed, media); if(ret != OMX_ErrorNone) { SetVideoInputParsed(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoQuantizationTable(OMX_ALG_VIDEO_PARAM_QUANTIZATION_TABLE& table, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(table); table.nPortIndex = port.index; QPs qps; auto ret = media->Get(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &qps); table.eQpTableMode = ConvertMediaToOMXQpTable(qps.mode.table); OMX_CHECK_MEDIA_GET(ret); return OMX_ErrorNone; } static OMX_ERRORTYPE SetQuantizationTable(OMX_ALG_EQpTableMode mode, shared_ptr media) { QPs qps; auto ret = media->Get(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &qps); OMX_CHECK_MEDIA_GET(ret); qps.mode.table = ConvertOMXToMediaQpTable(mode); ret = media->Set(SETTINGS_INDEX_QUANTIZATION_PARAMETER, &qps); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoQuantizationTable(OMX_ALG_VIDEO_PARAM_QUANTIZATION_TABLE const& table, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_QUANTIZATION_TABLE rollback; ConstructVideoQuantizationTable(rollback, port, media); auto ret = SetQuantizationTable(table.eQpTableMode, media); if(ret != OMX_ErrorNone) { SetVideoQuantizationTable(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructPortEarlyCallback(OMX_ALG_PORT_PARAM_EARLY_CALLBACK& earlyCB, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(earlyCB); earlyCB.nPortIndex = port.index; bool shouldUseLLP2EarlyCallback { false }; auto ret = media->Get(SETTINGS_INDEX_LLP2_EARLY_CB, &shouldUseLLP2EarlyCallback); OMX_CHECK_MEDIA_GET(ret); earlyCB.bEnableEarlyCallback = ConvertMediaToOMXBool(shouldUseLLP2EarlyCallback); return OMX_ErrorNone; } static OMX_ERRORTYPE SetEarlyCallback(OMX_BOOL bEnableEarlyCallback, shared_ptr media) { auto shouldUseLLP2EarlyCallback = ConvertOMXToMediaBool(bEnableEarlyCallback); auto ret = media->Set(SETTINGS_INDEX_LLP2_EARLY_CB, &shouldUseLLP2EarlyCallback); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetPortEarlyCallback(OMX_ALG_PORT_PARAM_EARLY_CALLBACK const& earlyCB, Port const& port, std::shared_ptr media) { OMX_ALG_PORT_PARAM_EARLY_CALLBACK rollback; ConstructPortEarlyCallback(rollback, port, media); auto ret = SetEarlyCallback(earlyCB.bEnableEarlyCallback, media); if(ret != OMX_ErrorNone) { SetPortEarlyCallback(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoAccessUnitDelimiter(OMX_ALG_VIDEO_PARAM_ACCESS_UNIT_DELIMITER& aud, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(aud); aud.nPortIndex = port.index; bool isAUDEnabled { false }; auto ret = media->Get(SETTINGS_INDEX_ACCESS_UNIT_DELIMITER, &isAUDEnabled); OMX_CHECK_MEDIA_GET(ret); aud.bEnableAccessUnitDelimiter = ConvertMediaToOMXBool(isAUDEnabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetAccessUnitDelimiter(OMX_BOOL bEnableAccessUnitDelimiter, shared_ptr media) { auto isAUDEnabled = ConvertOMXToMediaBool(bEnableAccessUnitDelimiter); auto ret = media->Set(SETTINGS_INDEX_ACCESS_UNIT_DELIMITER, &isAUDEnabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoAccessUnitDelimiter(OMX_ALG_VIDEO_PARAM_ACCESS_UNIT_DELIMITER const& aud, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_ACCESS_UNIT_DELIMITER rollback; ConstructVideoAccessUnitDelimiter(rollback, port, media); auto ret = SetAccessUnitDelimiter(aud.bEnableAccessUnitDelimiter, media); if(ret != OMX_ErrorNone) { SetVideoAccessUnitDelimiter(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoBufferingPeriodSEI(OMX_ALG_VIDEO_PARAM_BUFFERING_PERIOD_SEI& bpSEI, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(bpSEI); bpSEI.nPortIndex = port.index; bool isBPEnabled { false }; auto ret = media->Get(SETTINGS_INDEX_BUFFERING_PERIOD_SEI, &isBPEnabled); OMX_CHECK_MEDIA_GET(ret); bpSEI.bEnableBufferingPeriodSEI = ConvertMediaToOMXBool(isBPEnabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetBufferingPeriodSEI(OMX_BOOL bEnableBufferingPeriodSEI, shared_ptr media) { auto isBPEnabled = ConvertOMXToMediaBool(bEnableBufferingPeriodSEI); auto ret = media->Set(SETTINGS_INDEX_BUFFERING_PERIOD_SEI, &isBPEnabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoBufferingPeriodSEI(OMX_ALG_VIDEO_PARAM_BUFFERING_PERIOD_SEI const& bpSEI, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_BUFFERING_PERIOD_SEI rollback; ConstructVideoBufferingPeriodSEI(rollback, port, media); auto ret = SetBufferingPeriodSEI(bpSEI.bEnableBufferingPeriodSEI, media); if(ret != OMX_ErrorNone) { SetVideoBufferingPeriodSEI(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoPictureTimingSEI(OMX_ALG_VIDEO_PARAM_PICTURE_TIMING_SEI& ptSEI, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(ptSEI); ptSEI.nPortIndex = port.index; bool isPTEnabled { false }; auto ret = media->Get(SETTINGS_INDEX_PICTURE_TIMING_SEI, &isPTEnabled); OMX_CHECK_MEDIA_GET(ret); ptSEI.bEnablePictureTimingSEI = ConvertMediaToOMXBool(isPTEnabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetPictureTimingSEI(OMX_BOOL bEnablePictureTimingSEI, shared_ptr media) { auto isPTEnabled = ConvertOMXToMediaBool(bEnablePictureTimingSEI); auto ret = media->Set(SETTINGS_INDEX_PICTURE_TIMING_SEI, &isPTEnabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoPictureTimingSEI(OMX_ALG_VIDEO_PARAM_PICTURE_TIMING_SEI const& ptSEI, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_PICTURE_TIMING_SEI rollback; ConstructVideoPictureTimingSEI(rollback, port, media); auto ret = SetPictureTimingSEI(ptSEI.bEnablePictureTimingSEI, media); if(ret != OMX_ErrorNone) { SetVideoPictureTimingSEI(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoRecoveryPointSEI(OMX_ALG_VIDEO_PARAM_RECOVERY_POINT_SEI& rpSEI, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(rpSEI); rpSEI.nPortIndex = port.index; bool isRPEnabled { false }; auto ret = media->Get(SETTINGS_INDEX_RECOVERY_POINT_SEI, &isRPEnabled); OMX_CHECK_MEDIA_GET(ret); rpSEI.bEnableRecoveryPointSEI = ConvertMediaToOMXBool(isRPEnabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetRecoveryPointSEI(OMX_BOOL bEnableRecoveryPointSEI, shared_ptr media) { auto isRPEnabled = ConvertOMXToMediaBool(bEnableRecoveryPointSEI); auto ret = media->Set(SETTINGS_INDEX_RECOVERY_POINT_SEI, &isRPEnabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoRecoveryPointSEI(OMX_ALG_VIDEO_PARAM_RECOVERY_POINT_SEI const& rpSEI, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_RECOVERY_POINT_SEI rollback; ConstructVideoRecoveryPointSEI(rollback, port, media); auto ret = SetRecoveryPointSEI(rpSEI.bEnableRecoveryPointSEI, media); if(ret != OMX_ErrorNone) { SetVideoRecoveryPointSEI(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoMasteringDisplayColourVolumeSEI(OMX_ALG_VIDEO_PARAM_MASTERING_DISPLAY_COLOUR_VOLUME_SEI& mdcvSEI, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(mdcvSEI); mdcvSEI.nPortIndex = port.index; bool isMDCVEnabled { false }; auto ret = media->Get(SETTINGS_INDEX_MASTERING_DISPLAY_COLOUR_VOLUME_SEI, &isMDCVEnabled); OMX_CHECK_MEDIA_GET(ret); mdcvSEI.bEnableMasteringDisplayColourVolumeSEI = ConvertMediaToOMXBool(isMDCVEnabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetMasteringDisplayColourVolumeSEI(OMX_BOOL bEnableMasteringDisplayColourVolumeSEI, shared_ptr media) { auto isMDCVEnabled = ConvertOMXToMediaBool(bEnableMasteringDisplayColourVolumeSEI); auto ret = media->Set(SETTINGS_INDEX_MASTERING_DISPLAY_COLOUR_VOLUME_SEI, &isMDCVEnabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoMasteringDisplayColourVolumeSEI(OMX_ALG_VIDEO_PARAM_MASTERING_DISPLAY_COLOUR_VOLUME_SEI const& mdcvSEI, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_MASTERING_DISPLAY_COLOUR_VOLUME_SEI rollback; ConstructVideoMasteringDisplayColourVolumeSEI(rollback, port, media); auto ret = SetMasteringDisplayColourVolumeSEI(mdcvSEI.bEnableMasteringDisplayColourVolumeSEI, media); if(ret != OMX_ErrorNone) { SetVideoMasteringDisplayColourVolumeSEI(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoContentLightLevelSEI(OMX_ALG_VIDEO_PARAM_CONTENT_LIGHT_LEVEL_SEI& cllSEI, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(cllSEI); cllSEI.nPortIndex = port.index; bool isCLLEnabled { false }; auto ret = media->Get(SETTINGS_INDEX_CONTENT_LIGHT_LEVEL_SEI, &isCLLEnabled); OMX_CHECK_MEDIA_GET(ret); cllSEI.bEnableContentLightLevelSEI = ConvertMediaToOMXBool(isCLLEnabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetContentLightLevelSEI(OMX_BOOL bEnableContentLightLevelSEI, shared_ptr media) { auto isCLLEnabled = ConvertOMXToMediaBool(bEnableContentLightLevelSEI); auto ret = media->Set(SETTINGS_INDEX_CONTENT_LIGHT_LEVEL_SEI, &isCLLEnabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoContentLightLevelSEI(OMX_ALG_VIDEO_PARAM_CONTENT_LIGHT_LEVEL_SEI const& cllSEI, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_CONTENT_LIGHT_LEVEL_SEI rollback; ConstructVideoContentLightLevelSEI(rollback, port, media); auto ret = SetContentLightLevelSEI(cllSEI.bEnableContentLightLevelSEI, media); if(ret != OMX_ErrorNone) { SetVideoContentLightLevelSEI(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoST209410SEI(OMX_ALG_VIDEO_PARAM_ST2094_10_SEI& st2094_10SEI, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(st2094_10SEI); st2094_10SEI.nPortIndex = port.index; bool isST209410Enabled { false }; auto ret = media->Get(SETTINGS_INDEX_ST2094_10_SEI, &isST209410Enabled); OMX_CHECK_MEDIA_GET(ret); st2094_10SEI.bEnableST209410SEI = ConvertMediaToOMXBool(isST209410Enabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetST209410SEI(OMX_BOOL bEnableST209410SEI, shared_ptr media) { auto isST209410Enabled = ConvertOMXToMediaBool(bEnableST209410SEI); auto ret = media->Set(SETTINGS_INDEX_ST2094_10_SEI, &isST209410Enabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoST209410SEI(OMX_ALG_VIDEO_PARAM_ST2094_10_SEI const& st2094_10SEI, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_ST2094_10_SEI rollback; ConstructVideoST209410SEI(rollback, port, media); auto ret = SetST209410SEI(st2094_10SEI.bEnableST209410SEI, media); if(ret != OMX_ErrorNone) { SetVideoST209410SEI(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoST209440SEI(OMX_ALG_VIDEO_PARAM_ST2094_40_SEI& st2094_40SEI, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(st2094_40SEI); st2094_40SEI.nPortIndex = port.index; bool isST209440Enabled { false }; auto ret = media->Get(SETTINGS_INDEX_ST2094_40_SEI, &isST209440Enabled); OMX_CHECK_MEDIA_GET(ret); st2094_40SEI.bEnableST209440SEI = ConvertMediaToOMXBool(isST209440Enabled); return OMX_ErrorNone; } static OMX_ERRORTYPE SetST209440SEI(OMX_BOOL bEnableST209440SEI, shared_ptr media) { auto isST209440Enabled = ConvertOMXToMediaBool(bEnableST209440SEI); auto ret = media->Set(SETTINGS_INDEX_ST2094_40_SEI, &isST209440Enabled); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoST209440SEI(OMX_ALG_VIDEO_PARAM_ST2094_40_SEI const& st2094_40SEI, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_ST2094_40_SEI rollback; ConstructVideoST209440SEI(rollback, port, media); auto ret = SetST209440SEI(st2094_40SEI.bEnableST209440SEI, media); if(ret != OMX_ErrorNone) { SetVideoST209440SEI(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoRateControlPlugin(OMX_ALG_VIDEO_PARAM_RATE_CONTROL_PLUGIN const& rateCtrlPlugin, Port const& port, std::shared_ptr media) { (void)port; RateControlPlugin rcp; rcp.dmaBuf = rateCtrlPlugin.nDmabuf; rcp.dmaSize = rateCtrlPlugin.nDmaSize; auto ret = media->Set(SETTINGS_INDEX_RATE_CONTROL_PLUGIN, &rcp); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoRateControlPlugin(OMX_ALG_VIDEO_PARAM_RATE_CONTROL_PLUGIN& rateCtrlPlugin, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(rateCtrlPlugin); rateCtrlPlugin.nPortIndex = port.index; RateControlPlugin rcp; auto ret = media->Get(SETTINGS_INDEX_RATE_CONTROL_PLUGIN, &rcp); OMX_CHECK_MEDIA_GET(ret); rateCtrlPlugin.nDmabuf = rcp.dmaBuf; rateCtrlPlugin.nDmaSize = rcp.dmaSize; return OMX_ErrorNone; } static OMX_ERRORTYPE SetCrop(OMX_U32 nLeft, OMX_U32 nTop, OMX_U32 nWidth, OMX_U32 nHeight, shared_ptr media) { Region region; region.point.x = nLeft; region.point.y = nTop; region.dimension.horizontal = nWidth; region.dimension.vertical = nHeight; auto ret = media->Set(SETTINGS_INDEX_CROP, ®ion); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoCrop(OMX_CONFIG_RECTTYPE const& crop, Port const& port, std::shared_ptr media) { OMX_CONFIG_RECTTYPE rollback; ConstructVideoCrop(rollback, port, media); auto ret = SetCrop(crop.nLeft, crop.nTop, crop.nWidth, crop.nHeight, media); if(ret != OMX_ErrorNone) { SetVideoCrop(rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoCrop(OMX_CONFIG_RECTTYPE& crop, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(crop); crop.nPortIndex = port.index; Region region {}; auto ret = media->Get(SETTINGS_INDEX_CROP, ®ion); OMX_CHECK_MEDIA_GET(ret); crop.nLeft = region.point.x; crop.nTop = region.point.y; crop.nWidth = region.dimension.horizontal; crop.nHeight = region.dimension.vertical; return OMX_ErrorNone; } OMX_ERRORTYPE ConstructVideoMaxPictureSizesInBits(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZES_IN_BITS& maxPictureSize, Port const& port, std::shared_ptr media) { OMXChecker::SetHeaderVersion(maxPictureSize); maxPictureSize.nPortIndex = port.index; MaxPicturesSizes mps; auto ret = media->Get(SETTINGS_INDEX_MAX_PICTURE_SIZES_IN_BITS, &mps); OMX_CHECK_MEDIA_GET(ret); maxPictureSize.nMaxPictureSizeI = mps.i; maxPictureSize.nMaxPictureSizeP = mps.p; maxPictureSize.nMaxPictureSizeB = mps.b; return OMX_ErrorNone; } static OMX_ERRORTYPE SetMaxPictureSizesInBits(OMX_S32 mpsI, OMX_S32 mpsP, OMX_S32 mpsB, shared_ptr media) { MaxPicturesSizes mps; mps.i = static_cast(mpsI); mps.p = static_cast(mpsP); mps.b = static_cast(mpsB); auto ret = media->Set(SETTINGS_INDEX_MAX_PICTURE_SIZES_IN_BITS, &mps); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE SetVideoMaxPictureSizesInBits(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZES_IN_BITS const& maxPictureSize, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZES_IN_BITS rollback; ConstructVideoMaxPictureSizesInBits(rollback, port, media); auto ret = SetMaxPictureSizesInBits(maxPictureSize.nMaxPictureSizeI, maxPictureSize.nMaxPictureSizeP, maxPictureSize.nMaxPictureSizeB, media); if(ret != OMX_ErrorNone) { SetVideoMaxPictureSizesInBits(rollback, port, media); throw ret; } return OMX_ErrorNone; } vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_component_getset.h000066400000000000000000000427461373706561700255420ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once /* * Component Get/Set : * Functions used for getParameter/SetParameter */ #include "omx_component.h" // Common OMX_ERRORTYPE ConstructPortSupplier(OMX_PARAM_BUFFERSUPPLIERTYPE& s, Port const& port); OMX_ERRORTYPE ConstructReportedLatency(OMX_ALG_PARAM_REPORTED_LATENCY& lat, std::shared_ptr media); OMX_ERRORTYPE SetPortExpectedBuffer(OMX_PARAM_PORTDEFINITIONTYPE const& settings, Port& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoSubframe(OMX_ALG_VIDEO_PARAM_SUBFRAME& subframe, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoSubframe(OMX_ALG_VIDEO_PARAM_SUBFRAME const& subframe, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructPortBufferMode(OMX_ALG_PORT_PARAM_BUFFER_MODE& mode, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetInputBufferMode(OMX_ALG_BUFFER_MODE mode, std::shared_ptr media); OMX_ERRORTYPE SetOutputBufferMode(OMX_ALG_BUFFER_MODE mode, std::shared_ptr media); OMX_ERRORTYPE SetPortBufferMode(OMX_ALG_PORT_PARAM_BUFFER_MODE const& portBufferMode, Port const& port, std::shared_ptr media); OMX_ERRORTYPE GetVideoPortFormatSupported(OMX_VIDEO_PARAM_PORTFORMATTYPE& format, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoPortCurrentFormat(OMX_VIDEO_PARAM_PORTFORMATTYPE& f, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoPortFormat(OMX_VIDEO_PARAM_PORTFORMATTYPE const& format, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetClock(OMX_U32 framerateInQ16, std::shared_ptr media); OMX_ERRORTYPE ConstructPortDefinition(OMX_PARAM_PORTDEFINITIONTYPE& def, Port& port, std::shared_ptr media); OMX_ERRORTYPE SetPortDefinition(OMX_PARAM_PORTDEFINITIONTYPE const& settings, Port& port, ModuleInterface& module, std::shared_ptr media); // Encoder OMX_ERRORTYPE ConstructVideoBitrate(OMX_VIDEO_PARAM_BITRATETYPE& b, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoBitrate(OMX_VIDEO_PARAM_BITRATETYPE const& bitrate, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoQuantization(OMX_VIDEO_PARAM_QUANTIZATIONTYPE& q, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoQuantization(OMX_VIDEO_PARAM_QUANTIZATIONTYPE const& quantization, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoQuantizationControl(OMX_ALG_VIDEO_PARAM_QUANTIZATION_CONTROL& q, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoQuantizationControl(OMX_ALG_VIDEO_PARAM_QUANTIZATION_CONTROL const& quantizationControl, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoQuantizationExtension(OMX_ALG_VIDEO_PARAM_QUANTIZATION_EXTENSION& q, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoQuantizationExtension(OMX_ALG_VIDEO_PARAM_QUANTIZATION_EXTENSION const& quantizationExtension, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoAspectRatio(OMX_ALG_VIDEO_PARAM_ASPECT_RATIO& a, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoAspectRatio(OMX_ALG_VIDEO_PARAM_ASPECT_RATIO const& aspectRatio, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoMaxBitrate(OMX_ALG_VIDEO_PARAM_MAX_BITRATE& b, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoMaxBitrate(OMX_ALG_VIDEO_PARAM_MAX_BITRATE const& maxBitrate, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoLowBandwidth(OMX_ALG_VIDEO_PARAM_LOW_BANDWIDTH& bw, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoLowBandwidth(OMX_ALG_VIDEO_PARAM_LOW_BANDWIDTH const& lowBandwidth, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoGopControl(OMX_ALG_VIDEO_PARAM_GOP_CONTROL& gc, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoGopControl(OMX_ALG_VIDEO_PARAM_GOP_CONTROL const& gopControl, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoSceneChangeResilience(OMX_ALG_VIDEO_PARAM_SCENE_CHANGE_RESILIENCE& r, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoSceneChangeResilience(OMX_ALG_VIDEO_PARAM_SCENE_CHANGE_RESILIENCE const& sceneChangeResilience, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoSkipFrame(OMX_ALG_VIDEO_PARAM_SKIP_FRAME& skip, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoSkipFrame(OMX_ALG_VIDEO_PARAM_SKIP_FRAME const& skipFrame, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoInstantaneousDecodingRefresh(OMX_ALG_VIDEO_PARAM_INSTANTANEOUS_DECODING_REFRESH& idr, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoInstantaneousDecodingRefresh(OMX_ALG_VIDEO_PARAM_INSTANTANEOUS_DECODING_REFRESH const& instantaneousDecodingRefresh, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoPrefetchBuffer(OMX_ALG_VIDEO_PARAM_PREFETCH_BUFFER& pb, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoPrefetchBuffer(OMX_ALG_VIDEO_PARAM_PREFETCH_BUFFER const& prefetchBuffer, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoCodedPictureBuffer(OMX_ALG_VIDEO_PARAM_CODED_PICTURE_BUFFER& cpb, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoCodedPictureBuffer(OMX_ALG_VIDEO_PARAM_CODED_PICTURE_BUFFER const& codedPictureBuffer, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoScalingList(OMX_ALG_VIDEO_PARAM_SCALING_LIST& scl, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoScalingList(OMX_ALG_VIDEO_PARAM_SCALING_LIST const& scalingList, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoFillerData(OMX_ALG_VIDEO_PARAM_FILLER_DATA& f, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoFillerData(OMX_ALG_VIDEO_PARAM_FILLER_DATA const& fillerData, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoSlices(OMX_ALG_VIDEO_PARAM_SLICES& s, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoSlices(OMX_ALG_VIDEO_PARAM_SLICES const& slices, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoModesSupported(OMX_INTERLACEFORMATTYPE& interlace, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoModeCurrent(OMX_INTERLACEFORMATTYPE& interlace, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoModeCurrent(OMX_INTERLACEFORMATTYPE const& interlace, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoLongTerm(OMX_ALG_VIDEO_PARAM_LONG_TERM& longTerm, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoLongTerm(OMX_ALG_VIDEO_PARAM_LONG_TERM const& longTerm, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoLookAhead(OMX_ALG_VIDEO_PARAM_LOOKAHEAD& la, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoLookAhead(OMX_ALG_VIDEO_PARAM_LOOKAHEAD const& la, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoTwoPass(OMX_ALG_VIDEO_PARAM_TWOPASS& tp, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoTwoPass(OMX_ALG_VIDEO_PARAM_TWOPASS const& tp, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoColorPrimaries(OMX_ALG_VIDEO_PARAM_COLOR_PRIMARIES& colorPrimaries, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoColorPrimaries(OMX_ALG_VIDEO_PARAM_COLOR_PRIMARIES const& colorPrimaries, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoTransferCharacteristics(OMX_ALG_VIDEO_PARAM_TRANSFER_CHARACTERISTICS& transferCharac, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoTransferCharacteristics(OMX_ALG_VIDEO_PARAM_TRANSFER_CHARACTERISTICS const& transferCharac, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoColorMatrix(OMX_ALG_VIDEO_PARAM_COLOR_MATRIX& colorMatrix, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoColorMatrix(OMX_ALG_VIDEO_PARAM_COLOR_MATRIX const& colorMatrix, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoMaxPictureSize(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZE& maxPictureSizes, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoMaxPictureSize(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZE const& maxPictureSizes, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoMaxPictureSizes(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZES& maxPictureSizes, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoMaxPictureSizes(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZES const& maxPictureSizes, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoLoopFilterBeta(OMX_ALG_VIDEO_PARAM_LOOP_FILTER_BETA& loopFilterBeta, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoLoopFilterBeta(OMX_ALG_VIDEO_PARAM_LOOP_FILTER_BETA const& loopFilterBeta, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoLoopFilterTc(OMX_ALG_VIDEO_PARAM_LOOP_FILTER_TC& loopFilterTc, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoLoopFilterTc(OMX_ALG_VIDEO_PARAM_LOOP_FILTER_TC const& loopFilterTc, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoMaxPictureSizesInBits(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZES_IN_BITS& maxPictureSizes, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoMaxPictureSizesInBits(OMX_ALG_VIDEO_PARAM_MAX_PICTURE_SIZES_IN_BITS const& maxPictureSizes, Port const& port, std::shared_ptr media); // Decoder OMX_ERRORTYPE ConstructPreallocation(OMX_ALG_PARAM_PREALLOCATION& prealloc, bool isPreallocationEnabled); OMX_ERRORTYPE ConstructCommonSequencePictureModesSupported(OMX_ALG_COMMON_PARAM_SEQUENCE_PICTURE_MODE* mode, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoDecodedPictureBuffer(OMX_ALG_VIDEO_PARAM_DECODED_PICTURE_BUFFER& dpb, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoDecodedPictureBuffer(OMX_ALG_VIDEO_PARAM_DECODED_PICTURE_BUFFER const& dpb, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoInternalEntropyBuffers(OMX_ALG_VIDEO_PARAM_INTERNAL_ENTROPY_BUFFERS& ieb, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoInternalEntropyBuffers(OMX_ALG_VIDEO_PARAM_INTERNAL_ENTROPY_BUFFERS const& ieb, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructCommonSequencePictureMode(OMX_ALG_COMMON_PARAM_SEQUENCE_PICTURE_MODE& mode, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetCommonSequencePictureMode(OMX_ALG_COMMON_PARAM_SEQUENCE_PICTURE_MODE mode, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoInputParsed(OMX_ALG_VIDEO_PARAM_INPUT_PARSED& ip, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoInputParsed(OMX_ALG_VIDEO_PARAM_INPUT_PARSED const& ip, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoQuantizationTable(OMX_ALG_VIDEO_PARAM_QUANTIZATION_TABLE& table, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoQuantizationTable(OMX_ALG_VIDEO_PARAM_QUANTIZATION_TABLE const& table, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructPortEarlyCallback(OMX_ALG_PORT_PARAM_EARLY_CALLBACK& earlyCB, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetPortEarlyCallback(OMX_ALG_PORT_PARAM_EARLY_CALLBACK const& earlyCB, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoAccessUnitDelimiter(OMX_ALG_VIDEO_PARAM_ACCESS_UNIT_DELIMITER& aud, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoAccessUnitDelimiter(OMX_ALG_VIDEO_PARAM_ACCESS_UNIT_DELIMITER const& aud, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoBufferingPeriodSEI(OMX_ALG_VIDEO_PARAM_BUFFERING_PERIOD_SEI& bpSEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoBufferingPeriodSEI(OMX_ALG_VIDEO_PARAM_BUFFERING_PERIOD_SEI const& bpSEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoPictureTimingSEI(OMX_ALG_VIDEO_PARAM_PICTURE_TIMING_SEI& ptSEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoPictureTimingSEI(OMX_ALG_VIDEO_PARAM_PICTURE_TIMING_SEI const& ptSEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoRecoveryPointSEI(OMX_ALG_VIDEO_PARAM_RECOVERY_POINT_SEI& rpSEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoRecoveryPointSEI(OMX_ALG_VIDEO_PARAM_RECOVERY_POINT_SEI const& rpSEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoMasteringDisplayColourVolumeSEI(OMX_ALG_VIDEO_PARAM_MASTERING_DISPLAY_COLOUR_VOLUME_SEI& mdcvSEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoMasteringDisplayColourVolumeSEI(OMX_ALG_VIDEO_PARAM_MASTERING_DISPLAY_COLOUR_VOLUME_SEI const& mdcvSEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoContentLightLevelSEI(OMX_ALG_VIDEO_PARAM_CONTENT_LIGHT_LEVEL_SEI& cllSEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoContentLightLevelSEI(OMX_ALG_VIDEO_PARAM_CONTENT_LIGHT_LEVEL_SEI const& cllSEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoST209410SEI(OMX_ALG_VIDEO_PARAM_ST2094_10_SEI& st2094_10SEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoST209410SEI(OMX_ALG_VIDEO_PARAM_ST2094_10_SEI const& st2094_10SEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoST209440SEI(OMX_ALG_VIDEO_PARAM_ST2094_40_SEI& st2094_40SEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoST209440SEI(OMX_ALG_VIDEO_PARAM_ST2094_40_SEI const& st2094_40SEI, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoRateControlPlugin(OMX_ALG_VIDEO_PARAM_RATE_CONTROL_PLUGIN const& rateCtrlPlugin, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoRateControlPlugin(OMX_ALG_VIDEO_PARAM_RATE_CONTROL_PLUGIN& rateCtrlPlugin, Port const& port, std::shared_ptr media); OMX_ERRORTYPE SetVideoCrop(OMX_CONFIG_RECTTYPE const& crop, Port const& port, std::shared_ptr media); OMX_ERRORTYPE ConstructVideoCrop(OMX_CONFIG_RECTTYPE& crop, Port const& port, std::shared_ptr media); vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_component_interface.cpp000066400000000000000000000037071373706561700265340ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_component_interface.h" OMXComponentInterface::~OMXComponentInterface() = default; vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_component_interface.h000066400000000000000000000100631373706561700261720ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include #include struct OMXComponentInterface { virtual ~OMXComponentInterface() = 0; virtual OMX_ERRORTYPE SendCommand(OMX_IN OMX_COMMANDTYPE Cmd, OMX_IN OMX_U32 nParam1, OMX_IN OMX_PTR pCmdData) = 0; virtual OMX_ERRORTYPE GetState(OMX_OUT OMX_STATETYPE* pState) = 0; virtual OMX_ERRORTYPE SetCallbacks(OMX_IN OMX_CALLBACKTYPE* pCallbacks, OMX_IN OMX_PTR pAppData) = 0; virtual OMX_ERRORTYPE GetParameter(OMX_IN OMX_INDEXTYPE nParamIndex, OMX_INOUT OMX_PTR pParam) = 0; virtual OMX_ERRORTYPE SetParameter(OMX_IN OMX_INDEXTYPE nIndex, OMX_IN OMX_PTR pParam) = 0; virtual OMX_ERRORTYPE UseBuffer(OMX_OUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN OMX_U32 nSizeBytes, OMX_IN OMX_U8* pBuffer) = 0; virtual OMX_ERRORTYPE AllocateBuffer(OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN OMX_U32 nSizeBytes) = 0; virtual OMX_ERRORTYPE FreeBuffer(OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr) = 0; virtual OMX_ERRORTYPE EmptyThisBuffer(OMX_IN OMX_BUFFERHEADERTYPE* pInputBuf) = 0; virtual OMX_ERRORTYPE FillThisBuffer(OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr) = 0; virtual void ComponentDeInit() = 0; virtual OMX_ERRORTYPE GetComponentVersion(OMX_OUT OMX_STRING pComponentName, OMX_OUT OMX_VERSIONTYPE* pComponentVersion, OMX_OUT OMX_VERSIONTYPE* pSpecVersion) = 0; virtual OMX_ERRORTYPE GetConfig(OMX_IN OMX_INDEXTYPE nIndex, OMX_INOUT OMX_PTR pComponentConfigStructure) = 0; virtual OMX_ERRORTYPE SetConfig(OMX_IN OMX_INDEXTYPE nIndex, OMX_IN OMX_PTR pComponentConfigStructure) = 0; virtual OMX_ERRORTYPE GetExtensionIndex(OMX_IN OMX_STRING cParameterName, OMX_OUT OMX_INDEXTYPE* pIndexType) = 0; virtual OMX_ERRORTYPE ComponentTunnelRequest(OMX_IN OMX_U32 nPort, OMX_IN OMX_HANDLETYPE hTunneledComp, OMX_IN OMX_U32 nTunneledPort, OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup) = 0; virtual OMX_ERRORTYPE UseEGLImage(OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN void* eglImage) = 0; virtual OMX_ERRORTYPE ComponentRoleEnum(OMX_OUT OMX_U8* cRole, OMX_IN OMX_U32 nIndex) = 0; }; vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_component_structs.h000066400000000000000000000101731373706561700257430ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include "omx_buffer_handle.h" #include #include #include #include enum class Command { SetState, Flush, DisablePort, EnablePort, MarkBuffer, EmptyBuffer, FillBuffer, SetDynamic, SharedFence, Signal, Max, }; enum class TransientState { Invalid, LoadedToIdle, IdleToPause, IdleToLoaded, IdleToExecuting, PauseToExecuting, PauseToIdle, ExecutingToIdle, ExecutingToPause, Max, }; struct Task { Task() : cmd{Command::Max}, data{nullptr}, opt{nullptr} { } Command cmd; void* data; std::shared_ptr opt; }; struct Port { Port(int index, int expected) : index{index} { setExpected(expected); }; ~Port() = default; int const index; bool enable = true; bool playable = false; bool error = false; bool isTransientToEnable = false; bool isTransientToDisable = false; void ResetError() { std::lock_guard lock(mutex); error = false; } void ErrorOccured() { std::lock_guard lock(mutex); error = true; cv_full.notify_one(); cv_empty.notify_one(); } int getExpected() { return expected; } void setExpected(int iExpected) { expected = iExpected; playable = ((int)buffers.size() >= expected); } void Add(OMX_BUFFERHEADERTYPE* header) { std::lock_guard lock(mutex); buffers.push_back(header); if((int)buffers.size() < expected) return; playable = true; cv_full.notify_one(); } void Remove(OMX_BUFFERHEADERTYPE* header) { std::lock_guard lock(mutex); buffers.erase(std::remove(buffers.begin(), buffers.end(), header), buffers.end()); if((buffers.size() > 0 || expected == 0)) return; playable = false; cv_empty.notify_one(); } void WaitEmpty() { std::unique_lock lck(mutex); cv_empty.wait(lck, [&] { return !playable || expected == 0 || error; }); } void WaitFull() { std::unique_lock lck(mutex); cv_full.wait(lck, [&] { return playable || error; }); } private: int expected; std::mutex mutex; std::vector buffers; std::condition_variable cv_full; std::condition_variable cv_empty; }; vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_convert_omx_media.cpp000066400000000000000000002113271373706561700262130ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_convert_omx_media.h" #include #include #include using namespace std; OMX_BOOL ConvertMediaToOMXBool(bool boolean) { return (!boolean) ? OMX_FALSE : OMX_TRUE; } OMX_COLOR_FORMATTYPE ConvertMediaToOMXColor(ColorType color, int bitdepth) { switch(color) { case ColorType::COLOR_400: { if(bitdepth == 8) return OMX_COLOR_FormatL8; if(bitdepth == 10) return static_cast(OMX_ALG_COLOR_FormatL10bitPacked); throw invalid_argument("bitdepth"); } case ColorType::COLOR_420: { if(bitdepth == 8) return OMX_COLOR_FormatYUV420SemiPlanar; if(bitdepth == 10) return static_cast(OMX_ALG_COLOR_FormatYUV420SemiPlanar10bitPacked); throw invalid_argument("bitdepth"); } case ColorType::COLOR_422: { if(bitdepth == 8) return OMX_COLOR_FormatYUV422SemiPlanar; if(bitdepth == 10) return static_cast(OMX_ALG_COLOR_FormatYUV422SemiPlanar10bitPacked); throw invalid_argument("bitdepth"); } case ColorType::COLOR_MAX_ENUM: return OMX_COLOR_FormatMax; default: throw invalid_argument("color"); } } OMX_VIDEO_CODINGTYPE ConvertMediaToOMXCompression(CompressionType compression) { switch(compression) { case CompressionType::COMPRESSION_UNUSED: return OMX_VIDEO_CodingUnused; case CompressionType::COMPRESSION_MAX_ENUM: return OMX_VIDEO_CodingMax; case CompressionType::COMPRESSION_AVC: return OMX_VIDEO_CodingAVC; case CompressionType::COMPRESSION_VP9: return static_cast(OMX_ALG_VIDEO_CodingVP9); case CompressionType::COMPRESSION_HEVC: return static_cast(OMX_ALG_VIDEO_CodingHEVC); default: throw invalid_argument("compression"); } } OMX_U32 ConvertMediaToOMXFramerate(Clock clock) { assert(clock.clockratio); auto f = ((clock.framerate * 1000.0) / clock.clockratio) * 65536.0; return ceil(f); } OMX_ALG_BUFFER_MODE ConvertMediaToOMXBufferHandle(BufferHandleType handle) { if(handle == BufferHandleType::BUFFER_HANDLE_FD) return OMX_ALG_BUF_DMA; else return OMX_ALG_BUF_NORMAL; } bool ConvertOMXToMediaBool(OMX_BOOL boolean) { if(boolean == OMX_FALSE) return false; return true; } CompressionType ConvertOMXToMediaCompression(OMX_VIDEO_CODINGTYPE coding) { switch(static_cast(coding)) { case OMX_VIDEO_CodingUnused: return CompressionType::COMPRESSION_UNUSED; case OMX_VIDEO_CodingAVC: return CompressionType::COMPRESSION_AVC; case OMX_ALG_VIDEO_CodingHEVC: return CompressionType::COMPRESSION_HEVC; case OMX_ALG_VIDEO_CodingVP9: return CompressionType::COMPRESSION_VP9; case OMX_VIDEO_CodingMax: return CompressionType::COMPRESSION_MAX_ENUM; default: throw invalid_argument("coding"); } throw invalid_argument("coding"); } ColorType ConvertOMXToMediaColor(OMX_COLOR_FORMATTYPE format) { switch(static_cast(format)) { case OMX_COLOR_FormatL8: case OMX_ALG_COLOR_FormatL10bitPacked: return ColorType::COLOR_400; case OMX_COLOR_FormatYUV420SemiPlanar: case OMX_ALG_COLOR_FormatYUV420SemiPlanar10bitPacked: return ColorType::COLOR_420; case OMX_COLOR_FormatYUV422SemiPlanar: case OMX_ALG_COLOR_FormatYUV422SemiPlanar10bitPacked: return ColorType::COLOR_422; case OMX_COLOR_FormatMax: return ColorType::COLOR_MAX_ENUM; default: throw invalid_argument("format"); } throw invalid_argument("format"); } int ConvertOMXToMediaBitdepth(OMX_COLOR_FORMATTYPE format) { switch(static_cast(format)) { case OMX_COLOR_FormatL8: case OMX_COLOR_FormatYUV420SemiPlanar: case OMX_COLOR_FormatYUV422SemiPlanar: return 8; case OMX_ALG_COLOR_FormatL10bitPacked: case OMX_ALG_COLOR_FormatYUV420SemiPlanar10bitPacked: case OMX_ALG_COLOR_FormatYUV422SemiPlanar10bitPacked: return 10; case OMX_COLOR_FormatUnused: return 0; // XXX default: throw invalid_argument("color"); } throw invalid_argument("color"); } Clock ConvertOMXToMediaClock(OMX_U32 framerateInQ16) { Clock clock {}; clock.framerate = ceil(framerateInQ16 / 65536.0); clock.clockratio = rint((clock.framerate * 1000.0 * 65536.0) / framerateInQ16); if(clock.framerate == 0) clock.clockratio = 1000; return clock; } BufferHandleType ConvertOMXToMediaBufferHandle(OMX_ALG_BUFFER_MODE bufferMode) { switch(bufferMode) { case OMX_ALG_BUF_NORMAL: return BufferHandleType::BUFFER_HANDLE_CHAR_PTR; case OMX_ALG_BUF_DMA: return BufferHandleType::BUFFER_HANDLE_FD; case OMX_ALG_BUF_MAX_ENUM: // fallthrough default: throw invalid_argument("bufferMode"); } throw invalid_argument("bufferMode"); } DecodedPictureBufferType ConvertOMXToMediaDecodedPictureBuffer(OMX_ALG_EDpbMode mode) { switch(mode) { case OMX_ALG_DPB_NORMAL: return DecodedPictureBufferType::DECODED_PICTURE_BUFFER_NORMAL; case OMX_ALG_DPB_NO_REORDERING: return DecodedPictureBufferType::DECODED_PICTURE_BUFFER_NO_REORDERING; case OMX_ALG_DPB_MAX_ENUM: return DecodedPictureBufferType::DECODED_PICTURE_BUFFER_MAX_ENUM; default: return DecodedPictureBufferType::DECODED_PICTURE_BUFFER_MAX_ENUM; } return DecodedPictureBufferType::DECODED_PICTURE_BUFFER_MAX_ENUM; } OMX_ALG_EDpbMode ConvertMediaToOMXDecodedPictureBuffer(DecodedPictureBufferType mode) { switch(mode) { case DecodedPictureBufferType::DECODED_PICTURE_BUFFER_NORMAL: return OMX_ALG_DPB_NORMAL; case DecodedPictureBufferType::DECODED_PICTURE_BUFFER_NO_REORDERING: return OMX_ALG_DPB_NO_REORDERING; case DecodedPictureBufferType::DECODED_PICTURE_BUFFER_MAX_ENUM: return OMX_ALG_DPB_MAX_ENUM; default: return OMX_ALG_DPB_MAX_ENUM; } return OMX_ALG_DPB_MAX_ENUM; } static inline AVCProfileType ConvertOMXToMediaAVCProfile(OMX_VIDEO_AVCPROFILETYPE profile) { switch(static_cast(profile)) { case OMX_VIDEO_AVCProfileBaseline: return AVCProfileType::AVC_PROFILE_BASELINE; case OMX_VIDEO_AVCProfileMain: return AVCProfileType::AVC_PROFILE_MAIN; case OMX_VIDEO_AVCProfileExtended: return AVCProfileType::AVC_PROFILE_EXTENDED; case OMX_VIDEO_AVCProfileHigh: return AVCProfileType::AVC_PROFILE_HIGH; case OMX_VIDEO_AVCProfileHigh10: return AVCProfileType::AVC_PROFILE_HIGH_10; case OMX_VIDEO_AVCProfileHigh422: return AVCProfileType::AVC_PROFILE_HIGH_422; case OMX_VIDEO_AVCProfileHigh444: return AVCProfileType::AVC_PROFILE_HIGH_444_PREDICTIVE; case OMX_ALG_VIDEO_AVCProfileConstrainedBaseline: return AVCProfileType::AVC_PROFILE_CONSTRAINED_BASELINE; case OMX_ALG_VIDEO_AVCProfileProgressiveHigh: return AVCProfileType::AVC_PROFILE_PROGRESSIVE_HIGH; case OMX_ALG_VIDEO_AVCProfileConstrainedHigh: return AVCProfileType::AVC_PROFILE_CONSTRAINED_HIGH; case OMX_ALG_VIDEO_AVCProfileHigh10_Intra: return AVCProfileType::AVC_PROFILE_HIGH_10_INTRA; case OMX_ALG_VIDEO_AVCProfileHigh422_Intra: return AVCProfileType::AVC_PROFILE_HIGH_422_INTRA; case OMX_ALG_VIDEO_AVCProfileHigh444_Intra: return AVCProfileType::AVC_PROFILE_HIGH_444_INTRA; case OMX_ALG_VIDEO_AVCProfileCAVLC444_Intra: return AVCProfileType::AVC_PROFILE_CAVLC_444_INTRA; case OMX_ALG_VIDEO_XAVCProfileHigh10_Intra_CBG: return AVCProfileType::XAVC_PROFILE_HIGH10_INTRA_CBG; case OMX_ALG_VIDEO_XAVCProfileHigh10_Intra_VBR: return AVCProfileType::XAVC_PROFILE_HIGH10_INTRA_VBR; case OMX_ALG_VIDEO_XAVCProfileHigh422_Intra_CBG: return AVCProfileType::XAVC_PROFILE_HIGH_422_INTRA_CBG; case OMX_ALG_VIDEO_XAVCProfileHigh422_Intra_VBR: return AVCProfileType::XAVC_PROFILE_HIGH_422_INTRA_VBR; case OMX_ALG_VIDEO_XAVCProfileLongGopMain_MP4: return AVCProfileType::XAVC_PROFILE_LONG_GOP_MAIN_MP4; case OMX_ALG_VIDEO_XAVCProfileLongGopHigh_MP4: return AVCProfileType::XAVC_PROFILE_LONG_GOP_HIGH_MP4; case OMX_ALG_VIDEO_XAVCProfileLongGopHigh_MXF: return AVCProfileType::XAVC_PROFILE_LONG_GOP_HIGH_MXF; case OMX_ALG_VIDEO_XAVCProfileLongGopHigh422_MXF: return AVCProfileType::XAVC_PROFILE_LONG_GOP_HIGH_422_MXF; case OMX_VIDEO_AVCProfileMax: return AVCProfileType::AVC_PROFILE_MAX_ENUM; default: return AVCProfileType::AVC_PROFILE_MAX_ENUM; } return AVCProfileType::AVC_PROFILE_MAX_ENUM; } static inline int ConvertOMXToMediaAVCLevel(OMX_VIDEO_AVCLEVELTYPE level) { switch(static_cast(level)) { case OMX_VIDEO_AVCLevel1b: return 9; case OMX_VIDEO_AVCLevel1: return 10; case OMX_VIDEO_AVCLevel11: return 11; case OMX_VIDEO_AVCLevel12: return 12; case OMX_VIDEO_AVCLevel13: return 13; case OMX_VIDEO_AVCLevel2: return 20; case OMX_VIDEO_AVCLevel21: return 21; case OMX_VIDEO_AVCLevel22: return 22; case OMX_VIDEO_AVCLevel3: return 30; case OMX_VIDEO_AVCLevel31: return 31; case OMX_VIDEO_AVCLevel32: return 32; case OMX_VIDEO_AVCLevel4: return 40; case OMX_VIDEO_AVCLevel41: return 41; case OMX_VIDEO_AVCLevel42: return 42; case OMX_VIDEO_AVCLevel5: return 50; case OMX_VIDEO_AVCLevel51: return 51; case OMX_ALG_VIDEO_AVCLevel52: return 52; case OMX_ALG_VIDEO_AVCLevel60: return 60; case OMX_ALG_VIDEO_AVCLevel61: return 61; case OMX_ALG_VIDEO_AVCLevel62: return 62; default: return 0; } return 0; } ProfileLevel ConvertOMXToMediaAVCProfileLevel(OMX_VIDEO_AVCPROFILETYPE profile, OMX_VIDEO_AVCLEVELTYPE level) { ProfileLevel pf; pf.profile.avc = ConvertOMXToMediaAVCProfile(profile); pf.level = ConvertOMXToMediaAVCLevel(level); return pf; } OMX_VIDEO_AVCPROFILETYPE ConvertMediaToOMXAVCProfile(ProfileLevel profileLevel) { switch(profileLevel.profile.avc) { case AVCProfileType::AVC_PROFILE_BASELINE: return OMX_VIDEO_AVCProfileBaseline; case AVCProfileType::AVC_PROFILE_MAIN: return OMX_VIDEO_AVCProfileMain; case AVCProfileType::AVC_PROFILE_EXTENDED: return OMX_VIDEO_AVCProfileExtended; case AVCProfileType::AVC_PROFILE_HIGH: return OMX_VIDEO_AVCProfileHigh; case AVCProfileType::AVC_PROFILE_HIGH_10: return OMX_VIDEO_AVCProfileHigh10; case AVCProfileType::AVC_PROFILE_HIGH_422: return OMX_VIDEO_AVCProfileHigh422; case AVCProfileType::AVC_PROFILE_HIGH_444_PREDICTIVE: return OMX_VIDEO_AVCProfileHigh444; case AVCProfileType::AVC_PROFILE_CONSTRAINED_BASELINE: return static_cast(OMX_ALG_VIDEO_AVCProfileConstrainedBaseline); case AVCProfileType::AVC_PROFILE_PROGRESSIVE_HIGH: return static_cast(OMX_ALG_VIDEO_AVCProfileProgressiveHigh); case AVCProfileType::AVC_PROFILE_CONSTRAINED_HIGH: return static_cast(OMX_ALG_VIDEO_AVCProfileConstrainedHigh); case AVCProfileType::AVC_PROFILE_HIGH_10_INTRA: return static_cast(OMX_ALG_VIDEO_AVCProfileHigh10_Intra); case AVCProfileType::AVC_PROFILE_HIGH_422_INTRA: return static_cast(OMX_ALG_VIDEO_AVCProfileHigh422_Intra); case AVCProfileType::AVC_PROFILE_HIGH_444_INTRA: return static_cast(OMX_ALG_VIDEO_AVCProfileHigh444_Intra); case AVCProfileType::AVC_PROFILE_CAVLC_444_INTRA: return static_cast(OMX_ALG_VIDEO_AVCProfileCAVLC444_Intra); case AVCProfileType::XAVC_PROFILE_HIGH10_INTRA_CBG: return static_cast(OMX_ALG_VIDEO_XAVCProfileHigh10_Intra_CBG); case AVCProfileType::XAVC_PROFILE_HIGH10_INTRA_VBR: return static_cast(OMX_ALG_VIDEO_XAVCProfileHigh10_Intra_VBR); case AVCProfileType::XAVC_PROFILE_HIGH_422_INTRA_CBG: return static_cast(OMX_ALG_VIDEO_XAVCProfileHigh422_Intra_CBG); case AVCProfileType::XAVC_PROFILE_HIGH_422_INTRA_VBR: return static_cast(OMX_ALG_VIDEO_XAVCProfileHigh422_Intra_VBR); case AVCProfileType::XAVC_PROFILE_LONG_GOP_MAIN_MP4: return static_cast(OMX_ALG_VIDEO_XAVCProfileLongGopMain_MP4); case AVCProfileType::XAVC_PROFILE_LONG_GOP_HIGH_MP4: return static_cast(OMX_ALG_VIDEO_XAVCProfileLongGopHigh_MP4); case AVCProfileType::XAVC_PROFILE_LONG_GOP_HIGH_MXF: return static_cast(OMX_ALG_VIDEO_XAVCProfileLongGopHigh_MXF); case AVCProfileType::XAVC_PROFILE_LONG_GOP_HIGH_422_MXF: return static_cast(OMX_ALG_VIDEO_XAVCProfileLongGopHigh422_MXF); default: return OMX_VIDEO_AVCProfileMax; } return OMX_VIDEO_AVCProfileMax; } OMX_VIDEO_AVCLEVELTYPE ConvertMediaToOMXAVCLevel(ProfileLevel profileLevel) { switch(profileLevel.level) { case 9: return OMX_VIDEO_AVCLevel1b; case 10: return OMX_VIDEO_AVCLevel1; case 11: return OMX_VIDEO_AVCLevel11; case 12: return OMX_VIDEO_AVCLevel12; case 13: return OMX_VIDEO_AVCLevel13; case 20: return OMX_VIDEO_AVCLevel2; case 21: return OMX_VIDEO_AVCLevel21; case 22: return OMX_VIDEO_AVCLevel22; case 30: return OMX_VIDEO_AVCLevel3; case 31: return OMX_VIDEO_AVCLevel31; case 32: return OMX_VIDEO_AVCLevel32; case 40: return OMX_VIDEO_AVCLevel4; case 41: return OMX_VIDEO_AVCLevel41; case 42: return OMX_VIDEO_AVCLevel42; case 50: return OMX_VIDEO_AVCLevel5; case 51: return OMX_VIDEO_AVCLevel51; case 52: return static_cast(OMX_ALG_VIDEO_AVCLevel52); case 60: return static_cast(OMX_ALG_VIDEO_AVCLevel60); case 61: return static_cast(OMX_ALG_VIDEO_AVCLevel61); case 62: return static_cast(OMX_ALG_VIDEO_AVCLevel62); default: return OMX_VIDEO_AVCLevelMax; } return OMX_VIDEO_AVCLevelMax; } LoopFilterType ConvertOMXToMediaAVCLoopFilter(OMX_VIDEO_AVCLOOPFILTERTYPE loopFilter) { switch(loopFilter) { case OMX_VIDEO_AVCLoopFilterDisable: return LoopFilterType::LOOP_FILTER_DISABLE; case OMX_VIDEO_AVCLoopFilterDisableSliceBoundary: return LoopFilterType::LOOP_FILTER_ENABLE; case OMX_VIDEO_AVCLoopFilterEnable: return LoopFilterType::LOOP_FILTER_ENABLE_CROSS_SLICE; case OMX_VIDEO_AVCLoopFilterMax: return LoopFilterType::LOOP_FILTER_MAX_ENUM; default: return LoopFilterType::LOOP_FILTER_MAX_ENUM; } return LoopFilterType::LOOP_FILTER_MAX_ENUM; } OMX_VIDEO_AVCLOOPFILTERTYPE ConvertMediaToOMXAVCLoopFilter(LoopFilterType loopFilter) { switch(loopFilter) { case LoopFilterType::LOOP_FILTER_DISABLE: return OMX_VIDEO_AVCLoopFilterDisable; case LoopFilterType::LOOP_FILTER_ENABLE: return OMX_VIDEO_AVCLoopFilterDisableSliceBoundary; case LoopFilterType::LOOP_FILTER_ENABLE_CROSS_SLICE: return OMX_VIDEO_AVCLoopFilterEnable; case LoopFilterType::LOOP_FILTER_ENABLE_CROSS_TILE: return OMX_VIDEO_AVCLoopFilterMax; case LoopFilterType::LOOP_FILTER_ENABLE_CROSS_TILE_AND_SLICE: return OMX_VIDEO_AVCLoopFilterMax; case LoopFilterType::LOOP_FILTER_MAX_ENUM: return OMX_VIDEO_AVCLoopFilterMax; default: return OMX_VIDEO_AVCLoopFilterMax; } return OMX_VIDEO_AVCLoopFilterMax; } int ConvertOMXToMediaBFrames(OMX_U32 bFrames, OMX_U32 pFrames) { if(pFrames == 0) return 0; return (bFrames + pFrames) / (pFrames + 1); } int ConvertOMXToMediaGopLength(OMX_U32 bFrames, OMX_U32 pFrames) { return pFrames + bFrames + 1; } EntropyCodingType ConvertOMXToMediaEntropyCoding(OMX_BOOL isCabac) { if(isCabac == OMX_FALSE) return EntropyCodingType::ENTROPY_CODING_CAVLC; return EntropyCodingType::ENTROPY_CODING_CABAC; } int ConvertOMXToMediaQpInitial(OMX_U32 qpI) { return qpI; } int ConvertOMXToMediaQpDeltaIP(OMX_U32 qpI, OMX_U32 qpP) { return qpP - qpI; } int ConvertOMXToMediaQpDeltaPB(OMX_U32 qpP, OMX_U32 qpB) { return qpB - qpP; } int ConvertOMXToMediaQpMin(OMX_S32 qpMin) { return qpMin; } int ConvertOMXToMediaQpMax(OMX_S32 qpMax) { return qpMax; } QPControlType ConvertOMXToMediaQpCtrlMode(OMX_ALG_EQpCtrlMode mode) { switch(mode) { case OMX_ALG_QP_CTRL_NONE: return QPControlType::QP_CONTROL_NONE; case OMX_ALG_QP_CTRL_AUTO: return QPControlType::QP_CONTROL_AUTO; case OMX_ALG_QP_CTRL_ADAPTIVE_AUTO: return QPControlType::QP_CONTROL_ADAPTIVE_AUTO; case OMX_ALG_QP_CTRL_MAX_ENUM: return QPControlType::QP_CONTROL_MAX_ENUM; default: return QPControlType::QP_CONTROL_MAX_ENUM; } return QPControlType::QP_CONTROL_MAX_ENUM; } RateControlType ConvertOMXToMediaControlRate(OMX_VIDEO_CONTROLRATETYPE mode) { switch(static_cast(mode)) // all indexes are in OMX_U32 { case OMX_Video_ControlRateDisable: return RateControlType::RATE_CONTROL_CONSTANT_QUANTIZATION; case OMX_Video_ControlRateConstant: return RateControlType::RATE_CONTROL_CONSTANT_BITRATE; case OMX_Video_ControlRateVariable: return RateControlType::RATE_CONTROL_VARIABLE_BITRATE; case OMX_ALG_Video_ControlRateVariableCapped: return RateControlType::RATE_CONTROL_VARIABLE_CAPPED_BITRATE; case OMX_ALG_Video_ControlRateLowLatency: return RateControlType::RATE_CONTROL_LOW_LATENCY; case OMX_ALG_Video_ControlRatePlugin: return RateControlType::RATE_CONTROL_PLUGIN; case OMX_ALG_Video_ControlRateMaxEnum: return RateControlType::RATE_CONTROL_MAX_ENUM; default: return RateControlType::RATE_CONTROL_MAX_ENUM; } return RateControlType::RATE_CONTROL_MAX_ENUM; } AspectRatioType ConvertOMXToMediaAspectRatio(OMX_ALG_EAspectRatio aspectRatio) { switch(aspectRatio) { case OMX_ALG_ASPECT_RATIO_NONE: return AspectRatioType::ASPECT_RATIO_NONE; case OMX_ALG_ASPECT_RATIO_1_1: return AspectRatioType::ASPECT_RATIO_1_1; case OMX_ALG_ASPECT_RATIO_4_3: return AspectRatioType::ASPECT_RATIO_4_3; case OMX_ALG_ASPECT_RATIO_16_9: return AspectRatioType::ASPECT_RATIO_16_9; case OMX_ALG_ASPECT_RATIO_AUTO: return AspectRatioType::ASPECT_RATIO_AUTO; case OMX_ALG_ASPECT_RATIO_MAX_ENUM: return AspectRatioType::ASPECT_RATIO_MAX_ENUM; default: return AspectRatioType::ASPECT_RATIO_MAX_ENUM; } return AspectRatioType::ASPECT_RATIO_MAX_ENUM; } GopControlType ConvertOMXToMediaGopControl(OMX_ALG_EGopCtrlMode mode) { switch(mode) { case OMX_ALG_GOP_MODE_DEFAULT: return GopControlType::GOP_CONTROL_DEFAULT; case OMX_ALG_GOP_MODE_DEFAULT_B: return GopControlType::GOP_CONTROL_DEFAULT_B; case OMX_ALG_GOP_MODE_PYRAMIDAL: return GopControlType::GOP_CONTROL_PYRAMIDAL; case OMX_ALG_GOP_MODE_PYRAMIDAL_B: return GopControlType::GOP_CONTROL_PYRAMIDAL_B; case OMX_ALG_GOP_MODE_ADAPTIVE: return GopControlType::GOP_CONTROL_ADAPTIVE; case OMX_ALG_GOP_MODE_LOW_DELAY_P: return GopControlType::GOP_CONTROL_LOW_DELAY_P; case OMX_ALG_GOP_MODE_LOW_DELAY_B: return GopControlType::GOP_CONTROL_LOW_DELAY_B; case OMX_ALG_GOP_MODE_MAX_ENUM: return GopControlType::GOP_CONTROL_MAX_ENUM; default: return GopControlType::GOP_CONTROL_MAX_ENUM; } return GopControlType::GOP_CONTROL_MAX_ENUM; } GdrType ConvertOMXToMediaGdr(OMX_ALG_EGdrMode gdr) { switch(gdr) { case OMX_ALG_GDR_OFF: return GdrType::GDR_OFF; case OMX_ALG_GDR_HORIZONTAL: return GdrType::GDR_HORTIZONTAL; case OMX_ALG_GDR_VERTICAL: return GdrType::GDR_VERTICAL; case OMX_ALG_GDR_MAX_ENUM: return GdrType::GDR_MAX_ENUM; default: return GdrType::GDR_MAX_ENUM; } return GdrType::GDR_MAX_ENUM; } ScalingListType ConvertOMXToMediaScalingList(OMX_ALG_EScalingList scalingListMode) { switch(scalingListMode) { case OMX_ALG_SCL_DEFAULT: return ScalingListType::SCALING_LIST_DEFAULT; case OMX_ALG_SCL_FLAT: return ScalingListType::SCALING_LIST_FLAT; case OMX_ALG_SCL_MAX_ENUM: return ScalingListType::SCALING_LIST_MAX_ENUM; default: return ScalingListType::SCALING_LIST_MAX_ENUM; } return ScalingListType::SCALING_LIST_MAX_ENUM; } OMX_BOOL ConvertMediaToOMXEntropyCoding(EntropyCodingType mode) { switch(mode) { case EntropyCodingType::ENTROPY_CODING_CABAC: return OMX_TRUE; case EntropyCodingType::ENTROPY_CODING_CAVLC: return OMX_FALSE; case EntropyCodingType::ENTROPY_CODING_MAX_ENUM: return OMX_FALSE; default: return OMX_FALSE; } return OMX_FALSE; } OMX_U32 ConvertMediaToOMXBFrames(Gop gop) { return gop.length - ConvertMediaToOMXPFrames(gop) - 1; } OMX_U32 ConvertMediaToOMXPFrames(Gop gop) { return (gop.length - 1) / (gop.b + 1); } OMX_U32 ConvertMediaToOMXQpI(QPs qps) { return qps.initial; } OMX_U32 ConvertMediaToOMXQpP(QPs qps) { return qps.deltaIP + qps.initial; } OMX_U32 ConvertMediaToOMXQpB(QPs qps) { return qps.deltaIP + qps.deltaPB + qps.initial; } OMX_S32 ConvertMediaToOMXQpMin(QPs qps) { return qps.min; } OMX_S32 ConvertMediaToOMXQpMax(QPs qps) { return qps.max; } OMX_ALG_EQpCtrlMode ConvertMediaToOMXQpCtrlMode(QPControlType mode) { switch(mode) { case QPControlType::QP_CONTROL_NONE: return OMX_ALG_QP_CTRL_NONE; case QPControlType::QP_CONTROL_AUTO: return OMX_ALG_QP_CTRL_AUTO; case QPControlType::QP_CONTROL_ADAPTIVE_AUTO: return OMX_ALG_QP_CTRL_ADAPTIVE_AUTO; case QPControlType::QP_CONTROL_MAX_ENUM: return OMX_ALG_QP_CTRL_MAX_ENUM; default: return OMX_ALG_QP_CTRL_MAX_ENUM; } return OMX_ALG_QP_CTRL_MAX_ENUM; } OMX_VIDEO_CONTROLRATETYPE ConvertMediaToOMXControlRate(RateControlType mode) { switch(mode) { case RateControlType::RATE_CONTROL_CONSTANT_QUANTIZATION: return OMX_Video_ControlRateDisable; case RateControlType::RATE_CONTROL_CONSTANT_BITRATE: return OMX_Video_ControlRateConstant; case RateControlType::RATE_CONTROL_VARIABLE_BITRATE: return OMX_Video_ControlRateVariable; case RateControlType::RATE_CONTROL_VARIABLE_CAPPED_BITRATE: return static_cast(OMX_ALG_Video_ControlRateVariableCapped); case RateControlType::RATE_CONTROL_LOW_LATENCY: return static_cast(OMX_ALG_Video_ControlRateLowLatency); case RateControlType::RATE_CONTROL_PLUGIN: return static_cast(OMX_ALG_Video_ControlRatePlugin); case RateControlType::RATE_CONTROL_MAX_ENUM: return OMX_Video_ControlRateMax; default: return OMX_Video_ControlRateMax; } return OMX_Video_ControlRateMax; } OMX_ALG_EAspectRatio ConvertMediaToOMXAspectRatio(AspectRatioType aspectRatio) { switch(aspectRatio) { case AspectRatioType::ASPECT_RATIO_NONE: return OMX_ALG_ASPECT_RATIO_NONE; case AspectRatioType::ASPECT_RATIO_1_1: return OMX_ALG_ASPECT_RATIO_1_1; case AspectRatioType::ASPECT_RATIO_4_3: return OMX_ALG_ASPECT_RATIO_4_3; case AspectRatioType::ASPECT_RATIO_16_9: return OMX_ALG_ASPECT_RATIO_16_9; case AspectRatioType::ASPECT_RATIO_AUTO: return OMX_ALG_ASPECT_RATIO_AUTO; case AspectRatioType::ASPECT_RATIO_MAX_ENUM: return OMX_ALG_ASPECT_RATIO_MAX_ENUM; default: return OMX_ALG_ASPECT_RATIO_MAX_ENUM; } return OMX_ALG_ASPECT_RATIO_MAX_ENUM; } OMX_ALG_EGopCtrlMode ConvertMediaToOMXGopControl(GopControlType mode) { switch(mode) { case GopControlType::GOP_CONTROL_DEFAULT: return OMX_ALG_GOP_MODE_DEFAULT; case GopControlType::GOP_CONTROL_DEFAULT_B: return OMX_ALG_GOP_MODE_DEFAULT_B; case GopControlType::GOP_CONTROL_PYRAMIDAL: return OMX_ALG_GOP_MODE_PYRAMIDAL; case GopControlType::GOP_CONTROL_PYRAMIDAL_B: return OMX_ALG_GOP_MODE_PYRAMIDAL_B; case GopControlType::GOP_CONTROL_ADAPTIVE: return OMX_ALG_GOP_MODE_ADAPTIVE; case GopControlType::GOP_CONTROL_LOW_DELAY_P: return OMX_ALG_GOP_MODE_LOW_DELAY_P; case GopControlType::GOP_CONTROL_LOW_DELAY_B: return OMX_ALG_GOP_MODE_LOW_DELAY_B; default: return OMX_ALG_GOP_MODE_MAX_ENUM; } return OMX_ALG_GOP_MODE_MAX_ENUM; } OMX_ALG_EGdrMode ConvertMediaToOMXGdr(GdrType gdr) { switch(gdr) { case GdrType::GDR_OFF: return OMX_ALG_GDR_OFF; case GdrType::GDR_VERTICAL: return OMX_ALG_GDR_VERTICAL; case GdrType::GDR_HORTIZONTAL: return OMX_ALG_GDR_HORIZONTAL; default: return OMX_ALG_GDR_MAX_ENUM; } return OMX_ALG_GDR_MAX_ENUM; } OMX_ALG_EScalingList ConvertMediaToOMXScalingList(ScalingListType scalingLisgt) { switch(scalingLisgt) { case ScalingListType::SCALING_LIST_DEFAULT: return OMX_ALG_SCL_DEFAULT; case ScalingListType::SCALING_LIST_FLAT: return OMX_ALG_SCL_FLAT; case ScalingListType::SCALING_LIST_MAX_ENUM: return OMX_ALG_SCL_MAX_ENUM; default: return OMX_ALG_SCL_MAX_ENUM; } return OMX_ALG_SCL_MAX_ENUM; } LoopFilterType ConvertOMXToMediaHEVCLoopFilter(OMX_ALG_VIDEO_HEVCLOOPFILTERTYPE loopFilter) { switch(loopFilter) { case OMX_ALG_VIDEO_HEVCLoopFilterDisable: return LoopFilterType::LOOP_FILTER_DISABLE; case OMX_ALG_VIDEO_HEVCLoopFilterEnable: return LoopFilterType::LOOP_FILTER_ENABLE_CROSS_TILE_AND_SLICE; case OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossSlice: return LoopFilterType::LOOP_FILTER_ENABLE_CROSS_TILE; case OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossTile: return LoopFilterType::LOOP_FILTER_ENABLE_CROSS_SLICE; case OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossSliceAndTile: return LoopFilterType::LOOP_FILTER_ENABLE; case OMX_ALG_VIDEO_HEVCLoopFilterMaxEnum: return LoopFilterType::LOOP_FILTER_MAX_ENUM; default: return LoopFilterType::LOOP_FILTER_MAX_ENUM; } return LoopFilterType::LOOP_FILTER_MAX_ENUM; } OMX_ALG_VIDEO_HEVCLOOPFILTERTYPE ConvertMediaToOMXHEVCLoopFilter(LoopFilterType loopFilter) { switch(loopFilter) { case LoopFilterType::LOOP_FILTER_DISABLE: return OMX_ALG_VIDEO_HEVCLoopFilterDisable; case LoopFilterType::LOOP_FILTER_ENABLE: return OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossSliceAndTile; case LoopFilterType::LOOP_FILTER_ENABLE_CROSS_SLICE: return OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossTile; case LoopFilterType::LOOP_FILTER_ENABLE_CROSS_TILE: return OMX_ALG_VIDEO_HEVCLoopFilterDisableCrossSlice; case LoopFilterType::LOOP_FILTER_ENABLE_CROSS_TILE_AND_SLICE: return OMX_ALG_VIDEO_HEVCLoopFilterEnable; case LoopFilterType::LOOP_FILTER_MAX_ENUM: return OMX_ALG_VIDEO_HEVCLoopFilterMaxEnum; default: return OMX_ALG_VIDEO_HEVCLoopFilterMaxEnum; } return OMX_ALG_VIDEO_HEVCLoopFilterMaxEnum; } static inline HEVCProfileType ConvertOMXToMediaHEVCMainTierProfile(OMX_ALG_VIDEO_HEVCPROFILETYPE profile) { switch(profile) { case OMX_ALG_VIDEO_HEVCProfileMain: return HEVCProfileType::HEVC_PROFILE_MAIN; case OMX_ALG_VIDEO_HEVCProfileMain10: return HEVCProfileType::HEVC_PROFILE_MAIN_10; case OMX_ALG_VIDEO_HEVCProfileMainStill: return HEVCProfileType::HEVC_PROFILE_MAIN_STILL; case OMX_ALG_VIDEO_HEVCProfileMonochrome: return HEVCProfileType::HEVC_PROFILE_MONOCHROME; case OMX_ALG_VIDEO_HEVCProfileMonochrome10: return HEVCProfileType::HEVC_PROFILE_MONOCHROME_10; case OMX_ALG_VIDEO_HEVCProfileMonochrome12: return HEVCProfileType::HEVC_PROFILE_MONOCHROME_12; case OMX_ALG_VIDEO_HEVCProfileMonochrome16: return HEVCProfileType::HEVC_PROFILE_MONOCHROME_16; case OMX_ALG_VIDEO_HEVCProfileMain12: return HEVCProfileType::HEVC_PROFILE_MAIN_12; case OMX_ALG_VIDEO_HEVCProfileMain422: return HEVCProfileType::HEVC_PROFILE_MAIN_422; case OMX_ALG_VIDEO_HEVCProfileMain422_10: return HEVCProfileType::HEVC_PROFILE_MAIN_422_10; case OMX_ALG_VIDEO_HEVCProfileMain422_12: return HEVCProfileType::HEVC_PROFILE_MAIN_422_12; case OMX_ALG_VIDEO_HEVCProfileMain444: return HEVCProfileType::HEVC_PROFILE_MAIN_444; case OMX_ALG_VIDEO_HEVCProfileMain444_10: return HEVCProfileType::HEVC_PROFILE_MAIN_444_10; case OMX_ALG_VIDEO_HEVCProfileMain444_12: return HEVCProfileType::HEVC_PROFILE_MAIN_444_12; case OMX_ALG_VIDEO_HEVCProfileMain_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_INTRA; case OMX_ALG_VIDEO_HEVCProfileMain10_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_10_INTRA; case OMX_ALG_VIDEO_HEVCProfileMain12_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_12_INTRA; case OMX_ALG_VIDEO_HEVCProfileMain422_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_422_INTRA; case OMX_ALG_VIDEO_HEVCProfileMain422_10_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_422_10_INTRA; case OMX_ALG_VIDEO_HEVCProfileMain422_12_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_422_12_INTRA; case OMX_ALG_VIDEO_HEVCProfileMain444_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_444_INTRA; case OMX_ALG_VIDEO_HEVCProfileMain444_10_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_444_10_INTRA; case OMX_ALG_VIDEO_HEVCProfileMain444_12_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_444_12_INTRA; case OMX_ALG_VIDEO_HEVCProfileMain444_16_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_444_16_INTRA; case OMX_ALG_VIDEO_HEVCProfileMain444_Still: return HEVCProfileType::HEVC_PROFILE_MAIN_444_STILL; case OMX_ALG_VIDEO_HEVCProfileMain444_16_Still: return HEVCProfileType::HEVC_PROFILE_MAIN_444_16_STILL; case OMX_ALG_VIDEO_HEVCProfileHighThroughtPut444_16_Intra: return HEVCProfileType::HEVC_PROFILE_HIGH_THROUGHPUT_444_16_INTRA; case OMX_ALG_VIDEO_HEVCProfileMaxEnum: return HEVCProfileType::HEVC_PROFILE_MAX_ENUM; default: return HEVCProfileType::HEVC_PROFILE_MAX_ENUM; } return HEVCProfileType::HEVC_PROFILE_MAX_ENUM; } static inline HEVCProfileType ConvertOMXToMediaHEVCHighTierProfile(OMX_ALG_VIDEO_HEVCPROFILETYPE profile) { switch(profile) { case OMX_ALG_VIDEO_HEVCProfileMain: return HEVCProfileType::HEVC_PROFILE_MAIN_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain10: return HEVCProfileType::HEVC_PROFILE_MAIN_10_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMainStill: return HEVCProfileType::HEVC_PROFILE_MAIN_STILL_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMonochrome: return HEVCProfileType::HEVC_PROFILE_MONOCHROME_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMonochrome10: return HEVCProfileType::HEVC_PROFILE_MONOCHROME_10_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMonochrome12: return HEVCProfileType::HEVC_PROFILE_MONOCHROME_12_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMonochrome16: return HEVCProfileType::HEVC_PROFILE_MONOCHROME_16_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain12: return HEVCProfileType::HEVC_PROFILE_MAIN_12_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain422: return HEVCProfileType::HEVC_PROFILE_MAIN_422_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain422_10: return HEVCProfileType::HEVC_PROFILE_MAIN_422_10_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain422_12: return HEVCProfileType::HEVC_PROFILE_MAIN_422_12_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain444: return HEVCProfileType::HEVC_PROFILE_MAIN_444_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain444_10: return HEVCProfileType::HEVC_PROFILE_MAIN_444_10_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain444_12: return HEVCProfileType::HEVC_PROFILE_MAIN_444_12_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_INTRA_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain10_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_10_INTRA_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain12_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_12_INTRA_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain422_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_422_INTRA_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain422_10_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_422_10_INTRA_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain422_12_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_422_12_INTRA_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain444_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_444_INTRA_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain444_10_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_444_10_INTRA_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain444_12_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_444_12_INTRA_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain444_16_Intra: return HEVCProfileType::HEVC_PROFILE_MAIN_444_16_INTRA_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain444_Still: return HEVCProfileType::HEVC_PROFILE_MAIN_444_STILL_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMain444_16_Still: return HEVCProfileType::HEVC_PROFILE_MAIN_444_16_STILL_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileHighThroughtPut444_16_Intra: return HEVCProfileType::HEVC_PROFILE_HIGH_THROUGHPUT_444_16_INTRA_HIGH_TIER; case OMX_ALG_VIDEO_HEVCProfileMaxEnum: return HEVCProfileType::HEVC_PROFILE_MAX_ENUM; default: return HEVCProfileType::HEVC_PROFILE_MAX_ENUM; } return HEVCProfileType::HEVC_PROFILE_MAX_ENUM; } static inline int ConvertOMXToMediaHEVCLevel(OMX_ALG_VIDEO_HEVCLEVELTYPE level) { switch(level) { case OMX_ALG_VIDEO_HEVCMainTierLevel1: return 10; case OMX_ALG_VIDEO_HEVCMainTierLevel2: return 20; case OMX_ALG_VIDEO_HEVCMainTierLevel21: return 21; case OMX_ALG_VIDEO_HEVCMainTierLevel3: return 30; case OMX_ALG_VIDEO_HEVCMainTierLevel31: return 31; case OMX_ALG_VIDEO_HEVCMainTierLevel4: case OMX_ALG_VIDEO_HEVCHighTierLevel4: return 40; case OMX_ALG_VIDEO_HEVCMainTierLevel41: case OMX_ALG_VIDEO_HEVCHighTierLevel41: return 41; case OMX_ALG_VIDEO_HEVCMainTierLevel5: case OMX_ALG_VIDEO_HEVCHighTierLevel5: return 50; case OMX_ALG_VIDEO_HEVCMainTierLevel51: case OMX_ALG_VIDEO_HEVCHighTierLevel51: return 51; case OMX_ALG_VIDEO_HEVCMainTierLevel52: case OMX_ALG_VIDEO_HEVCHighTierLevel52: return 52; case OMX_ALG_VIDEO_HEVCMainTierLevel6: case OMX_ALG_VIDEO_HEVCHighTierLevel6: return 60; case OMX_ALG_VIDEO_HEVCMainTierLevel61: case OMX_ALG_VIDEO_HEVCHighTierLevel61: return 61; case OMX_ALG_VIDEO_HEVCMainTierLevel62: case OMX_ALG_VIDEO_HEVCHighTierLevel62: return 62; default: return 0; } return 0; } static inline bool IsMainTier(OMX_ALG_VIDEO_HEVCLEVELTYPE level) { switch(level) { case OMX_ALG_VIDEO_HEVCMainTierLevel1: case OMX_ALG_VIDEO_HEVCMainTierLevel2: case OMX_ALG_VIDEO_HEVCMainTierLevel21: case OMX_ALG_VIDEO_HEVCMainTierLevel3: case OMX_ALG_VIDEO_HEVCMainTierLevel31: case OMX_ALG_VIDEO_HEVCMainTierLevel4: case OMX_ALG_VIDEO_HEVCMainTierLevel41: case OMX_ALG_VIDEO_HEVCMainTierLevel5: case OMX_ALG_VIDEO_HEVCMainTierLevel51: case OMX_ALG_VIDEO_HEVCMainTierLevel52: case OMX_ALG_VIDEO_HEVCMainTierLevel6: case OMX_ALG_VIDEO_HEVCMainTierLevel61: case OMX_ALG_VIDEO_HEVCMainTierLevel62: return true; default: return false; } return false; } ProfileLevel ConvertOMXToMediaHEVCProfileLevel(OMX_ALG_VIDEO_HEVCPROFILETYPE profile, OMX_ALG_VIDEO_HEVCLEVELTYPE level) { ProfileLevel pf; pf.profile.hevc = IsMainTier(level) ? ConvertOMXToMediaHEVCMainTierProfile(profile) : ConvertOMXToMediaHEVCHighTierProfile(profile); pf.level = ConvertOMXToMediaHEVCLevel(level); return pf; } OMX_ALG_VIDEO_HEVCPROFILETYPE ConvertMediaToOMXHEVCProfile(ProfileLevel profileLevel) { switch(profileLevel.profile.hevc) { case HEVCProfileType::HEVC_PROFILE_MAIN: case HEVCProfileType::HEVC_PROFILE_MAIN_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain; case HEVCProfileType::HEVC_PROFILE_MAIN_10: case HEVCProfileType::HEVC_PROFILE_MAIN_10_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain10; case HEVCProfileType::HEVC_PROFILE_MAIN_STILL: case HEVCProfileType::HEVC_PROFILE_MAIN_STILL_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMainStill; case HEVCProfileType::HEVC_PROFILE_MONOCHROME: case HEVCProfileType::HEVC_PROFILE_MONOCHROME_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMonochrome; case HEVCProfileType::HEVC_PROFILE_MONOCHROME_10: case HEVCProfileType::HEVC_PROFILE_MONOCHROME_10_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMonochrome10; case HEVCProfileType::HEVC_PROFILE_MONOCHROME_12: case HEVCProfileType::HEVC_PROFILE_MONOCHROME_12_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMonochrome12; case HEVCProfileType::HEVC_PROFILE_MONOCHROME_16: case HEVCProfileType::HEVC_PROFILE_MONOCHROME_16_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMonochrome16; case HEVCProfileType::HEVC_PROFILE_MAIN_12: case HEVCProfileType::HEVC_PROFILE_MAIN_12_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain12; case HEVCProfileType::HEVC_PROFILE_MAIN_422: case HEVCProfileType::HEVC_PROFILE_MAIN_422_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain422; case HEVCProfileType::HEVC_PROFILE_MAIN_422_10: case HEVCProfileType::HEVC_PROFILE_MAIN_422_10_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain422_10; case HEVCProfileType::HEVC_PROFILE_MAIN_422_12: case HEVCProfileType::HEVC_PROFILE_MAIN_422_12_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain422_12; case HEVCProfileType::HEVC_PROFILE_MAIN_444: case HEVCProfileType::HEVC_PROFILE_MAIN_444_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain444; case HEVCProfileType::HEVC_PROFILE_MAIN_444_10: case HEVCProfileType::HEVC_PROFILE_MAIN_444_10_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain444_10; case HEVCProfileType::HEVC_PROFILE_MAIN_444_12: case HEVCProfileType::HEVC_PROFILE_MAIN_444_12_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain444_12; case HEVCProfileType::HEVC_PROFILE_MAIN_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_INTRA_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain_Intra; case HEVCProfileType::HEVC_PROFILE_MAIN_10_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_10_INTRA_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain10_Intra; case HEVCProfileType::HEVC_PROFILE_MAIN_12_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_12_INTRA_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain12_Intra; case HEVCProfileType::HEVC_PROFILE_MAIN_422_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_422_INTRA_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain422_Intra; case HEVCProfileType::HEVC_PROFILE_MAIN_422_10_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_422_10_INTRA_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain422_10_Intra; case HEVCProfileType::HEVC_PROFILE_MAIN_422_12_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_422_12_INTRA_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain422_12_Intra; case HEVCProfileType::HEVC_PROFILE_MAIN_444_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_444_INTRA_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain444_Intra; case HEVCProfileType::HEVC_PROFILE_MAIN_444_10_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_444_10_INTRA_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain444_10_Intra; case HEVCProfileType::HEVC_PROFILE_MAIN_444_12_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_444_12_INTRA_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain444_12_Intra; case HEVCProfileType::HEVC_PROFILE_MAIN_444_16_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_444_16_INTRA_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain444_16_Intra; case HEVCProfileType::HEVC_PROFILE_MAIN_444_STILL: case HEVCProfileType::HEVC_PROFILE_MAIN_444_STILL_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain444_Still; case HEVCProfileType::HEVC_PROFILE_MAIN_444_16_STILL: case HEVCProfileType::HEVC_PROFILE_MAIN_444_16_STILL_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileMain444_Still; case HEVCProfileType::HEVC_PROFILE_HIGH_THROUGHPUT_444_16_INTRA: case HEVCProfileType::HEVC_PROFILE_HIGH_THROUGHPUT_444_16_INTRA_HIGH_TIER: return OMX_ALG_VIDEO_HEVCProfileHighThroughtPut444_16_Intra; default: return OMX_ALG_VIDEO_HEVCProfileMaxEnum; } return OMX_ALG_VIDEO_HEVCProfileMaxEnum; } static inline OMX_ALG_VIDEO_HEVCLEVELTYPE ConvertMediaToOMXHEVCMainLevel(ProfileLevel profileLevel) { switch(profileLevel.level) { case 10: return OMX_ALG_VIDEO_HEVCMainTierLevel1; case 20: return OMX_ALG_VIDEO_HEVCMainTierLevel2; case 21: return OMX_ALG_VIDEO_HEVCMainTierLevel21; case 30: return OMX_ALG_VIDEO_HEVCMainTierLevel3; case 31: return OMX_ALG_VIDEO_HEVCMainTierLevel31; case 40: return OMX_ALG_VIDEO_HEVCMainTierLevel4; case 41: return OMX_ALG_VIDEO_HEVCMainTierLevel41; case 50: return OMX_ALG_VIDEO_HEVCMainTierLevel5; case 51: return OMX_ALG_VIDEO_HEVCMainTierLevel51; case 52: return OMX_ALG_VIDEO_HEVCMainTierLevel52; case 60: return OMX_ALG_VIDEO_HEVCMainTierLevel6; case 61: return OMX_ALG_VIDEO_HEVCMainTierLevel61; case 62: return OMX_ALG_VIDEO_HEVCMainTierLevel62; default: return OMX_ALG_VIDEO_HEVCLevelMaxEnum; } return OMX_ALG_VIDEO_HEVCLevelMaxEnum; } static inline OMX_ALG_VIDEO_HEVCLEVELTYPE ConvertMediaToOMXHEVCHighLevel(ProfileLevel profileLevel) { switch(profileLevel.level) { case 40: return OMX_ALG_VIDEO_HEVCHighTierLevel4; case 41: return OMX_ALG_VIDEO_HEVCHighTierLevel41; case 50: return OMX_ALG_VIDEO_HEVCHighTierLevel5; case 51: return OMX_ALG_VIDEO_HEVCHighTierLevel51; case 52: return OMX_ALG_VIDEO_HEVCHighTierLevel52; case 60: return OMX_ALG_VIDEO_HEVCHighTierLevel6; case 61: return OMX_ALG_VIDEO_HEVCHighTierLevel61; case 62: return OMX_ALG_VIDEO_HEVCHighTierLevel62; default: return OMX_ALG_VIDEO_HEVCLevelMaxEnum; } return OMX_ALG_VIDEO_HEVCLevelMaxEnum; } static inline bool IsMainTier(ProfileLevel profileLevel) { switch(profileLevel.profile.hevc) { case HEVCProfileType::HEVC_PROFILE_MONOCHROME: case HEVCProfileType::HEVC_PROFILE_MONOCHROME_10: case HEVCProfileType::HEVC_PROFILE_MONOCHROME_12: case HEVCProfileType::HEVC_PROFILE_MONOCHROME_16: case HEVCProfileType::HEVC_PROFILE_MAIN: case HEVCProfileType::HEVC_PROFILE_MAIN_10: case HEVCProfileType::HEVC_PROFILE_MAIN_12: case HEVCProfileType::HEVC_PROFILE_MAIN_16: case HEVCProfileType::HEVC_PROFILE_MAIN_422: case HEVCProfileType::HEVC_PROFILE_MAIN_422_10: case HEVCProfileType::HEVC_PROFILE_MAIN_422_12: case HEVCProfileType::HEVC_PROFILE_MAIN_422_16: case HEVCProfileType::HEVC_PROFILE_MAIN_444: case HEVCProfileType::HEVC_PROFILE_MAIN_444_10: case HEVCProfileType::HEVC_PROFILE_MAIN_444_12: case HEVCProfileType::HEVC_PROFILE_MAIN_444_16: case HEVCProfileType::HEVC_PROFILE_MAIN_STILL: case HEVCProfileType::HEVC_PROFILE_MAIN_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_10_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_12_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_16_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_422_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_422_10_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_422_12_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_422_16_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_444_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_444_10_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_444_12_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_444_16_INTRA: case HEVCProfileType::HEVC_PROFILE_MAIN_444_STILL: case HEVCProfileType::HEVC_PROFILE_MAIN_444_16_STILL: case HEVCProfileType::HEVC_PROFILE_HIGH_THROUGHPUT_444_16_INTRA: return true; default: return false; } return false; } OMX_ALG_VIDEO_HEVCLEVELTYPE ConvertMediaToOMXHEVCLevel(ProfileLevel profileLevel) { return IsMainTier(profileLevel) ? ConvertMediaToOMXHEVCMainLevel(profileLevel) : ConvertMediaToOMXHEVCHighLevel(profileLevel); } BufferModeType ConvertOMXToMediaBufferMode(OMX_ALG_VIDEO_BUFFER_MODE mode) { switch(mode) { case OMX_ALG_VIDEO_BUFFER_MODE_FRAME: return BufferModeType::BUFFER_MODE_FRAME; case OMX_ALG_VIDEO_BUFFER_MODE_FRAME_NO_REORDERING: return BufferModeType::BUFFER_MODE_FRAME_NO_REORDERING; case OMX_ALG_VIDEO_BUFFER_MODE_SLICE: return BufferModeType::BUFFER_MODE_SLICE; case OMX_ALG_VIDEO_BUFFER_MODE_MAX_ENUM: return BufferModeType::BUFFER_MODE_MAX_ENUM; default: return BufferModeType::BUFFER_MODE_MAX_ENUM; } return BufferModeType::BUFFER_MODE_MAX_ENUM; } OMX_ALG_VIDEO_BUFFER_MODE ConvertMediaToOMXBufferMode(BufferModeType mode) { switch(mode) { case BufferModeType::BUFFER_MODE_FRAME: return OMX_ALG_VIDEO_BUFFER_MODE_FRAME; case BufferModeType::BUFFER_MODE_FRAME_NO_REORDERING: return OMX_ALG_VIDEO_BUFFER_MODE_FRAME_NO_REORDERING; case BufferModeType::BUFFER_MODE_SLICE: return OMX_ALG_VIDEO_BUFFER_MODE_SLICE; case BufferModeType::BUFFER_MODE_MAX_ENUM: return OMX_ALG_VIDEO_BUFFER_MODE_MAX_ENUM; default: return OMX_ALG_VIDEO_BUFFER_MODE_MAX_ENUM; } return OMX_ALG_VIDEO_BUFFER_MODE_MAX_ENUM; } QualityType ConvertOMXToMediaQualityPreset(OMX_ALG_ERoiQuality quality) { switch(quality) { case OMX_ALG_ROI_QUALITY_HIGH: return QualityType::REGION_OF_INTEREST_QUALITY_HIGH; case OMX_ALG_ROI_QUALITY_MEDIUM: return QualityType::REGION_OF_INTEREST_QUALITY_MEDIUM; case OMX_ALG_ROI_QUALITY_LOW: return QualityType::REGION_OF_INTEREST_QUALITY_LOW; case OMX_ALG_ROI_QUALITY_DONT_CARE: return QualityType::REGION_OF_INTEREST_QUALITY_DONT_CARE; case OMX_ALG_ROI_QUALITY_INTRA: return QualityType::REGION_OF_INTEREST_QUALITY_INTRA; case OMX_ALG_ROI_QUALITY_MAX_ENUM: return QualityType::REGION_OF_INTEREST_QUALITY_MAX_ENUM; default: return QualityType::REGION_OF_INTEREST_QUALITY_MAX_ENUM; } return QualityType::REGION_OF_INTEREST_QUALITY_MAX_ENUM; } int ConvertOMXToMediaQualityValue(OMX_S32 quality) { return static_cast(quality); } OMX_U32 ConvertMediaToOMXInterlaceFlag(VideoModeType mode) { switch(mode) { case VideoModeType::VIDEO_MODE_PROGRESSIVE: return OMX_InterlaceFrameProgressive; case VideoModeType::VIDEO_MODE_ALTERNATE_TOP_BOTTOM_FIELD: return OMX_ALG_InterlaceAlternateTopFieldFirst; case VideoModeType::VIDEO_MODE_ALTERNATE_BOTTOM_TOP_FIELD: return OMX_ALG_InterlaceAlternateBottomFieldFirst; case VideoModeType::VIDEO_MODE_MAX_ENUM: assert(0); default: assert(0); } assert(0); return 0; } VideoModeType ConvertOMXToMediaVideoMode(OMX_U32 flag) { switch(flag) { case OMX_InterlaceFrameProgressive: return VideoModeType::VIDEO_MODE_PROGRESSIVE; case OMX_ALG_InterlaceAlternateTopFieldFirst: return VideoModeType::VIDEO_MODE_ALTERNATE_TOP_BOTTOM_FIELD; case OMX_ALG_InterlaceAlternateBottomFieldFirst: return VideoModeType::VIDEO_MODE_ALTERNATE_BOTTOM_TOP_FIELD; default: assert(0); return VideoModeType::VIDEO_MODE_MAX_ENUM; } assert(0); return VideoModeType::VIDEO_MODE_MAX_ENUM; } SequencePictureModeType ConvertOMXToMediaSequencePictureMode(OMX_ALG_SEQUENCE_PICTURE_MODE mode) { switch(mode) { case OMX_ALG_SEQUENCE_PICTURE_UNKNOWN: return SequencePictureModeType::SEQUENCE_PICTURE_MODE_UNKNOWN; case OMX_ALG_SEQUENCE_PICTURE_FRAME: return SequencePictureModeType::SEQUENCE_PICTURE_MODE_FRAME; case OMX_ALG_SEQUENCE_PICTURE_FIELD: return SequencePictureModeType::SEQUENCE_PICTURE_MODE_FIELD; case OMX_ALG_SEQUENCE_PICTURE_FRAME_AND_FIELD: return SequencePictureModeType::SEQUENCE_PICTURE_MODE_FRAME_AND_FIELD; case OMX_ALG_SEQUENCE_PICTURE_MAX_ENUM: return SequencePictureModeType::SEQUENCE_PICTURE_MODE_MAX_ENUM; default: return SequencePictureModeType::SEQUENCE_PICTURE_MODE_MAX_ENUM; } return SequencePictureModeType::SEQUENCE_PICTURE_MODE_MAX_ENUM; } OMX_ALG_SEQUENCE_PICTURE_MODE ConvertMediaToOMXSequencePictureMode(SequencePictureModeType mode) { switch(mode) { case SequencePictureModeType::SEQUENCE_PICTURE_MODE_UNKNOWN: return OMX_ALG_SEQUENCE_PICTURE_UNKNOWN; case SequencePictureModeType::SEQUENCE_PICTURE_MODE_FRAME: return OMX_ALG_SEQUENCE_PICTURE_FRAME; case SequencePictureModeType::SEQUENCE_PICTURE_MODE_FIELD: return OMX_ALG_SEQUENCE_PICTURE_FIELD; case SequencePictureModeType::SEQUENCE_PICTURE_MODE_FRAME_AND_FIELD: return OMX_ALG_SEQUENCE_PICTURE_FRAME_AND_FIELD; case SequencePictureModeType::SEQUENCE_PICTURE_MODE_MAX_ENUM: return OMX_ALG_SEQUENCE_PICTURE_MAX_ENUM; default: return OMX_ALG_SEQUENCE_PICTURE_MAX_ENUM; } return OMX_ALG_SEQUENCE_PICTURE_MAX_ENUM; } OMX_ALG_VIDEO_COLOR_PRIMARIESTYPE ConvertMediaToOMXColorPrimaries(ColorPrimariesType colorPrimaries) { switch(colorPrimaries) { case ColorPrimariesType::COLOR_PRIMARIES_UNSPECIFIED: return OMX_ALG_VIDEO_COLOR_PRIMARIES_UNSPECIFIED; case ColorPrimariesType::COLOR_PRIMARIES_RESERVED: return OMX_ALG_VIDEO_COLOR_PRIMARIES_RESERVED; case ColorPrimariesType::COLOR_PRIMARIES_BT_470_NTSC: return OMX_ALG_VIDEO_COLOR_PRIMARIES_BT_470_NTSC; case ColorPrimariesType::COLOR_PRIMARIES_BT_601_NTSC: return OMX_ALG_VIDEO_COLOR_PRIMARIES_BT_601_NTSC; case ColorPrimariesType::COLOR_PRIMARIES_BT_601_PAL: return OMX_ALG_VIDEO_COLOR_PRIMARIES_BT_601_PAL; case ColorPrimariesType::COLOR_PRIMARIES_BT_709: return OMX_ALG_VIDEO_COLOR_PRIMARIES_BT_709; case ColorPrimariesType::COLOR_PRIMARIES_BT_2020: return OMX_ALG_VIDEO_COLOR_PRIMARIES_BT_2020; case ColorPrimariesType::COLOR_PRIMARIES_SMPTE_240M: return OMX_ALG_VIDEO_COLOR_PRIMARIES_SMPTE_240M; case ColorPrimariesType::COLOR_PRIMARIES_SMPTE_ST_428: return OMX_ALG_VIDEO_COLOR_PRIMARIES_SMPTE_ST_428; case ColorPrimariesType::COLOR_PRIMARIES_SMPTE_RP_431: return OMX_ALG_VIDEO_COLOR_PRIMARIES_SMPTE_RP_431; case ColorPrimariesType::COLOR_PRIMARIES_SMPTE_EG_432: return OMX_ALG_VIDEO_COLOR_PRIMARIES_SMPTE_EG_432; case ColorPrimariesType::COLOR_PRIMARIES_EBU_3213: return OMX_ALG_VIDEO_COLOR_PRIMARIES_EBU_3213; case ColorPrimariesType::COLOR_PRIMARIES_GENERIC_FILM: return OMX_ALG_VIDEO_COLOR_PRIMARIES_GENERIC_FILM; case ColorPrimariesType::COLOR_PRIMARIES_MAX_ENUM: return OMX_ALG_VIDEO_COLOR_PRIMARIES_MAX_ENUM; default: return OMX_ALG_VIDEO_COLOR_PRIMARIES_MAX_ENUM; } return OMX_ALG_VIDEO_COLOR_PRIMARIES_MAX_ENUM; } ColorPrimariesType ConvertOMXToMediaColorPrimaries(OMX_ALG_VIDEO_COLOR_PRIMARIESTYPE colorPrimaries) { switch(colorPrimaries) { case OMX_ALG_VIDEO_COLOR_PRIMARIES_UNSPECIFIED: return ColorPrimariesType::COLOR_PRIMARIES_UNSPECIFIED; case OMX_ALG_VIDEO_COLOR_PRIMARIES_RESERVED: return ColorPrimariesType::COLOR_PRIMARIES_RESERVED; case OMX_ALG_VIDEO_COLOR_PRIMARIES_BT_470_NTSC: return ColorPrimariesType::COLOR_PRIMARIES_BT_470_NTSC; case OMX_ALG_VIDEO_COLOR_PRIMARIES_BT_601_NTSC: return ColorPrimariesType::COLOR_PRIMARIES_BT_601_NTSC; case OMX_ALG_VIDEO_COLOR_PRIMARIES_BT_601_PAL: return ColorPrimariesType::COLOR_PRIMARIES_BT_601_PAL; case OMX_ALG_VIDEO_COLOR_PRIMARIES_BT_709: return ColorPrimariesType::COLOR_PRIMARIES_BT_709; case OMX_ALG_VIDEO_COLOR_PRIMARIES_BT_2020: return ColorPrimariesType::COLOR_PRIMARIES_BT_2020; case OMX_ALG_VIDEO_COLOR_PRIMARIES_SMPTE_240M: return ColorPrimariesType::COLOR_PRIMARIES_SMPTE_240M; case OMX_ALG_VIDEO_COLOR_PRIMARIES_SMPTE_ST_428: return ColorPrimariesType::COLOR_PRIMARIES_SMPTE_ST_428; case OMX_ALG_VIDEO_COLOR_PRIMARIES_SMPTE_RP_431: return ColorPrimariesType::COLOR_PRIMARIES_SMPTE_RP_431; case OMX_ALG_VIDEO_COLOR_PRIMARIES_SMPTE_EG_432: return ColorPrimariesType::COLOR_PRIMARIES_SMPTE_EG_432; case OMX_ALG_VIDEO_COLOR_PRIMARIES_EBU_3213: return ColorPrimariesType::COLOR_PRIMARIES_EBU_3213; case OMX_ALG_VIDEO_COLOR_PRIMARIES_GENERIC_FILM: return ColorPrimariesType::COLOR_PRIMARIES_GENERIC_FILM; case OMX_ALG_VIDEO_COLOR_PRIMARIES_MAX_ENUM: return ColorPrimariesType::COLOR_PRIMARIES_MAX_ENUM; default: return ColorPrimariesType::COLOR_PRIMARIES_MAX_ENUM; } return ColorPrimariesType::COLOR_PRIMARIES_MAX_ENUM; } OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS ConvertMediaToOMXTransferCharacteristics(TransferCharacteristicsType transferCharac) { switch(transferCharac) { case TransferCharacteristicsType::TRANSFER_CHARACTERISTICS_UNSPECIFIED: return OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS_UNSPECIFIED; case TransferCharacteristicsType::TRANSFER_CHARACTERISTICS_BT_2100_PQ: return OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS_BT_2100_PQ; case TransferCharacteristicsType::TRANSFER_CHARACTERISTICS_BT_2100_HLG: return OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS_BT_2100_HLG; default: return OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS_MAX_ENUM; } return OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS_MAX_ENUM; } TransferCharacteristicsType ConvertOMXToMediaTransferCharacteristics(OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS transferCharac) { switch(transferCharac) { case OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS_UNSPECIFIED: return TransferCharacteristicsType::TRANSFER_CHARACTERISTICS_UNSPECIFIED; case OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS_BT_2100_PQ: return TransferCharacteristicsType::TRANSFER_CHARACTERISTICS_BT_2100_PQ; case OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS_BT_2100_HLG: return TransferCharacteristicsType::TRANSFER_CHARACTERISTICS_BT_2100_HLG; default: return TransferCharacteristicsType::TRANSFER_CHARACTERISTICS_MAX_ENUM; } return TransferCharacteristicsType::TRANSFER_CHARACTERISTICS_MAX_ENUM; } OMX_ALG_VIDEO_COLOR_MATRIX ConvertMediaToOMXColourMatrix(ColourMatrixType colourMatrix) { switch(colourMatrix) { case ColourMatrixType::COLOUR_MATRIX_UNSPECIFIED: return OMX_ALG_VIDEO_COLOR_MATRIX_UNSPECIFIED; case ColourMatrixType::COLOUR_MATRIX_BT_2100_YCBCR: return OMX_ALG_VIDEO_COLOR_MATRIX_BT_2100_YCBCR; default: return OMX_ALG_VIDEO_COLOR_MATRIX_MAX_ENUM; } return OMX_ALG_VIDEO_COLOR_MATRIX_MAX_ENUM; } ColourMatrixType ConvertOMXToMediaColourMatrix(OMX_ALG_VIDEO_COLOR_MATRIX colourMatrix) { switch(colourMatrix) { case OMX_ALG_VIDEO_COLOR_MATRIX_UNSPECIFIED: return ColourMatrixType::COLOUR_MATRIX_UNSPECIFIED; case OMX_ALG_VIDEO_COLOR_MATRIX_BT_2100_YCBCR: return ColourMatrixType::COLOUR_MATRIX_BT_2100_YCBCR; default: return ColourMatrixType::COLOUR_MATRIX_MAX_ENUM; } return ColourMatrixType::COLOUR_MATRIX_MAX_ENUM; } void ConvertMediaToOMX_DPL_ST2094_40(OMX_ALG_DISPLAY_PEAK_LUMINANCE_ST2094_40& dst, DisplayPeakLuminance_ST2094_40 const& src) { dst.bActualPeakLuminanceFlag = ConvertMediaToOMXBool(src.actualPeakLuminanceFlag); if(src.actualPeakLuminanceFlag) { dst.nNumRowsActualPeakLuminance = src.numRowsActualPeakLuminance; dst.nNumColsActualPeakLuminance = src.numColsActualPeakLuminance; for(int i = 0; i < src.numRowsActualPeakLuminance; i++) for(int j = 0; j < src.numColsActualPeakLuminance; j++) dst.nActualPeakLuminance[i][j] = src.actualPeakLuminance[i][j]; } } OMX_ALG_VIDEO_CONFIG_HIGH_DYNAMIC_RANGE_SEI ConvertMediaToOMXHDRSEI(HighDynamicRangeSeis const& hdrSEIs) { OMX_ALG_VIDEO_CONFIG_HIGH_DYNAMIC_RANGE_SEI omxHDRSEIs; omxHDRSEIs.bHasMDCV = ConvertMediaToOMXBool(hdrSEIs.hasMDCV); if(hdrSEIs.hasMDCV) { for(int i = 0; i < 3; i++) { omxHDRSEIs.masteringDisplayColourVolume.displayPrimaries[i].nX = hdrSEIs.masteringDisplayColourVolume.displayPrimaries[i].x; omxHDRSEIs.masteringDisplayColourVolume.displayPrimaries[i].nY = hdrSEIs.masteringDisplayColourVolume.displayPrimaries[i].y; } omxHDRSEIs.masteringDisplayColourVolume.whitePoint.nX = hdrSEIs.masteringDisplayColourVolume.whitePoint.x; omxHDRSEIs.masteringDisplayColourVolume.whitePoint.nY = hdrSEIs.masteringDisplayColourVolume.whitePoint.y; omxHDRSEIs.masteringDisplayColourVolume.nMaxDisplayMasteringLuminance = hdrSEIs.masteringDisplayColourVolume.maxDisplayMasteringLuminance; omxHDRSEIs.masteringDisplayColourVolume.nMinDisplayMasteringLuminance = hdrSEIs.masteringDisplayColourVolume.minDisplayMasteringLuminance; } omxHDRSEIs.bHasCLL = ConvertMediaToOMXBool(hdrSEIs.hasCLL); if(hdrSEIs.hasCLL) { omxHDRSEIs.contentLightLevel.nMaxContentLightLevel = hdrSEIs.contentLightLevel.maxContentLightLevel; omxHDRSEIs.contentLightLevel.nMaxPicAverageLightLevel = hdrSEIs.contentLightLevel.maxPicAverageLightLevel; } omxHDRSEIs.bHasST2094_10 = ConvertMediaToOMXBool(hdrSEIs.hasST2094_10); if(hdrSEIs.hasST2094_10) { omxHDRSEIs.st2094_10.nApplicationVersion = hdrSEIs.st2094_10.applicationVersion; omxHDRSEIs.st2094_10.bProcessingWindowFlag = ConvertMediaToOMXBool(hdrSEIs.st2094_10.processingWindowFlag); if(hdrSEIs.st2094_10.processingWindowFlag) { omxHDRSEIs.st2094_10.processingWindow.nActiveAreaLeftOffset = hdrSEIs.st2094_10.processingWindow.activeAreaLeftOffset; omxHDRSEIs.st2094_10.processingWindow.nActiveAreaRightOffset = hdrSEIs.st2094_10.processingWindow.activeAreaRightOffset; omxHDRSEIs.st2094_10.processingWindow.nActiveAreaTopOffset = hdrSEIs.st2094_10.processingWindow.activeAreaTopOffset; omxHDRSEIs.st2094_10.processingWindow.nActiveAreaBottomOffset = hdrSEIs.st2094_10.processingWindow.activeAreaBottomOffset; } omxHDRSEIs.st2094_10.imageCharacteristics.nMinPQ = hdrSEIs.st2094_10.imageCharacteristics.minPQ; omxHDRSEIs.st2094_10.imageCharacteristics.nMaxPQ = hdrSEIs.st2094_10.imageCharacteristics.maxPQ; omxHDRSEIs.st2094_10.imageCharacteristics.nAvgPQ = hdrSEIs.st2094_10.imageCharacteristics.avgPQ; omxHDRSEIs.st2094_10.nNumManualAdjustments = hdrSEIs.st2094_10.numManualAdjustments; for(int i = 0; i < hdrSEIs.st2094_10.numManualAdjustments; i++) { omxHDRSEIs.st2094_10.manualAdjustments[i].nTargetMaxPQ = hdrSEIs.st2094_10.manualAdjustments[i].targetMaxPQ; omxHDRSEIs.st2094_10.manualAdjustments[i].nTrimSlope = hdrSEIs.st2094_10.manualAdjustments[i].trimSlope; omxHDRSEIs.st2094_10.manualAdjustments[i].nTrimOffset = hdrSEIs.st2094_10.manualAdjustments[i].trimOffset; omxHDRSEIs.st2094_10.manualAdjustments[i].nTrimPower = hdrSEIs.st2094_10.manualAdjustments[i].trimPower; omxHDRSEIs.st2094_10.manualAdjustments[i].nTrimChromaWeight = hdrSEIs.st2094_10.manualAdjustments[i].trimChromaWeight; omxHDRSEIs.st2094_10.manualAdjustments[i].nTrimSaturationGain = hdrSEIs.st2094_10.manualAdjustments[i].trimSaturationGain; omxHDRSEIs.st2094_10.manualAdjustments[i].nMSWeight = hdrSEIs.st2094_10.manualAdjustments[i].msWeight; } } omxHDRSEIs.bHasST2094_40 = ConvertMediaToOMXBool(hdrSEIs.hasST2094_40); if(hdrSEIs.hasST2094_40) { omxHDRSEIs.st2094_40.nApplicationVersion = hdrSEIs.st2094_40.applicationVersion; omxHDRSEIs.st2094_40.nNumWindows = hdrSEIs.st2094_40.numWindows; for(int i = 0; i < hdrSEIs.st2094_40.numWindows - 1; i++) { OMX_ALG_PROCESSING_WINDOW_ST2094_40* pOmxPW = &omxHDRSEIs.st2094_40.processingWindows[i]; const ProcessingWindow_ST2094_40* pPW = &hdrSEIs.st2094_40.processingWindows[i]; pOmxPW->baseProcessingWindow.nUpperLeftCornerX = pPW->baseProcessingWindow.upperLeftCornerX; pOmxPW->baseProcessingWindow.nUpperLeftCornerY = pPW->baseProcessingWindow.upperLeftCornerY; pOmxPW->baseProcessingWindow.nLowerRightCornerX = pPW->baseProcessingWindow.lowerRightCornerX; pOmxPW->baseProcessingWindow.nLowerRightCornerY = pPW->baseProcessingWindow.lowerRightCornerY; pOmxPW->nCenterOfEllipseX = pPW->centerOfEllipseX; pOmxPW->nCenterOfEllipseY = pPW->centerOfEllipseY; pOmxPW->nRotationAngle = pPW->rotationAngle; pOmxPW->nSemimajorAxisInternalEllipse = pPW->semimajorAxisInternalEllipse; pOmxPW->nSemimajorAxisExternalEllipse = pPW->semimajorAxisExternalEllipse; pOmxPW->nSemiminorAxisExternalEllipse = pPW->semiminorAxisExternalEllipse; pOmxPW->nOverlapProcessOption = pPW->overlapProcessOption; } omxHDRSEIs.st2094_40.targetedSystemDisplay.nMaximumLuminance = hdrSEIs.st2094_40.targetedSystemDisplay.maximumLuminance; ConvertMediaToOMX_DPL_ST2094_40(omxHDRSEIs.st2094_40.targetedSystemDisplay.peakLuminance, hdrSEIs.st2094_40.targetedSystemDisplay.peakLuminance); ConvertMediaToOMX_DPL_ST2094_40(omxHDRSEIs.st2094_40.masteringDisplayPeakLuminance, hdrSEIs.st2094_40.masteringDisplayPeakLuminance); for(int i = 0; i < hdrSEIs.st2094_40.numWindows; i++) { OMX_ALG_PROCESSING_WINDOW_TRANSFORM_ST2094_40* pOmxPWT = &omxHDRSEIs.st2094_40.processingWindowTransforms[i]; const ProcessingWindowTransform_ST2094_40* pPWT = &hdrSEIs.st2094_40.processingWindowTransforms[i]; for(int j = 0; j < 3; j++) pOmxPWT->nMaxScl[j] = pPWT->maxscl[j]; pOmxPWT->nAverageMaxrgb = pPWT->averageMaxrgb; pOmxPWT->nNumDistributionMaxrgbPercentiles = pPWT->numDistributionMaxrgbPercentiles; for(int j = 0; j < pPWT->numDistributionMaxrgbPercentiles; j++) { pOmxPWT->nDistributionMaxrgbPercentages[j] = pPWT->distributionMaxrgbPercentages[j]; pOmxPWT->nDistributionMaxrgbPercentiles[j] = pPWT->distributionMaxrgbPercentiles[j]; } pOmxPWT->nFractionBrightPixels = pPWT->fractionBrightPixels; pOmxPWT->toneMapping.bToneMappingFlag = ConvertMediaToOMXBool(pPWT->toneMapping.toneMappingFlag); if(pPWT->toneMapping.toneMappingFlag) { pOmxPWT->toneMapping.bKneePointX = pPWT->toneMapping.kneePointX; pOmxPWT->toneMapping.bKneePointY = pPWT->toneMapping.kneePointY; pOmxPWT->toneMapping.nNumBezierCurveAnchors = pPWT->toneMapping.numBezierCurveAnchors; for(int j = 0; j < pPWT->toneMapping.numBezierCurveAnchors; j++) pOmxPWT->toneMapping.nBezierCurveAnchors[j] = pPWT->toneMapping.bezierCurveAnchors[j]; } pOmxPWT->bColorSaturationMappingFlag = ConvertMediaToOMXBool(pPWT->colorSaturationMappingFlag); if(pPWT->colorSaturationMappingFlag) pOmxPWT->nColorSaturationWeight = pPWT->colorSaturationWeight; } } return omxHDRSEIs; } void ConvertOMXToMedia_DPL_ST2094_40(DisplayPeakLuminance_ST2094_40& dst, OMX_ALG_DISPLAY_PEAK_LUMINANCE_ST2094_40 const& src) { dst.actualPeakLuminanceFlag = ConvertOMXToMediaBool(src.bActualPeakLuminanceFlag); if(dst.actualPeakLuminanceFlag) { dst.numRowsActualPeakLuminance = src.nNumRowsActualPeakLuminance; dst.numColsActualPeakLuminance = src.nNumColsActualPeakLuminance; for(int i = 0; i < dst.numRowsActualPeakLuminance; i++) for(int j = 0; j < dst.numColsActualPeakLuminance; j++) dst.actualPeakLuminance[i][j] = src.nActualPeakLuminance[i][j]; } } HighDynamicRangeSeis ConvertOMXToMediaHDRSEI(OMX_ALG_VIDEO_CONFIG_HIGH_DYNAMIC_RANGE_SEI const& hdrSEIs) { HighDynamicRangeSeis modHDRSEIs; modHDRSEIs.hasMDCV = ConvertOMXToMediaBool(hdrSEIs.bHasMDCV); if(modHDRSEIs.hasMDCV) { for(int i = 0; i < 3; i++) { modHDRSEIs.masteringDisplayColourVolume.displayPrimaries[i].x = hdrSEIs.masteringDisplayColourVolume.displayPrimaries[i].nX; modHDRSEIs.masteringDisplayColourVolume.displayPrimaries[i].y = hdrSEIs.masteringDisplayColourVolume.displayPrimaries[i].nY; } modHDRSEIs.masteringDisplayColourVolume.whitePoint.x = hdrSEIs.masteringDisplayColourVolume.whitePoint.nX; modHDRSEIs.masteringDisplayColourVolume.whitePoint.y = hdrSEIs.masteringDisplayColourVolume.whitePoint.nY; modHDRSEIs.masteringDisplayColourVolume.maxDisplayMasteringLuminance = hdrSEIs.masteringDisplayColourVolume.nMaxDisplayMasteringLuminance; modHDRSEIs.masteringDisplayColourVolume.minDisplayMasteringLuminance = hdrSEIs.masteringDisplayColourVolume.nMinDisplayMasteringLuminance; } modHDRSEIs.hasCLL = ConvertOMXToMediaBool(hdrSEIs.bHasCLL); if(modHDRSEIs.hasCLL) { modHDRSEIs.contentLightLevel.maxContentLightLevel = hdrSEIs.contentLightLevel.nMaxContentLightLevel; modHDRSEIs.contentLightLevel.maxPicAverageLightLevel = hdrSEIs.contentLightLevel.nMaxPicAverageLightLevel; } modHDRSEIs.hasST2094_10 = ConvertOMXToMediaBool(hdrSEIs.bHasST2094_10); if(modHDRSEIs.hasST2094_10) { modHDRSEIs.st2094_10.applicationVersion = hdrSEIs.st2094_10.nApplicationVersion; modHDRSEIs.st2094_10.processingWindowFlag = ConvertOMXToMediaBool(hdrSEIs.st2094_10.bProcessingWindowFlag); if(modHDRSEIs.st2094_10.processingWindowFlag) { modHDRSEIs.st2094_10.processingWindow.activeAreaLeftOffset = hdrSEIs.st2094_10.processingWindow.nActiveAreaLeftOffset; modHDRSEIs.st2094_10.processingWindow.activeAreaRightOffset = hdrSEIs.st2094_10.processingWindow.nActiveAreaRightOffset; modHDRSEIs.st2094_10.processingWindow.activeAreaTopOffset = hdrSEIs.st2094_10.processingWindow.nActiveAreaTopOffset; modHDRSEIs.st2094_10.processingWindow.activeAreaBottomOffset = hdrSEIs.st2094_10.processingWindow.nActiveAreaBottomOffset; } modHDRSEIs.st2094_10.imageCharacteristics.minPQ = hdrSEIs.st2094_10.imageCharacteristics.nMinPQ; modHDRSEIs.st2094_10.imageCharacteristics.maxPQ = hdrSEIs.st2094_10.imageCharacteristics.nMaxPQ; modHDRSEIs.st2094_10.imageCharacteristics.avgPQ = hdrSEIs.st2094_10.imageCharacteristics.nAvgPQ; modHDRSEIs.st2094_10.numManualAdjustments = hdrSEIs.st2094_10.nNumManualAdjustments; for(int i = 0; i < modHDRSEIs.st2094_10.numManualAdjustments; i++) { modHDRSEIs.st2094_10.manualAdjustments[i].targetMaxPQ = hdrSEIs.st2094_10.manualAdjustments[i].nTargetMaxPQ; modHDRSEIs.st2094_10.manualAdjustments[i].trimSlope = hdrSEIs.st2094_10.manualAdjustments[i].nTrimSlope; modHDRSEIs.st2094_10.manualAdjustments[i].trimOffset = hdrSEIs.st2094_10.manualAdjustments[i].nTrimOffset; modHDRSEIs.st2094_10.manualAdjustments[i].trimPower = hdrSEIs.st2094_10.manualAdjustments[i].nTrimPower; modHDRSEIs.st2094_10.manualAdjustments[i].trimChromaWeight = hdrSEIs.st2094_10.manualAdjustments[i].nTrimChromaWeight; modHDRSEIs.st2094_10.manualAdjustments[i].trimSaturationGain = hdrSEIs.st2094_10.manualAdjustments[i].nTrimSaturationGain; modHDRSEIs.st2094_10.manualAdjustments[i].msWeight = hdrSEIs.st2094_10.manualAdjustments[i].nMSWeight; } } modHDRSEIs.hasST2094_40 = ConvertOMXToMediaBool(hdrSEIs.bHasST2094_40); if(modHDRSEIs.hasST2094_40) { modHDRSEIs.st2094_40.applicationVersion = hdrSEIs.st2094_40.nApplicationVersion; modHDRSEIs.st2094_40.numWindows = hdrSEIs.st2094_40.nNumWindows; for(int i = 0; i < modHDRSEIs.st2094_40.numWindows - 1; i++) { const OMX_ALG_PROCESSING_WINDOW_ST2094_40* pOmxPW = &hdrSEIs.st2094_40.processingWindows[i]; ProcessingWindow_ST2094_40* pPW = &modHDRSEIs.st2094_40.processingWindows[i]; pPW->baseProcessingWindow.upperLeftCornerX = pOmxPW->baseProcessingWindow.nUpperLeftCornerX; pPW->baseProcessingWindow.upperLeftCornerY = pOmxPW->baseProcessingWindow.nUpperLeftCornerY; pPW->baseProcessingWindow.lowerRightCornerX = pOmxPW->baseProcessingWindow.nLowerRightCornerX; pPW->baseProcessingWindow.lowerRightCornerY = pOmxPW->baseProcessingWindow.nLowerRightCornerY; pPW->centerOfEllipseX = pOmxPW->nCenterOfEllipseX; pPW->centerOfEllipseY = pOmxPW->nCenterOfEllipseY; pPW->rotationAngle = pOmxPW->nRotationAngle; pPW->semimajorAxisInternalEllipse = pOmxPW->nSemimajorAxisInternalEllipse; pPW->semimajorAxisExternalEllipse = pOmxPW->nSemimajorAxisExternalEllipse; pPW->semiminorAxisExternalEllipse = pOmxPW->nSemiminorAxisExternalEllipse; pPW->overlapProcessOption = pOmxPW->nOverlapProcessOption; } modHDRSEIs.st2094_40.targetedSystemDisplay.maximumLuminance = hdrSEIs.st2094_40.targetedSystemDisplay.nMaximumLuminance; ConvertOMXToMedia_DPL_ST2094_40(modHDRSEIs.st2094_40.targetedSystemDisplay.peakLuminance, hdrSEIs.st2094_40.targetedSystemDisplay.peakLuminance); ConvertOMXToMedia_DPL_ST2094_40(modHDRSEIs.st2094_40.masteringDisplayPeakLuminance, hdrSEIs.st2094_40.masteringDisplayPeakLuminance); for(int i = 0; i < modHDRSEIs.st2094_40.numWindows; i++) { const OMX_ALG_PROCESSING_WINDOW_TRANSFORM_ST2094_40* pOmxPWT = &hdrSEIs.st2094_40.processingWindowTransforms[i]; ProcessingWindowTransform_ST2094_40* pPWT = &modHDRSEIs.st2094_40.processingWindowTransforms[i]; for(int j = 0; j < 3; j++) pPWT->maxscl[j] = pOmxPWT->nMaxScl[j]; pPWT->averageMaxrgb = pOmxPWT->nAverageMaxrgb; pPWT->numDistributionMaxrgbPercentiles = pOmxPWT->nNumDistributionMaxrgbPercentiles; for(int j = 0; j < pPWT->numDistributionMaxrgbPercentiles; j++) { pPWT->distributionMaxrgbPercentages[j] = pOmxPWT->nDistributionMaxrgbPercentages[j]; pPWT->distributionMaxrgbPercentiles[j] = pOmxPWT->nDistributionMaxrgbPercentiles[j]; } pPWT->fractionBrightPixels = pOmxPWT->nFractionBrightPixels; pPWT->toneMapping.toneMappingFlag = ConvertOMXToMediaBool(pOmxPWT->toneMapping.bToneMappingFlag); if(pPWT->toneMapping.toneMappingFlag) { pPWT->toneMapping.kneePointX = pOmxPWT->toneMapping.bKneePointX; pPWT->toneMapping.kneePointY = pOmxPWT->toneMapping.bKneePointY; pPWT->toneMapping.numBezierCurveAnchors = pOmxPWT->toneMapping.nNumBezierCurveAnchors; for(int j = 0; j < pOmxPWT->toneMapping.nNumBezierCurveAnchors; j++) pPWT->toneMapping.bezierCurveAnchors[j] = pOmxPWT->toneMapping.nBezierCurveAnchors[j]; } pPWT->colorSaturationMappingFlag = ConvertOMXToMediaBool(pOmxPWT->bColorSaturationMappingFlag); if(pPWT->colorSaturationMappingFlag) pPWT->colorSaturationWeight = pOmxPWT->nColorSaturationWeight; } } return modHDRSEIs; } OMX_ALG_EQpTableMode ConvertMediaToOMXQpTable(QPTableType mode) { switch(mode) { case QPTableType::QP_TABLE_NONE: return OMX_ALG_QP_TABLE_NONE; case QPTableType::QP_TABLE_ABSOLUTE: return OMX_ALG_QP_TABLE_ABSOLUTE; case QPTableType::QP_TABLE_RELATIVE: return OMX_ALG_QP_TABLE_RELATIVE; case QPTableType::QP_TABLE_MAX_ENUM: return OMX_ALG_QP_TABLE_MAX_ENUM; default: return OMX_ALG_QP_TABLE_MAX_ENUM; } return OMX_ALG_QP_TABLE_MAX_ENUM; } QPTableType ConvertOMXToMediaQpTable(OMX_ALG_EQpTableMode mode) { switch(mode) { case OMX_ALG_QP_TABLE_NONE: return QPTableType::QP_TABLE_NONE; case OMX_ALG_QP_TABLE_ABSOLUTE: return QPTableType::QP_TABLE_ABSOLUTE; case OMX_ALG_QP_TABLE_RELATIVE: return QPTableType::QP_TABLE_RELATIVE; case OMX_ALG_QP_TABLE_MAX_ENUM: return QPTableType::QP_TABLE_MAX_ENUM; default: return QPTableType::QP_TABLE_MAX_ENUM; } return QPTableType::QP_TABLE_MAX_ENUM; } vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_convert_omx_media.h000066400000000000000000000157151373706561700256630ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include #include #include #include "module/module_enums.h" #include "module/module_structs.h" ColorType ConvertOMXToMediaColor(OMX_COLOR_FORMATTYPE format); OMX_COLOR_FORMATTYPE ConvertMediaToOMXColor(ColorType color, int bitdepth); CompressionType ConvertOMXToMediaCompression(OMX_VIDEO_CODINGTYPE coding); OMX_VIDEO_CODINGTYPE ConvertMediaToOMXCompression(CompressionType compression); OMX_U32 ConvertMediaToOMXFramerate(Clock clock); int ConvertOMXToMediaBitdepth(OMX_COLOR_FORMATTYPE format); Clock ConvertOMXToMediaClock(OMX_U32 framerateInQ16); bool ConvertOMXToMediaBool(OMX_BOOL boolean); OMX_BOOL ConvertMediaToOMXBool(bool boolean); BufferHandleType ConvertOMXToMediaBufferHandle(OMX_ALG_BUFFER_MODE bufferMode); OMX_ALG_BUFFER_MODE ConvertMediaToOMXBufferHandle(BufferHandleType handle); DecodedPictureBufferType ConvertOMXToMediaDecodedPictureBuffer(OMX_ALG_EDpbMode mode); OMX_ALG_EDpbMode ConvertMediaToOMXDecodedPictureBuffer(DecodedPictureBufferType mode); ProfileLevel ConvertOMXToMediaAVCProfileLevel(OMX_VIDEO_AVCPROFILETYPE profile, OMX_VIDEO_AVCLEVELTYPE level); OMX_VIDEO_AVCPROFILETYPE ConvertMediaToOMXAVCProfile(ProfileLevel profileLevel); OMX_VIDEO_AVCLEVELTYPE ConvertMediaToOMXAVCLevel(ProfileLevel profileLevel); ProfileLevel ConvertOMXToMediaHEVCProfileLevel(OMX_ALG_VIDEO_HEVCPROFILETYPE profile, OMX_ALG_VIDEO_HEVCLEVELTYPE level); OMX_ALG_VIDEO_HEVCPROFILETYPE ConvertMediaToOMXHEVCProfile(ProfileLevel profileLevel); OMX_ALG_VIDEO_HEVCLEVELTYPE ConvertMediaToOMXHEVCLevel(ProfileLevel profileLevel); LoopFilterType ConvertOMXToMediaAVCLoopFilter(OMX_VIDEO_AVCLOOPFILTERTYPE loopFilter); OMX_VIDEO_AVCLOOPFILTERTYPE ConvertMediaToOMXAVCLoopFilter(LoopFilterType loopFilter); LoopFilterType ConvertOMXToMediaHEVCLoopFilter(OMX_ALG_VIDEO_HEVCLOOPFILTERTYPE loopFilter); OMX_ALG_VIDEO_HEVCLOOPFILTERTYPE ConvertMediaToOMXHEVCLoopFilter(LoopFilterType loopFilter); int ConvertOMXToMediaBFrames(OMX_U32 bFrames, OMX_U32 pFrames); int ConvertOMXToMediaGopLength(OMX_U32 bFrames, OMX_U32 pFrames); OMX_U32 ConvertMediaToOMXBFrames(Gop gop); OMX_U32 ConvertMediaToOMXPFrames(Gop gop); EntropyCodingType ConvertOMXToMediaEntropyCoding(OMX_BOOL isCabac); OMX_BOOL ConvertMediaToOMXEntropyCoding(EntropyCodingType mode); int ConvertOMXToMediaQpInitial(OMX_U32 qpI); int ConvertOMXToMediaQpDeltaIP(OMX_U32 qpI, OMX_U32 qpP); int ConvertOMXToMediaQpDeltaPB(OMX_U32 pP, OMX_U32 qpB); OMX_U32 ConvertMediaToOMXQpI(QPs qps); OMX_U32 ConvertMediaToOMXQpP(QPs qps); OMX_U32 ConvertMediaToOMXQpB(QPs qps); int ConvertOMXToMediaQpMin(OMX_S32 qpMin); OMX_S32 ConvertMediaToOMXQpMin(QPs qps); int ConvertOMXToMediaQpMax(OMX_S32 qpMax); OMX_S32 ConvertMediaToOMXQpMax(QPs qps); QPControlType ConvertOMXToMediaQpCtrlMode(OMX_ALG_EQpCtrlMode mode); OMX_ALG_EQpCtrlMode ConvertMediaToOMXQpCtrlMode(QPControlType mode); RateControlType ConvertOMXToMediaControlRate(OMX_VIDEO_CONTROLRATETYPE mode); OMX_VIDEO_CONTROLRATETYPE ConvertMediaToOMXControlRate(RateControlType mode); AspectRatioType ConvertOMXToMediaAspectRatio(OMX_ALG_EAspectRatio aspectRatio); OMX_ALG_EAspectRatio ConvertMediaToOMXAspectRatio(AspectRatioType aspectRatio); GopControlType ConvertOMXToMediaGopControl(OMX_ALG_EGopCtrlMode mode); OMX_ALG_EGopCtrlMode ConvertMediaToOMXGopControl(GopControlType mode); GdrType ConvertOMXToMediaGdr(OMX_ALG_EGdrMode gdr); OMX_ALG_EGdrMode ConvertMediaToOMXGdr(GdrType gdr); ScalingListType ConvertOMXToMediaScalingList(OMX_ALG_EScalingList scalingListMode); OMX_ALG_EScalingList ConvertMediaToOMXScalingList(ScalingListType scalingLisgt); BufferModeType ConvertOMXToMediaBufferMode(OMX_ALG_VIDEO_BUFFER_MODE mode); OMX_ALG_VIDEO_BUFFER_MODE ConvertMediaToOMXBufferMode(BufferModeType mode); QualityType ConvertOMXToMediaQualityPreset(OMX_ALG_ERoiQuality quality); int ConvertOMXToMediaQualityValue(OMX_S32 quality); OMX_U32 ConvertMediaToOMXInterlaceFlag(VideoModeType mode); VideoModeType ConvertOMXToMediaVideoMode(OMX_U32 flag); SequencePictureModeType ConvertOMXToMediaSequencePictureMode(OMX_ALG_SEQUENCE_PICTURE_MODE mode); OMX_ALG_SEQUENCE_PICTURE_MODE ConvertMediaToOMXSequencePictureMode(SequencePictureModeType mode); OMX_ALG_VIDEO_COLOR_PRIMARIESTYPE ConvertMediaToOMXColorPrimaries(ColorPrimariesType colorPrimaries); ColorPrimariesType ConvertOMXToMediaColorPrimaries(OMX_ALG_VIDEO_COLOR_PRIMARIESTYPE colorPrimaries); OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS ConvertMediaToOMXTransferCharacteristics(TransferCharacteristicsType transferCharac); TransferCharacteristicsType ConvertOMXToMediaTransferCharacteristics(OMX_ALG_VIDEO_TRANSFER_CHARACTERISTICS transferCharac); OMX_ALG_VIDEO_COLOR_MATRIX ConvertMediaToOMXColourMatrix(ColourMatrixType colourMatrix); ColourMatrixType ConvertOMXToMediaColourMatrix(OMX_ALG_VIDEO_COLOR_MATRIX colourMatrix); OMX_ALG_VIDEO_CONFIG_HIGH_DYNAMIC_RANGE_SEI ConvertMediaToOMXHDRSEI(HighDynamicRangeSeis const& hdrSEIs); HighDynamicRangeSeis ConvertOMXToMediaHDRSEI(OMX_ALG_VIDEO_CONFIG_HIGH_DYNAMIC_RANGE_SEI const& hdrSEIs); OMX_ALG_EQpTableMode ConvertMediaToOMXQpTable(QPTableType mode); QPTableType ConvertOMXToMediaQpTable(OMX_ALG_EQpTableMode mode); vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_expertise_avc.cpp000066400000000000000000000211361373706561700253470ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_expertise_avc.h" #include "omx_convert_omx_media.h" using namespace std; ExpertiseAVC::~ExpertiseAVC() = default; static OMX_ERRORTYPE SetMediaProfileLevel(OMX_VIDEO_AVCPROFILETYPE const& profile, OMX_VIDEO_AVCLEVELTYPE const& level, std::shared_ptr media) { ProfileLevel p; p.profile.avc = ConvertOMXToMediaAVCProfileLevel(profile, level).profile.avc; p.level = ConvertOMXToMediaAVCProfileLevel(profile, level).level; auto ret = media->Set(SETTINGS_INDEX_PROFILE_LEVEL, &p); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } static OMX_ERRORTYPE SetMediaGop(OMX_U32 bFrames, OMX_U32 pFrames, std::shared_ptr media) { Gop gop; auto ret = media->Get(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); if(ret == MediatypeInterface::BAD_INDEX) return OMX_ErrorUnsupportedIndex; gop.b = ConvertOMXToMediaBFrames(bFrames, pFrames); gop.length = ConvertOMXToMediaGopLength(bFrames, pFrames); ret = media->Set(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } static OMX_ERRORTYPE SetMediaEntropyCoding(OMX_BOOL entropyCoding, std::shared_ptr media) { EntropyCodingType e = ConvertOMXToMediaEntropyCoding(entropyCoding); auto ret = media->Set(SETTINGS_INDEX_ENTROPY_CODING, &e); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } static OMX_ERRORTYPE SetMediaConstrainedIntraPrediction(OMX_BOOL constrainedIntraPrediction, std::shared_ptr media) { bool b = ConvertOMXToMediaBool(constrainedIntraPrediction); auto ret = media->Set(SETTINGS_INDEX_CONSTRAINED_INTRA_PREDICTION, &b); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } static OMX_ERRORTYPE SetMediaLoopFilter(OMX_VIDEO_AVCLOOPFILTERTYPE const& loopFilter, std::shared_ptr media) { LoopFilterType l = ConvertOMXToMediaAVCLoopFilter(loopFilter); auto ret = media->Set(SETTINGS_INDEX_LOOP_FILTER, &l); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE ExpertiseAVC::GetProfileLevelSupported(OMX_PTR param, std::shared_ptr media) { vector supported; auto ret = media->Get(SETTINGS_INDEX_PROFILES_LEVELS_SUPPORTED, &supported); OMX_CHECK_MEDIA_GET(ret); auto& pl = *(OMX_VIDEO_PARAM_PROFILELEVELTYPE*)param; if(pl.nProfileIndex >= supported.size()) return OMX_ErrorNoMore; pl.eProfile = ConvertMediaToOMXAVCProfile(supported[pl.nProfileIndex]); pl.eLevel = ConvertMediaToOMXAVCLevel(supported[pl.nProfileIndex]); return OMX_ErrorNone; } OMX_ERRORTYPE ExpertiseAVC::GetProfileLevel(OMX_PTR param, Port const& port, std::shared_ptr media) { ProfileLevel profileLevel; auto ret = media->Get(SETTINGS_INDEX_PROFILE_LEVEL, &profileLevel); OMX_CHECK_MEDIA_GET(ret); auto& pl = *(OMX_VIDEO_PARAM_PROFILELEVELTYPE*)param; pl.nPortIndex = port.index; pl.eProfile = ConvertMediaToOMXAVCProfile(profileLevel); pl.eLevel = ConvertMediaToOMXAVCLevel(profileLevel); return OMX_ErrorNone; } OMX_ERRORTYPE ExpertiseAVC::SetProfileLevel(OMX_PTR param, Port const& port, std::shared_ptr media) { OMX_VIDEO_PARAM_PROFILELEVELTYPE rollback; GetProfileLevel(&rollback, port, media); auto pl = *(OMX_VIDEO_PARAM_PROFILELEVELTYPE*)param; auto profile = static_cast(pl.eProfile); auto level = static_cast(pl.eLevel); auto ret = SetMediaProfileLevel(profile, level, media); if(ret != OMX_ErrorNone) { SetProfileLevel(&rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ExpertiseAVC::GetExpertise(OMX_PTR param, Port const& port, std::shared_ptr media) { ProfileLevel profileLevel; Gop gop; EntropyCodingType entropyCoding; bool isConstrainedIntraPrediction; LoopFilterType loopFilter; auto ret = media->Get(SETTINGS_INDEX_PROFILE_LEVEL, &profileLevel); OMX_CHECK_MEDIA_GET(ret); bool bGop = (media->Get(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop) == MediatypeInterface::SUCCESS); bool bEntropyCoding = (media->Get(SETTINGS_INDEX_ENTROPY_CODING, &entropyCoding) == MediatypeInterface::SUCCESS); bool bIntraPred = (media->Get(SETTINGS_INDEX_CONSTRAINED_INTRA_PREDICTION, &isConstrainedIntraPrediction) == MediatypeInterface::SUCCESS); bool bLoopFilter = (media->Get(SETTINGS_INDEX_LOOP_FILTER, &loopFilter) == MediatypeInterface::SUCCESS); auto& avc = *(OMX_VIDEO_PARAM_AVCTYPE*)param; avc.nPortIndex = port.index; avc.nBFrames = bGop ? ConvertMediaToOMXBFrames(gop) : 0; avc.nPFrames = bGop ? ConvertMediaToOMXPFrames(gop) : 0; avc.bUseHadamard = OMX_TRUE; // XXX avc.nRefFrames = 1; // XXX avc.nRefIdx10ActiveMinus1 = 0; // XXX avc.nRefIdx11ActiveMinus1 = 0; // XXX avc.bEnableUEP = OMX_FALSE; // XXX avc.bEnableFMO = OMX_FALSE; // XXX avc.bEnableASO = OMX_FALSE; // XXX avc.bEnableRS = OMX_FALSE; // XXX avc.eProfile = ConvertMediaToOMXAVCProfile(profileLevel); avc.eLevel = ConvertMediaToOMXAVCLevel(profileLevel); avc.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB; // XXX avc.bFrameMBsOnly = OMX_TRUE; // XXX avc.bMBAFF = OMX_FALSE; // XXX avc.bEntropyCodingCABAC = bEntropyCoding ? ConvertMediaToOMXEntropyCoding(entropyCoding) : OMX_FALSE; avc.bWeightedPPrediction = OMX_FALSE; // XXX avc.nWeightedBipredicitonMode = OMX_FALSE; // XXX avc.bconstIpred = bIntraPred ? ConvertMediaToOMXBool(isConstrainedIntraPrediction) : OMX_FALSE; avc.bDirect8x8Inference = OMX_TRUE; // XXX avc.bDirectSpatialTemporal = OMX_TRUE; // XXX avc.nCabacInitIdc = 0; // XXX avc.eLoopFilterMode = bLoopFilter ? ConvertMediaToOMXAVCLoopFilter(loopFilter) : OMX_VIDEO_AVCLoopFilterMax; return OMX_ErrorNone; } OMX_ERRORTYPE ExpertiseAVC::SetExpertise(OMX_PTR param, Port const& port, std::shared_ptr media) { OMX_VIDEO_PARAM_AVCTYPE rollback; GetExpertise(&rollback, port, media); auto avc = *(OMX_VIDEO_PARAM_AVCTYPE*)param; auto ret = SetMediaProfileLevel(avc.eProfile, avc.eLevel, media); if(ret != OMX_ErrorNone) { SetExpertise(&rollback, port, media); throw ret; } // only encoder ret = SetMediaGop(avc.nBFrames, avc.nPFrames, media); if(ret == OMX_ErrorBadParameter) { SetExpertise(&rollback, port, media); throw ret; } ret = SetMediaEntropyCoding(avc.bEntropyCodingCABAC, media); if(ret == OMX_ErrorBadParameter) { SetExpertise(&rollback, port, media); throw ret; } ret = SetMediaConstrainedIntraPrediction(avc.bconstIpred, media); if(ret == OMX_ErrorBadParameter) { SetExpertise(&rollback, port, media); throw ret; } ret = SetMediaLoopFilter(avc.eLoopFilterMode, media); if(ret == OMX_ErrorBadParameter) { SetExpertise(&rollback, port, media); throw ret; } return OMX_ErrorNone; } vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_expertise_avc.h000066400000000000000000000050521373706561700250130ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include "omx_expertise_interface.h" struct ExpertiseAVC final : ExpertiseInterface { ~ExpertiseAVC() override; OMX_ERRORTYPE GetProfileLevelSupported(OMX_PTR param, std::shared_ptr media) override; OMX_ERRORTYPE GetProfileLevel(OMX_PTR param, Port const& port, std::shared_ptr media) override; OMX_ERRORTYPE SetProfileLevel(OMX_PTR param, Port const& port, std::shared_ptr media) override; OMX_ERRORTYPE GetExpertise(OMX_PTR param, Port const& port, std::shared_ptr media) override; OMX_ERRORTYPE SetExpertise(OMX_PTR param, Port const& port, std::shared_ptr media) override; }; vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_expertise_hevc.cpp000066400000000000000000000164471373706561700255340ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_expertise_hevc.h" #include "omx_convert_omx_media.h" using namespace std; ExpertiseHEVC::~ExpertiseHEVC() = default; static OMX_ERRORTYPE SetMediaProfileLevel(OMX_ALG_VIDEO_HEVCPROFILETYPE const& profile, OMX_ALG_VIDEO_HEVCLEVELTYPE const& level, std::shared_ptr media) { ProfileLevel p; p.profile.hevc = ConvertOMXToMediaHEVCProfileLevel(profile, level).profile.hevc; p.level = ConvertOMXToMediaHEVCProfileLevel(profile, level).level; auto ret = media->Set(SETTINGS_INDEX_PROFILE_LEVEL, &p); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } static OMX_ERRORTYPE SetMediaGop(OMX_U32 bFrames, OMX_U32 pFrames, std::shared_ptr media) { Gop gop; auto ret = media->Get(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); if(ret == MediatypeInterface::BAD_INDEX) return OMX_ErrorUnsupportedIndex; gop.b = ConvertOMXToMediaBFrames(bFrames, pFrames); gop.length = ConvertOMXToMediaGopLength(bFrames, pFrames); ret = media->Set(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } static OMX_ERRORTYPE SetMediaConstrainedIntraPrediction(OMX_BOOL constrainedIntraPrediction, std::shared_ptr media) { bool b = ConvertOMXToMediaBool(constrainedIntraPrediction); auto ret = media->Set(SETTINGS_INDEX_CONSTRAINED_INTRA_PREDICTION, &b); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } static OMX_ERRORTYPE SetMediaLoopFilter(OMX_ALG_VIDEO_HEVCLOOPFILTERTYPE const& loopFilter, std::shared_ptr media) { LoopFilterType l = ConvertOMXToMediaHEVCLoopFilter(loopFilter); auto ret = media->Set(SETTINGS_INDEX_LOOP_FILTER, &l); OMX_CHECK_MEDIA_SET(ret); return OMX_ErrorNone; } OMX_ERRORTYPE ExpertiseHEVC::GetProfileLevelSupported(OMX_PTR param, std::shared_ptr media) { vector supported; auto ret = media->Get(SETTINGS_INDEX_PROFILES_LEVELS_SUPPORTED, &supported); OMX_CHECK_MEDIA_GET(ret); auto& pl = *(OMX_VIDEO_PARAM_PROFILELEVELTYPE*)param; if(pl.nProfileIndex >= supported.size()) return OMX_ErrorNoMore; pl.eProfile = ConvertMediaToOMXHEVCProfile(supported[pl.nProfileIndex]); pl.eLevel = ConvertMediaToOMXHEVCLevel(supported[pl.nProfileIndex]); return OMX_ErrorNone; } OMX_ERRORTYPE ExpertiseHEVC::GetProfileLevel(OMX_PTR param, Port const& port, std::shared_ptr media) { ProfileLevel profileLevel; auto ret = media->Get(SETTINGS_INDEX_PROFILE_LEVEL, &profileLevel); OMX_CHECK_MEDIA_GET(ret); auto& pl = *(OMX_VIDEO_PARAM_PROFILELEVELTYPE*)param; pl.nPortIndex = port.index; pl.eProfile = ConvertMediaToOMXHEVCProfile(profileLevel); pl.eLevel = ConvertMediaToOMXHEVCLevel(profileLevel); return OMX_ErrorNone; } OMX_ERRORTYPE ExpertiseHEVC::SetProfileLevel(OMX_PTR param, Port const& port, std::shared_ptr media) { OMX_VIDEO_PARAM_PROFILELEVELTYPE rollback; GetProfileLevel(&rollback, port, media); auto pl = *(OMX_VIDEO_PARAM_PROFILELEVELTYPE*)param; auto profile = static_cast(pl.eProfile); auto level = static_cast(pl.eLevel); auto ret = SetMediaProfileLevel(profile, level, media); if(ret != OMX_ErrorNone) { SetProfileLevel(&rollback, port, media); throw ret; } return OMX_ErrorNone; } OMX_ERRORTYPE ExpertiseHEVC::GetExpertise(OMX_PTR param, Port const& port, std::shared_ptr media) { ProfileLevel profileLevel; Gop gop; bool isConstrainedIntraPrediction; LoopFilterType loopFilter; auto ret = media->Get(SETTINGS_INDEX_PROFILE_LEVEL, &profileLevel); OMX_CHECK_MEDIA_GET(ret); bool bGop = (media->Get(SETTINGS_INDEX_GROUP_OF_PICTURES, &gop) == MediatypeInterface::SUCCESS); bool bIntraPred = (media->Get(SETTINGS_INDEX_CONSTRAINED_INTRA_PREDICTION, &isConstrainedIntraPrediction) == MediatypeInterface::SUCCESS); bool bLoopFilter = (media->Get(SETTINGS_INDEX_LOOP_FILTER, &loopFilter) == MediatypeInterface::SUCCESS); auto& hevc = *(OMX_ALG_VIDEO_PARAM_HEVCTYPE*)param; hevc.nPortIndex = port.index; hevc.nBFrames = bGop ? ConvertMediaToOMXBFrames(gop) : 0; hevc.nPFrames = bGop ? ConvertMediaToOMXPFrames(gop) : 0; hevc.eProfile = ConvertMediaToOMXHEVCProfile(profileLevel); hevc.eLevel = ConvertMediaToOMXHEVCLevel(profileLevel); hevc.bConstIpred = bIntraPred ? ConvertMediaToOMXBool(isConstrainedIntraPrediction) : OMX_FALSE; hevc.eLoopFilterMode = bLoopFilter ? ConvertMediaToOMXHEVCLoopFilter(loopFilter) : OMX_ALG_VIDEO_HEVCLoopFilterMaxEnum; return OMX_ErrorNone; } OMX_ERRORTYPE ExpertiseHEVC::SetExpertise(OMX_PTR param, Port const& port, std::shared_ptr media) { OMX_ALG_VIDEO_PARAM_HEVCTYPE rollback; GetExpertise(&rollback, port, media); auto hevc = *(OMX_ALG_VIDEO_PARAM_HEVCTYPE*)param; auto ret = SetMediaProfileLevel(hevc.eProfile, hevc.eLevel, media); if(ret != OMX_ErrorNone) { SetExpertise(&rollback, port, media); throw ret; } // only encoder ret = SetMediaGop(hevc.nBFrames, hevc.nPFrames, media); if(ret == OMX_ErrorBadParameter) { SetExpertise(&rollback, port, media); throw ret; } ret = SetMediaConstrainedIntraPrediction(hevc.bConstIpred, media); if(ret == OMX_ErrorBadParameter) { SetExpertise(&rollback, port, media); throw ret; } ret = SetMediaLoopFilter(hevc.eLoopFilterMode, media); if(ret == OMX_ErrorBadParameter) { SetExpertise(&rollback, port, media); throw ret; } return OMX_ErrorNone; } vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_expertise_hevc.h000066400000000000000000000050541373706561700251710ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include "omx_expertise_interface.h" struct ExpertiseHEVC final : ExpertiseInterface { ~ExpertiseHEVC() override; OMX_ERRORTYPE GetProfileLevelSupported(OMX_PTR param, std::shared_ptr media) override; OMX_ERRORTYPE GetProfileLevel(OMX_PTR param, Port const& port, std::shared_ptr media) override; OMX_ERRORTYPE SetProfileLevel(OMX_PTR param, Port const& port, std::shared_ptr media) override; OMX_ERRORTYPE GetExpertise(OMX_PTR param, Port const& port, std::shared_ptr media) override; OMX_ERRORTYPE SetExpertise(OMX_PTR param, Port const& port, std::shared_ptr media) override; }; vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_expertise_interface.cpp000066400000000000000000000037011373706561700265340ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_expertise_interface.h" ExpertiseInterface::~ExpertiseInterface() = default; vcu-omx-il-xilinx-v2020.2/base/omx_component/omx_expertise_interface.h000066400000000000000000000060401373706561700262000ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include #include #include "module/mediatype_interface.h" #include "omx_component_structs.h" #define OMX_CHECK_MEDIA_GET(ret) \ if(ret == MediatypeInterface::BAD_INDEX) \ throw OMX_ErrorUnsupportedIndex; \ assert(ret == MediatypeInterface::SUCCESS); #define OMX_CHECK_MEDIA_SET(ret) \ if(ret == MediatypeInterface::BAD_INDEX) \ return OMX_ErrorUnsupportedIndex; \ if(ret == MediatypeInterface::BAD_PARAMETER) \ return OMX_ErrorBadParameter; \ assert(ret == MediatypeInterface::SUCCESS); struct ExpertiseInterface { virtual ~ExpertiseInterface() = 0; virtual OMX_ERRORTYPE GetProfileLevelSupported(OMX_PTR param, std::shared_ptr media) = 0; virtual OMX_ERRORTYPE GetProfileLevel(OMX_PTR param, Port const& port, std::shared_ptr media) = 0; virtual OMX_ERRORTYPE SetProfileLevel(OMX_PTR param, Port const& port, std::shared_ptr media) = 0; virtual OMX_ERRORTYPE GetExpertise(OMX_PTR param, Port const& port, std::shared_ptr media) = 0; virtual OMX_ERRORTYPE SetExpertise(OMX_PTR param, Port const& port, std::shared_ptr media) = 0; }; vcu-omx-il-xilinx-v2020.2/base/omx_component/project_codec.mk000066400000000000000000000011571373706561700242540ustar00rootroot00000000000000THIS.omx_component_codec:=$(call get-my-dir) OMX_COMPONENT_CODEC_SRCS+=\ $(THIS.omx_component_codec)/omx_component_interface.cpp\ $(THIS.omx_component_codec)/omx_component.cpp\ $(THIS.omx_component_codec)/omx_convert_omx_media.cpp\ $(THIS.omx_component_codec)/omx_buffer_handle.cpp\ $(THIS.omx_component_codec)/omx_component_getset.cpp\ $(THIS.omx_component_codec)/omx_expertise_interface.cpp\ $(THIS.omx_component_codec)/omx_expertise_avc.cpp\ $(THIS.omx_component_codec)/omx_expertise_hevc.cpp\ UNITTESTS+=$(shell find $(THIS.omx_component_codec)/unittests -name "*.cpp") UNITTESTS+=$(OMX_COMPONENT_CODEC_SRCS) vcu-omx-il-xilinx-v2020.2/base/omx_component/project_dec.mk000066400000000000000000000002361373706561700237270ustar00rootroot00000000000000THIS.omx_component_dec:=$(call get-my-dir) OMX_COMPONENT_DEC_SRCS+=\ $(THIS.omx_component_dec)/omx_component_dec.cpp\ UNITTESTS+=$(OMX_COMPONENT_DEC_SRCS) vcu-omx-il-xilinx-v2020.2/base/omx_component/project_enc.mk000066400000000000000000000002361373706561700237410ustar00rootroot00000000000000THIS.omx_component_enc:=$(call get-my-dir) OMX_COMPONENT_ENC_SRCS+=\ $(THIS.omx_component_enc)/omx_component_enc.cpp\ UNITTESTS+=$(OMX_COMPONENT_ENC_SRCS) vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/000077500000000000000000000000001373706561700205725ustar00rootroot00000000000000vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/omx_wrapper_codec_entry_point.cpp000066400000000000000000000252251373706561700274360ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "omx_wrapper_codec_entry_point.h" #include #include #include using namespace std; OMXComponentInterface* GetThis(OMX_IN OMX_HANDLETYPE hComponent) { if(!hComponent) return nullptr; return static_cast((((OMX_COMPONENTTYPE*)hComponent)->pComponentPrivate)); } OMX_ERRORTYPE SendCommand(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_COMMANDTYPE Cmd, OMX_IN OMX_U32 nParam1, OMX_IN OMX_PTR pCmdData) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", Cmd: " } +ToStringOMXCommand(Cmd) + string { ", nParam1: " } +to_string(nParam1) + string { ", pCmdData: " } +ToStringAddr(pCmdData)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->SendCommand(Cmd, nParam1, pCmdData); } OMX_ERRORTYPE GetState(OMX_IN OMX_HANDLETYPE hComponent, OMX_OUT OMX_STATETYPE* pState) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", pState: " } +ToStringAddr(pState)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->GetState(pState); } OMX_ERRORTYPE SetCallbacks(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_CALLBACKTYPE* pCallbacks, OMX_IN OMX_PTR pAppData) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", pCallbacks: " } +ToStringAddr(pCallbacks) + string { ", pAppData: " } +ToStringAddr(pAppData)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->SetCallbacks(pCallbacks, pAppData); } OMX_ERRORTYPE GetParameter(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nParamIndex, OMX_INOUT OMX_PTR pParam) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", nParamIndex: " } +ToStringOMXIndex(nParamIndex) + string { ", pParam: " } +ToStringAddr(pParam)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->GetParameter(nParamIndex, pParam); } OMX_ERRORTYPE SetParameter(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nParamIndex, OMX_IN OMX_PTR pParam) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", nParamIndex: " } +ToStringOMXIndex(nParamIndex) + string { ", pParam: " } +ToStringAddr(pParam)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->SetParameter(nParamIndex, pParam); } OMX_ERRORTYPE UseBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_OUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN OMX_U32 nSizeBytes, OMX_IN OMX_U8* pBuffer) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", ppBufferHdr: " } +ToStringAddr(ppBufferHdr) + string { ", nPortIndex: " } +to_string(nPortIndex) + string { ", pAppPrivate: " } +ToStringAddr(pAppPrivate) + string { ", nSizeBytes: " } +to_string(nSizeBytes) + string { ", pBuffer: " } +ToStringAddr(pBuffer)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->UseBuffer(ppBufferHdr, nPortIndex, pAppPrivate, nSizeBytes, pBuffer); } OMX_ERRORTYPE AllocateBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN OMX_U32 nSizeBytes) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", ppBufferHdr: " } +ToStringAddr(ppBufferHdr) + string { ", nPortIndex: " } +to_string(nPortIndex) + string { ", pAppPrivate: " } +ToStringAddr(pAppPrivate) + string { ", nSizeBytes: " } +to_string(nSizeBytes)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->AllocateBuffer(ppBufferHdr, nPortIndex, pAppPrivate, nSizeBytes); } OMX_ERRORTYPE FreeBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", nPortIndex: " } +to_string(nPortIndex) + string { ", pBufferHdr: " } +ToStringAddr(pBufferHdr)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->FreeBuffer(nPortIndex, pBufferHdr); } OMX_ERRORTYPE EmptyThisBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", pBufferHdr: " } +ToStringAddr(pBufferHdr)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->EmptyThisBuffer(pBufferHdr); } OMX_ERRORTYPE FillThisBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", pBufferHdr: " } +ToStringAddr(pBufferHdr)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->FillThisBuffer(pBufferHdr); } OMX_ERRORTYPE GetComponentVersion(OMX_IN OMX_HANDLETYPE hComponent, OMX_OUT OMX_STRING pComponentName, OMX_OUT OMX_VERSIONTYPE* pComponentVersion, OMX_OUT OMX_VERSIONTYPE* pSpecVersion, OMX_OUT OMX_UUIDTYPE pComponentUUID[128]) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", pComponentName: " } +ToStringAddr(pComponentName) + string { ", pComponentVersion: " } +ToStringAddr(pComponentVersion) + string { ", pSpecVersion: " } +ToStringAddr(pSpecVersion) + string { ", pComponentUUID: " } +ToStringAddr(pComponentUUID)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->GetComponentVersion(pComponentName, pComponentVersion, pSpecVersion); } OMX_ERRORTYPE GetConfig(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nConfigIndex, OMX_INOUT OMX_PTR pComponentConfigStructure) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", nConfigIndex: " } +ToStringOMXIndex(nConfigIndex) + string { ", pComponentConfigStructure: " } +ToStringAddr(pComponentConfigStructure)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->GetConfig(nConfigIndex, pComponentConfigStructure); } OMX_ERRORTYPE SetConfig(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nConfigIndex, OMX_IN OMX_PTR pComponentConfigStructure) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", nConfigIndex: " } +ToStringOMXIndex(nConfigIndex) + string { ", pComponentConfigStructure: " } +ToStringAddr(pComponentConfigStructure)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->SetConfig(nConfigIndex, pComponentConfigStructure); } OMX_ERRORTYPE GetExtensionIndex(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_STRING cParameterName, OMX_OUT OMX_INDEXTYPE* pIndexType) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", cParameterName: " } +cParameterName + string { ", pIndexType: " } +ToStringAddr(pIndexType)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->GetExtensionIndex(cParameterName, pIndexType); } OMX_ERRORTYPE ComponentTunnelRequest(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_U32 nPort, OMX_IN OMX_HANDLETYPE hTunneledComp, OMX_IN OMX_U32 nTunneledPort, OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", nPort: " } +to_string(nPort) + string { ", hTunneledComp: " } +ToStringAddr(hTunneledComp) + string { ", nTunneledPort: " } +to_string(nTunneledPort) + string { ", pTunnelSetup: " } +ToStringAddr(pTunnelSetup)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->ComponentTunnelRequest(nPort, hTunneledComp, nTunneledPort, pTunnelSetup); } OMX_ERRORTYPE UseEGLImage(OMX_IN OMX_HANDLETYPE hComponent, OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN void* eglImage) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", ppBufferHdr: " } +ToStringAddr(ppBufferHdr) + string { ", nPortIndex: " } +to_string(nPortIndex) + string { ", pAppPrivate: " } +ToStringAddr(pAppPrivate) + string { ", eglImage: " } +ToStringAddr(eglImage)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->UseEGLImage(ppBufferHdr, nPortIndex, pAppPrivate, eglImage); } OMX_ERRORTYPE ComponentRoleEnum(OMX_IN OMX_HANDLETYPE hComponent, OMX_OUT OMX_U8* cRole, OMX_IN OMX_U32 nIndex) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent) + string { ", cRole: " } +ToStringAddr(cRole) + string { ", nIndex: " } +to_string(nIndex)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; return pThis->ComponentRoleEnum(cRole, nIndex); } vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/omx_wrapper_codec_entry_point.h000066400000000000000000000106601373706561700271000ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include #include "base/omx_component/omx_component_interface.h" OMXComponentInterface* GetThis(OMX_IN OMX_HANDLETYPE hComponent); OMX_ERRORTYPE SendCommand(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_COMMANDTYPE Cmd, OMX_IN OMX_U32 nParam1, OMX_IN OMX_PTR pCmdData); OMX_ERRORTYPE GetState(OMX_IN OMX_HANDLETYPE hComponent, OMX_OUT OMX_STATETYPE* pState); OMX_ERRORTYPE SetCallbacks(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_CALLBACKTYPE* pCallbacks, OMX_IN OMX_PTR pAppData); OMX_ERRORTYPE GetParameter(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nParamIndex, OMX_INOUT OMX_PTR pParam); OMX_ERRORTYPE SetParameter(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nParamIndex, OMX_IN OMX_PTR pParam); OMX_ERRORTYPE UseBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_OUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN OMX_U32 nSizeBytes, OMX_IN OMX_U8* pBuffer); OMX_ERRORTYPE AllocateBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN OMX_U32 nSizeBytes); OMX_ERRORTYPE FreeBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr); OMX_ERRORTYPE EmptyThisBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr); OMX_ERRORTYPE FillThisBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE* pBufferHdr); OMX_ERRORTYPE GetComponentVersion(OMX_IN OMX_HANDLETYPE hComponent, OMX_OUT OMX_STRING pComponentName, OMX_OUT OMX_VERSIONTYPE* pComponentVersion, OMX_OUT OMX_VERSIONTYPE* pSpecVersion, OMX_OUT OMX_UUIDTYPE pComponentUUID[128]); OMX_ERRORTYPE GetConfig(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nConfigIndex, OMX_INOUT OMX_PTR pComponentConfigStructure); OMX_ERRORTYPE SetConfig(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nConfigIndex, OMX_IN OMX_PTR pComponentConfigStructure); OMX_ERRORTYPE GetExtensionIndex(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_STRING cParameterName, OMX_OUT OMX_INDEXTYPE* pIndexType); OMX_ERRORTYPE ComponentTunnelRequest(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_U32 nPort, OMX_IN OMX_HANDLETYPE hTunneledComp, OMX_IN OMX_U32 nTunneledPort, OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup); OMX_ERRORTYPE UseEGLImage(OMX_IN OMX_HANDLETYPE hComponent, OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_IN OMX_U32 nPortIndex, OMX_IN OMX_PTR pAppPrivate, OMX_IN void* eglImage); OMX_ERRORTYPE ComponentRoleEnum(OMX_IN OMX_HANDLETYPE hComponent, OMX_OUT OMX_U8* cRole, OMX_IN OMX_U32 nIndex); vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/omx_wrapper_dec.cpp000066400000000000000000000132471373706561700244630ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "base/omx_component/omx_component_dec.h" #include "base/omx_component/omx_expertise_hevc.h" #include "module/mediatype_dec_hevc.h" #include "module/module_dec.h" #include "module/device_dec_hardware_mcu.h" #include #include #include #include using namespace std; extern "C" { #include } static char const* ALLOC_DEVICE_DEC_NAME = "/dev/allegroDecodeIP"; static AL_TAllocator* createDmaAlloc(string deviceName) { auto alloc = AL_DmaAlloc_Create(deviceName.c_str()); if(alloc == nullptr) throw runtime_error { string { "Couldnt allocate dma allocator (tried using " } +deviceName + string { ")" } }; return alloc; } static BufferContiguities constexpr BUFFER_CONTIGUITIES_HARDWARE { false, true }; static BufferBytesAlignments constexpr BUFFER_BYTES_ALIGNMENTS_HARDWARE { 0, 32 }; static StrideAlignments constexpr STRIDE_ALIGNMENTS_HARDWARE { 64, 64 }; #include "base/omx_component/omx_expertise_avc.h" #include "module/mediatype_dec_avc.h" static DecComponent* GenerateAvcComponentHardware(OMX_HANDLETYPE hComponent, OMX_STRING cComponentName, OMX_STRING cRole) { shared_ptr media { new DecMediatypeAVC { BUFFER_CONTIGUITIES_HARDWARE, BUFFER_BYTES_ALIGNMENTS_HARDWARE, STRIDE_ALIGNMENTS_HARDWARE } }; shared_ptr device { new DecDeviceHardwareMcu {} }; shared_ptr allocator { createDmaAlloc(ALLOC_DEVICE_DEC_NAME), [](AL_TAllocator* allocator) { AL_Allocator_Destroy(allocator); } }; unique_ptr module { new DecModule { media, device, allocator } }; unique_ptr expertise { new ExpertiseAVC {} }; return new DecComponent { hComponent, media, move(module), cComponentName, cRole, move(expertise) }; } static DecComponent* GenerateHevcComponentHardware(OMX_HANDLETYPE hComponent, OMX_STRING cComponentName, OMX_STRING cRole) { shared_ptr media { new DecMediatypeHEVC { BUFFER_CONTIGUITIES_HARDWARE, BUFFER_BYTES_ALIGNMENTS_HARDWARE, STRIDE_ALIGNMENTS_HARDWARE } }; shared_ptr device { new DecDeviceHardwareMcu {} }; shared_ptr allocator { createDmaAlloc(ALLOC_DEVICE_DEC_NAME), [](AL_TAllocator* allocator) { AL_Allocator_Destroy(allocator); } }; unique_ptr module { new DecModule { media, device, allocator } }; unique_ptr expertise { new ExpertiseHEVC {} }; return new DecComponent { hComponent, media, move(module), cComponentName, cRole, move(expertise) }; } static OMX_PTR GenerateDefaultComponent(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_STRING cComponentName, OMX_IN OMX_STRING cRole) { if(!strncmp(cComponentName, "OMX.allegro.h265.hardware.decoder", strlen(cComponentName))) return GenerateHevcComponentHardware(hComponent, cComponentName, cRole); if(!strncmp(cComponentName, "OMX.allegro.h265.decoder", strlen(cComponentName))) return GenerateHevcComponentHardware(hComponent, cComponentName, cRole); if(!strncmp(cComponentName, "OMX.allegro.h264.hardware.decoder", strlen(cComponentName))) return GenerateAvcComponentHardware(hComponent, cComponentName, cRole); if(!strncmp(cComponentName, "OMX.allegro.h264.decoder", strlen(cComponentName))) return GenerateAvcComponentHardware(hComponent, cComponentName, cRole); return nullptr; } OMX_PTR CreateDecComponentPrivate(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_STRING cComponentName, OMX_IN OMX_STRING cRole) { return GenerateDefaultComponent(hComponent, cComponentName, cRole); } void DestroyDecComponentPrivate(OMX_IN OMX_PTR pComponentPrivate) { delete static_cast(pComponentPrivate); } vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/omx_wrapper_dec.h000066400000000000000000000040671373706561700241300ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once OMX_PTR CreateDecComponentPrivate(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_STRING cComponentName, OMX_IN OMX_STRING cRole); void DestroyDecComponentPrivate(OMX_IN OMX_PTR pComponentPrivate); vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/omx_wrapper_dec_entry_point.cpp000066400000000000000000000075441373706561700271200ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include #include "base/omx_component/omx_component_interface.h" #include "base/omx_checker/omx_checker.h" #include "omx_wrapper_codec_entry_point.cpp" #include "omx_wrapper_dec.h" #include #include #include using namespace std; static OMX_ERRORTYPE ComponentDeInit(OMX_IN OMX_HANDLETYPE hComponent) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; pThis->ComponentDeInit(); auto pComp = static_cast(hComponent); DestroyDecComponentPrivate(pComp->pComponentPrivate); return OMX_ErrorNone; } extern "C" { OMX_API OMX_ERRORTYPE CreateComponent(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_STRING cComponentName, OMX_IN OMX_STRING cRole, OMX_IN OMX_PTR pAppPrivate, OMX_IN OMX_CALLBACKTYPE* pCallbacks) { if(!hComponent) return OMX_ErrorBadParameter; OMX_PTR pThis = CreateDecComponentPrivate(hComponent, cComponentName, cRole); if(!pThis) return OMX_ErrorBadParameter; auto pComp = (OMX_COMPONENTTYPE*)hComponent; OMXChecker::SetHeaderVersion(*pComp); pComp->pComponentPrivate = pThis; pComp->pApplicationPrivate = pAppPrivate; pComp->SetCallbacks = SetCallbacks; pComp->SendCommand = SendCommand; pComp->GetParameter = GetParameter; pComp->SetParameter = SetParameter; pComp->GetState = GetState; pComp->UseBuffer = UseBuffer; pComp->AllocateBuffer = AllocateBuffer; pComp->FreeBuffer = FreeBuffer; pComp->EmptyThisBuffer = EmptyThisBuffer; pComp->FillThisBuffer = FillThisBuffer; pComp->ComponentDeInit = ComponentDeInit; pComp->GetComponentVersion = GetComponentVersion; pComp->GetConfig = GetConfig; pComp->SetConfig = SetConfig; pComp->GetExtensionIndex = GetExtensionIndex; pComp->ComponentTunnelRequest = ComponentTunnelRequest; pComp->UseEGLImage = UseEGLImage; pComp->ComponentRoleEnum = ComponentRoleEnum; return pComp->SetCallbacks(pComp, pCallbacks, pAppPrivate); } } vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/omx_wrapper_enc.cpp000066400000000000000000000155251373706561700244760ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include "module/mediatype_enc_hevc.h" #include "module/module_enc.h" #include "module/cpp_memory.h" #include "base/omx_component/omx_component_enc.h" #include "base/omx_component/omx_expertise_hevc.h" #if AL_ENABLE_DMA_COPY_ENC #include "module/dma_memory.h" #endif #include "module/device_enc_hardware_mcu.h" #include #include #include #include using namespace std; extern "C" { #include } static int constexpr HORIZONTAL_STRIDE_ALIGNMENTS = 64; static int constexpr VERCTICAL_STRIDE_ALIGNMENTS_HEVC = 32; static StrideAlignments constexpr STRIDE_ALIGNMENTS_HEVC { HORIZONTAL_STRIDE_ALIGNMENTS, VERCTICAL_STRIDE_ALIGNMENTS_HEVC }; static int constexpr VERCTICAL_STRIDE_ALIGNMENTS_AVC = 16; static StrideAlignments constexpr STRIDE_ALIGNMENTS_AVC { HORIZONTAL_STRIDE_ALIGNMENTS, VERCTICAL_STRIDE_ALIGNMENTS_AVC }; #if defined(ANDROID) || defined(__ANDROID_API__) static bool constexpr IS_SEPARATE_CONFIGURATION_FROM_DATA_ENABLED = true; #else static bool constexpr IS_SEPARATE_CONFIGURATION_FROM_DATA_ENABLED = false; #endif static MemoryInterface* createMemory() { #if AL_ENABLE_DMA_COPY_ENC char const* device = "/dev/dmaproxy"; return new DMAMemory { device }; #else return new CPPMemory {}; #endif } static char const* ALLOC_DEVICE_ENC_NAME = "/dev/allegroIP"; static AL_TAllocator* createDmaAlloc(string deviceName) { auto alloc = AL_DmaAlloc_Create(deviceName.c_str()); if(alloc == nullptr) throw runtime_error { string { "Couldnt allocate dma allocator (tried using " } +deviceName + string { ")" } }; return alloc; } static BufferContiguities constexpr BUFFER_CONTIGUITIES_HARDWARE { true, true }; static BufferBytesAlignments constexpr BUFFER_BYTES_ALIGNMENTS_HARDWARE { HORIZONTAL_STRIDE_ALIGNMENTS, HORIZONTAL_STRIDE_ALIGNMENTS }; #include "base/omx_component/omx_expertise_avc.h" #include "module/mediatype_enc_avc.h" static EncComponent* GenerateAvcComponentHardware(OMX_HANDLETYPE hComponent, OMX_STRING cComponentName, OMX_STRING cRole) { shared_ptr allocator { createDmaAlloc(ALLOC_DEVICE_ENC_NAME), [](AL_TAllocator* allocator) { AL_Allocator_Destroy(allocator); } }; shared_ptr media { new EncMediatypeAVC { BUFFER_CONTIGUITIES_HARDWARE, BUFFER_BYTES_ALIGNMENTS_HARDWARE, STRIDE_ALIGNMENTS_AVC, IS_SEPARATE_CONFIGURATION_FROM_DATA_ENABLED, allocator } }; shared_ptr device { new EncDeviceHardwareMcu { allocator } }; shared_ptr memory { createMemory() }; unique_ptr module { new EncModule { media, device, allocator, memory } }; unique_ptr expertise { new ExpertiseAVC {} }; return new EncComponent { hComponent, media, move(module), cComponentName, cRole, move(expertise) }; } static EncComponent* GenerateHevcComponentHardware(OMX_HANDLETYPE hComponent, OMX_STRING cComponentName, OMX_STRING cRole) { shared_ptr allocator { createDmaAlloc(ALLOC_DEVICE_ENC_NAME), [](AL_TAllocator* allocator) { AL_Allocator_Destroy(allocator); } }; shared_ptr media { new EncMediatypeHEVC { BUFFER_CONTIGUITIES_HARDWARE, BUFFER_BYTES_ALIGNMENTS_HARDWARE, STRIDE_ALIGNMENTS_HEVC, IS_SEPARATE_CONFIGURATION_FROM_DATA_ENABLED, allocator } }; shared_ptr device { new EncDeviceHardwareMcu { allocator } }; shared_ptr memory { createMemory() }; unique_ptr module { new EncModule { media, device, allocator, memory } }; unique_ptr expertise { new ExpertiseHEVC {} }; return new EncComponent { hComponent, media, move(module), cComponentName, cRole, move(expertise) }; } static OMX_PTR GenerateDefaultComponent(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_STRING cComponentName, OMX_IN OMX_STRING cRole) { if(!strncmp(cComponentName, "OMX.allegro.h265.hardware.encoder", strlen(cComponentName))) return GenerateHevcComponentHardware(hComponent, cComponentName, cRole); if(!strncmp(cComponentName, "OMX.allegro.h265.encoder", strlen(cComponentName))) return GenerateHevcComponentHardware(hComponent, cComponentName, cRole); if(!strncmp(cComponentName, "OMX.allegro.h264.hardware.encoder", strlen(cComponentName))) return GenerateAvcComponentHardware(hComponent, cComponentName, cRole); if(!strncmp(cComponentName, "OMX.allegro.h264.encoder", strlen(cComponentName))) return GenerateAvcComponentHardware(hComponent, cComponentName, cRole); return nullptr; } OMX_PTR CreateEncComponentPrivate(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_STRING cComponentName, OMX_IN OMX_STRING cRole) { return GenerateDefaultComponent(hComponent, cComponentName, cRole); } void DestroyEncComponentPrivate(OMX_IN OMX_PTR pComponentPrivate) { delete static_cast(pComponentPrivate); } vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/omx_wrapper_enc.h000066400000000000000000000040671373706561700241420ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once OMX_PTR CreateEncComponentPrivate(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_STRING cComponentName, OMX_IN OMX_STRING cRole); void DestroyEncComponentPrivate(OMX_IN OMX_PTR pComponentPrivate); vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/omx_wrapper_enc_entry_point.cpp000066400000000000000000000075441373706561700271320ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include #include "base/omx_component/omx_component_interface.h" #include "base/omx_checker/omx_checker.h" #include "omx_wrapper_codec_entry_point.cpp" #include "omx_wrapper_enc.h" #include #include #include using namespace std; static OMX_ERRORTYPE ComponentDeInit(OMX_IN OMX_HANDLETYPE hComponent) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent)); auto pThis = GetThis(hComponent); if(!pThis) return OMX_ErrorBadParameter; pThis->ComponentDeInit(); auto pComp = static_cast(hComponent); DestroyEncComponentPrivate(pComp->pComponentPrivate); return OMX_ErrorNone; } extern "C" { OMX_API OMX_ERRORTYPE CreateComponent(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_STRING cComponentName, OMX_IN OMX_STRING cRole, OMX_IN OMX_PTR pAppPrivate, OMX_IN OMX_CALLBACKTYPE* pCallbacks) { if(!hComponent) return OMX_ErrorBadParameter; OMX_PTR pThis = CreateEncComponentPrivate(hComponent, cComponentName, cRole); if(!pThis) return OMX_ErrorBadParameter; auto pComp = (OMX_COMPONENTTYPE*)hComponent; OMXChecker::SetHeaderVersion(*pComp); pComp->pComponentPrivate = pThis; pComp->pApplicationPrivate = pAppPrivate; pComp->SetCallbacks = SetCallbacks; pComp->SendCommand = SendCommand; pComp->GetParameter = GetParameter; pComp->SetParameter = SetParameter; pComp->GetState = GetState; pComp->UseBuffer = UseBuffer; pComp->AllocateBuffer = AllocateBuffer; pComp->FreeBuffer = FreeBuffer; pComp->EmptyThisBuffer = EmptyThisBuffer; pComp->FillThisBuffer = FillThisBuffer; pComp->ComponentDeInit = ComponentDeInit; pComp->GetComponentVersion = GetComponentVersion; pComp->GetConfig = GetConfig; pComp->SetConfig = SetConfig; pComp->GetExtensionIndex = GetExtensionIndex; pComp->ComponentTunnelRequest = ComponentTunnelRequest; pComp->UseEGLImage = UseEGLImage; pComp->ComponentRoleEnum = ComponentRoleEnum; return pComp->SetCallbacks(pComp, pCallbacks, pAppPrivate); } } vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/project_codec.mk000066400000000000000000000002031373706561700237210ustar00rootroot00000000000000THIS.omx_wrapper_codec:=$(call get-my-dir) OMX_WRAPPER_CODEC_SRCS+=\ $(THIS.omx_wrapper_codec)/omx_wrapper_codec_entry_point.cpp vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/project_dec.mk000066400000000000000000000002521373706561700234030ustar00rootroot00000000000000THIS.omx_wrapper_dec:=$(call get-my-dir) OMX_WRAPPER_DEC_SRCS+=\ $(THIS.omx_wrapper_dec)/omx_wrapper_dec.cpp\ $(THIS.omx_wrapper_dec)/omx_wrapper_dec_entry_point.cpp\ vcu-omx-il-xilinx-v2020.2/base/omx_wrapper/project_enc.mk000066400000000000000000000002531373706561700234160ustar00rootroot00000000000000THIS.omx_wrapper_enc:=$(call get-my-dir) OMX_WRAPPER_ENC_SRCS+=\ $(THIS.omx_wrapper_enc)/omx_wrapper_enc.cpp\ $(THIS.omx_wrapper_enc)/omx_wrapper_enc_entry_point.cpp\ vcu-omx-il-xilinx-v2020.2/builder.mk000066400000000000000000000021741373706561700173000ustar00rootroot00000000000000############################################################## #general rules ############################################################## .SUFFIXES: V?=0 ifeq ($(V),0) Q=@ else Q= endif LINK_COMPAT:= ifneq ($(findstring mingw,$(TARGET)),mingw) LINK_COMPAT+=-Wl,--hash-style=both endif $(BIN)/%.cpp.o: %.cpp @mkdir -p $(dir $@) $(Q)$(CXX) $(CFLAGS) $(INCLUDES) -std=c++11 -o $@ -c $< @$(CXX) -MM "$<" -MT "$@" -o "$(BIN)/$*_cpp.deps" $(INCLUDES) $(CFLAGS) -std=c++11 @echo "CXX $<" $(BIN)/%.c.o: %.c @mkdir -p $(dir $@) $(Q)$(CC) $(CFLAGS) $(INCLUDES) -std=gnu99 -o $@ -c $< @$(CC) -MM "$<" -MT "$@" -o "$(BIN)/$*_c.deps" $(INCLUDES) $(CFLAGS) @echo "CC $<" $(BIN)/%.a: @mkdir -p $(dir $@) $(Q)$(AR) cr $@ $^ @echo "AR $@" $(BIN)/%: @mkdir -p $(dir $@) $(Q)$(CXX) -o $@ $^ $(LINK_COMPAT) $(LDFLAGS) @echo "CXX $@" $(BIN)/%.so: $(Q)$(CXX) $(CFLAGS) -shared -Wl,-soname,$(notdir $@).$(MAJOR) -o "$@.$(VERSION)" $^ $(LDFLAGS) @echo "LD $@" @ln -fs "$(@:$(BIN)/%=%).$(VERSION)" $@.$(MAJOR) @ln -fs "$(@:$(BIN)/%=%).$(VERSION)" $@ # Dependency generation include $(shell test -d $(BIN) && find $(BIN) -name "*.deps") vcu-omx-il-xilinx-v2020.2/compile.sh000077500000000000000000000007651373706561700173140ustar00rootroot00000000000000readonly bin="$(pwd)/bin" readonly omx_headers="$(pwd)/omx_header" readonly external_srcs="$(pwd)/../allegro-vcu-ctrl-sw" readonly external_libs="$external_srcs/bin" readonly external_includes="$(pwd)/../allegro-vcu-ctrl-sw/include" readonly external_configs="$(pwd)/../allegro-vcu-ctrl-sw/include/config.h" BIN=$bin \ OMX_HEADERS=$omx_headers \ EXTERNAL_INCLUDE=$external_includes \ EXTERNAL_SRC=$external_srcs \ EXTERNAL_LIB=$external_libs \ EXTERNAL_CONFIG=$external_configs \ make -j`nproc` "$@" vcu-omx-il-xilinx-v2020.2/core/000077500000000000000000000000001373706561700162455ustar00rootroot00000000000000vcu-omx-il-xilinx-v2020.2/core/core_version.mk000066400000000000000000000001361373706561700212730ustar00rootroot00000000000000CORE_MAJOR=1 CORE_MINOR=1 CORE_STEP=2 CORE_VERSION=$(CORE_MAJOR).$(CORE_MINOR).$(CORE_STEP) vcu-omx-il-xilinx-v2020.2/core/omx_core.cpp000066400000000000000000000211631373706561700205670ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #include #include #include #include #include #include #include #include "omx_core.h" #include #include using namespace std; static int constexpr OMX_MAX_COMP_ROLES = 1; static int constexpr NB_OF_COMP = sizeof(AL_COMP_LIST) / sizeof(omx_comp_type); static omx_comp_type const* getComp(char* cComponentName) { if(!cComponentName) return nullptr; for(int i = 0; i < NB_OF_COMP; i++) { if(strncmp(cComponentName, AL_COMP_LIST[i].name, strlen(AL_COMP_LIST[i].name)) == 0) return &AL_COMP_LIST[i]; } return nullptr; } OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void) { LOG_IMPORTANT(); string env("/usr/lib"); if(getenv("OMX_ALLEGRO_PATH")) env = getenv("OMX_ALLEGRO_PATH"); string path = env + "/"; #if defined(ANDROID) || defined(__ANDROID_API__) path = "/system/lib/"; #endif /* ANDROID */ int libraryLoaded = 0; for(int i = 0; i < NB_OF_COMP; i++) { string cCodecName = path + AL_COMP_LIST[i].pSoLibName + "." + to_string(OMX_VERSION_MAJOR); AL_COMP_LIST[i].pLibHandle = ::dlopen(cCodecName.c_str(), RTLD_LAZY); if(AL_COMP_LIST[i].pLibHandle == nullptr) LOG_ERROR(dlerror()); else libraryLoaded++; } if(libraryLoaded == 0) { LOG_ERROR("No library found! Did you set OMX_ALLEGRO_PATH?"); return OMX_ErrorUndefined; } return OMX_ErrorNone; } OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void) { LOG_IMPORTANT(); for(int i = 0; i < NB_OF_COMP; i++) { if(AL_COMP_LIST[i].pLibHandle == nullptr) continue; if(::dlclose(AL_COMP_LIST[i].pLibHandle)) LOG_ERROR(dlerror()); } return OMX_ErrorNone; } OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(OMX_OUT OMX_STRING cComponentName, OMX_IN OMX_U32 nNameLength, OMX_IN OMX_U32 nIndex) { LOG_IMPORTANT(string { "cComponentName: " } +ToStringAddr(cComponentName) + string { ", nNameLength: " } +to_string(nNameLength) + string { ", nIndex: " } +to_string(nIndex)); if(!cComponentName) return OMX_ErrorBadParameter; if(nIndex >= NB_OF_COMP) return OMX_ErrorNoMore; strncpy(cComponentName, AL_COMP_LIST[nIndex].name, nNameLength); return OMX_ErrorNone; } using CreateComponentFuncPtr = add_pointer::type; static OMX_HANDLETYPE CreateComponent(const omx_comp_type* pComponent, char const* cFunctionName, OMX_PTR pAppData, OMX_CALLBACKTYPE* pCallBacks) { dlerror(); auto createFunction = (CreateComponentFuncPtr)dlsym(pComponent->pLibHandle, cFunctionName); auto pErr = dlerror(); if(pErr) { LOG_ERROR(pErr); return nullptr; } auto pMyComponent = new OMX_COMPONENTTYPE; auto eRet = createFunction(pMyComponent, (OMX_STRING)pComponent->name, (OMX_STRING)pComponent->role, pAppData, pCallBacks); if(eRet != OMX_ErrorNone) { delete pMyComponent; return nullptr; } return pMyComponent; } OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(OMX_OUT OMX_HANDLETYPE* pHandle, OMX_IN OMX_STRING cComponentName, OMX_IN OMX_PTR pAppData, OMX_IN OMX_CALLBACKTYPE* pCallBacks) { LOG_IMPORTANT(string { "pHandle: " } +ToStringAddr(pHandle) + string { ", cComponentName: " } +cComponentName + string { ", pAppData: " } +ToStringAddr(pAppData) + string { ", pCallBacks: " } +ToStringAddr(pCallBacks)); if(!pHandle) return OMX_ErrorBadParameter; auto pComponent = getComp(cComponentName); if(!pComponent) return OMX_ErrorComponentNotFound; try { *pHandle = CreateComponent(pComponent, "CreateComponent", pAppData, pCallBacks); } catch(runtime_error const& e) { LOG_ERROR(e.what()); return OMX_ErrorUndefined; } return *pHandle ? OMX_ErrorNone : OMX_ErrorUndefined; } OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComponent) { LOG_IMPORTANT(string { "hComponent: " } +ToStringAddr(hComponent)); auto pMyComponent = static_cast(hComponent); auto eRet = pMyComponent->ComponentDeInit(hComponent); delete pMyComponent; return eRet; } OMX_ERRORTYPE OMX_GetComponentsOfRole(OMX_IN OMX_STRING role, OMX_INOUT OMX_U32* pNumComps, OMX_INOUT OMX_U8** compNames) { LOG_IMPORTANT(string { "role: " } +role + string { ", pNumComps: " } +ToStringAddr(pNumComps) + string { ", compNames: " } +ToStringAddr(compNames)); if((!role) || (!pNumComps)) return OMX_ErrorBadParameter; if(!compNames) { *pNumComps = 0; for(int i = 0; i < NB_OF_COMP; i++) { if(strncmp(AL_COMP_LIST[i].role, role, strlen(role)) == 0) (*pNumComps)++; } return OMX_ErrorNone; } if(*pNumComps == 0) return OMX_ErrorBadParameter; int compNamesIndex = 0; for(int i = 0; i < NB_OF_COMP; i++) { if(strncmp(AL_COMP_LIST[i].role, role, strlen(role)) == 0) { strncpy((char*)compNames[compNamesIndex++], AL_COMP_LIST[i].name, OMX_MAX_STRINGNAME_SIZE); if(static_cast(compNamesIndex) >= *pNumComps) return OMX_ErrorNone; } } return OMX_ErrorNone; } OMX_ERRORTYPE OMX_GetRolesOfComponent(OMX_IN OMX_STRING compName, OMX_INOUT OMX_U32* pNumRoles, OMX_OUT OMX_U8** roles) { LOG_IMPORTANT(string { "compName: " } +compName + string { ", pNumRoles: " } +ToStringAddr(pNumRoles) + string { ", roles: " } +ToStringAddr(roles)); auto pComponent = getComp(compName); if(!pComponent) return OMX_ErrorComponentNotFound; if(!roles && !pNumRoles) return OMX_ErrorBadParameter; if(roles && !pNumRoles) return OMX_ErrorBadParameter; if(roles && pNumRoles && (*pNumRoles == 0)) return OMX_ErrorBadParameter; if(!roles && pNumRoles) { *pNumRoles = static_cast(OMX_MAX_COMP_ROLES); return OMX_ErrorNone; } auto minNumRoles = min(*pNumRoles, static_cast(OMX_MAX_COMP_ROLES)); *pNumRoles = minNumRoles; for(OMX_U32 i = 0; i < minNumRoles; i++) strncpy((char*)roles[i], (char*)pComponent->role, OMX_MAX_STRINGNAME_SIZE); return OMX_ErrorNone; } OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(OMX_IN OMX_HANDLETYPE hOutput, OMX_IN OMX_U32 nPortOutput, OMX_IN OMX_HANDLETYPE hInput, OMX_IN OMX_U32 nPortInput) { LOG_IMPORTANT(string { "hOutput: " } +ToStringAddr(hOutput) + string { ", nPortOutput: " } +to_string(nPortOutput) + string { ", hInput: " } +ToStringAddr(hInput) + string { ", nPortInput: " } +to_string(nPortInput)); auto pMyComponent = static_cast(hOutput); if(!pMyComponent) return OMX_ErrorInvalidComponent; return pMyComponent->ComponentTunnelRequest(hOutput, nPortOutput, hInput, nPortInput, nullptr); } OMX_ERRORTYPE OMX_GetContentPipe(OMX_OUT OMX_HANDLETYPE* hPipe, OMX_IN OMX_STRING szURI) { LOG_IMPORTANT(string { "hPipe: " } +ToStringAddr(hPipe) + string { ", szURI: " } +szURI); return OMX_ErrorNotImplemented; } vcu-omx-il-xilinx-v2020.2/core/omx_core.h000066400000000000000000000060661373706561700202410ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include typedef struct { char const name[OMX_MAX_STRINGNAME_SIZE]; void* pLibHandle; char const* pSoLibName; char const role[OMX_MAX_STRINGNAME_SIZE]; }omx_comp_type; static omx_comp_type AL_COMP_LIST[] = { { "OMX.allegro.h265.encoder", nullptr, "libOMX.allegro.video_encoder.so", "video_encoder.hevc", }, { "OMX.allegro.h265.hardware.encoder", nullptr, "libOMX.allegro.video_encoder.so", "video_encoder.hevc", }, { "OMX.allegro.h264.encoder", nullptr, "libOMX.allegro.video_encoder.so", "video_encoder.avc", }, { "OMX.allegro.h264.hardware.encoder", nullptr, "libOMX.allegro.video_encoder.so", "video_encoder.avc", }, { "OMX.allegro.h265.decoder", nullptr, "libOMX.allegro.video_decoder.so", "video_decoder.hevc", }, { "OMX.allegro.h265.hardware.decoder", nullptr, "libOMX.allegro.video_decoder.so", "video_decoder.hevc", }, { "OMX.allegro.h264.decoder", nullptr, "libOMX.allegro.video_decoder.so", "video_decoder.avc", }, { "OMX.allegro.h264.hardware.decoder", nullptr, "libOMX.allegro.video_decoder.so", "video_decoder.avc", }, }; vcu-omx-il-xilinx-v2020.2/core/project.mk000066400000000000000000000014651373706561700202520ustar00rootroot00000000000000THIS.core:=$(call get-my-dir) include $(THIS.core)/core_version.mk LIB_OMX_CORE_NAME:=libOMX.allegro.core.so LIB_OMX_CORE:=$(BIN)/$(LIB_OMX_CORE_NAME) OMX_CORE_SRCS:=\ $(THIS.core)/omx_core.cpp\ OMX_CORE_OBJ:=$(OMX_CORE_SRCS:%=$(BIN)/%.o) OMX_CORE_OBJ+=$(UTILITY_SRCS:%=$(BIN)/%.o) OMX_CORE_CFLAGS:=$(DEFAULT_CFLAGS) OMX_CORE_CFLAGS+=-fPIC OMX_CORE_CFLAGS+=-pthread OMX_CORE_LDFLAGS:=$(DEFAULT_LDFLAGS) OMX_CORE_LDFLAGS+=-ldl OMX_CORE_LDFLAGS+=-lpthread $(LIB_OMX_CORE): $(OMX_CORE_OBJ) $(LIB_OMX_CORE): CFLAGS:=$(OMX_CORE_CFLAGS) $(LIB_OMX_CORE): LDFLAGS:=$(OMX_CORE_LDFLAGS) $(LIB_OMX_CORE): MAJOR:=$(CORE_MAJOR) $(LIB_OMX_CORE): VERSION:=$(CORE_VERSION) core: $(LIB_OMX_CORE) .PHONY:core TARGETS+=core UNITTESTS+=$(OMX_CORE_SRCS) UNITTESTS+=$(shell find $(THIS.core)/unittests -name "*.cpp") vcu-omx-il-xilinx-v2020.2/decoder_version.mk000066400000000000000000000001261373706561700210170ustar00rootroot00000000000000DEC_MAJOR=1 DEC_MINOR=1 DEC_STEP=2 DEC_VERSION=$(DEC_MAJOR).$(DEC_MINOR).$(DEC_STEP) vcu-omx-il-xilinx-v2020.2/encoder_version.mk000066400000000000000000000001261373706561700210310ustar00rootroot00000000000000ENC_MAJOR=1 ENC_MINOR=1 ENC_STEP=2 ENC_VERSION=$(ENC_MAJOR).$(ENC_MINOR).$(ENC_STEP) vcu-omx-il-xilinx-v2020.2/exe_omx/000077500000000000000000000000001373706561700167615ustar00rootroot00000000000000vcu-omx-il-xilinx-v2020.2/exe_omx/common/000077500000000000000000000000001373706561700202515ustar00rootroot00000000000000vcu-omx-il-xilinx-v2020.2/exe_omx/common/CommandLineParser.h000066400000000000000000000256611373706561700237770ustar00rootroot00000000000000/****************************************************************************** * * Copyright (C) 2016-2020 Allegro DVT2. All rights reserved. * * 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 and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * 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 * XILINX OR ALLEGRO DVT2 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. * * Except as contained in this notice, the name of Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * * * Except as contained in this notice, the name of Allegro DVT2 shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Allegro DVT2. * ******************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include struct CommandLineParser { CommandLineParser() = default; explicit CommandLineParser(std::function onOptionParsed_) : onOptionParsed{onOptionParsed_} {}; struct Option { std::function parser; std::string desc; /* full formatted description with the name of the option */ std::string desc_; /* description provided by the user verbatim */ bool repeat = false; }; void parse(int argc, char* argv[]) { for(int i = 1; i < argc; ++i) words.push(argv[i]); while(!words.empty()) { auto const word = popWord(); if(isOption(word)) { auto i_func = options.find(word); if(i_func == options.end()) throw std::runtime_error("Unknown option: '" + word + "', use --help to get help"); i_func->second.parser(word); } else /* positional argument */ { if(positionals.empty()) throw std::runtime_error("Too many positional arguments. Can't interpret '" + word + "', use -h to get help"); auto& positional = positionals.front(); positional.parser(word); if(!positional.repeat) positionals.pop_front(); } } } void startSection(std::string const& sectionName) { curSection = sectionName; } void endSection(std::string const& sectionName) { if(curSection != sectionName) throw std::runtime_error("The section being ended isn't the current section."); /* Return to the default section */ curSection = ""; } template T readVal(std::string word) { bool hex = (word[0] == '0' && word[1] == 'x'); std::stringstream ss(hex ? word.substr(2) : word); ss.unsetf(std::ios::dec); ss.unsetf(std::ios::hex); if(hex) ss.setf(std::ios_base::hex, std::ios_base::basefield); T value; ss >> value; if(ss.fail() || ss.tellg() != std::streampos(-1)) throw std::runtime_error("Expected an integer, got '" + word + "'"); return value; } int readInt(std::string word) { return readVal(word); } uint32_t readUint(std::string word) { return readVal(word); } double readDouble(std::string word) { return readVal(word); } int popInt() { auto word = popWord(); return readInt(word); } uint32_t popUint() { auto word = popWord(); return readUint(word); } double popDouble() { auto word = popWord(); return readDouble(word); } std::string popWord() { if(words.empty()) throw std::runtime_error("Unexpected end of command line, use -h to get help"); auto word = words.front(); words.pop(); return word; } void addOption(std::string name, std::function func, std::string desc_, std::string const& type = "") { Option o; o.parser = func; o.desc_ = desc_; o.desc = makeDescription(name, type, desc_); insertOption(name, o); } template void setCustom_(std::string name, VariableType* value, Func customParser, std::string desc_, std::string const& type) { Option o; o.parser = [=](std::string word) { if(isOption(word)) *value = (VariableType)customParser(popWord()); else *value = customParser(word); }; o.desc_ = desc_; o.desc = makeDescription(name, type, desc_); insertOption(name, o); } template void addCustom(std::string name, VariableType* value, ParserRetType (* customParser)(std::string const &), std::string desc_, std::string const& type = "") { setCustom_(name, value, customParser, desc_, type); } // add an option with a user-provided value parsing function template void addCustom(std::string name, VariableType* value, std::function customParser, std::string desc_, std::string const& type = "") { setCustom_(name, value, customParser, desc_, type); } template void addFlag(std::string name, T* flag, std::string desc_, T value = (T) 1) { Option o; o.desc_ = desc_; o.desc = makeDescription(name, "", desc_); o.parser = [=](std::string word) { bool checkIsOption = isOption(word); assert(checkIsOption); * flag = value; }; insertOption(name, o); } template void addInt(std::string name, T* number, std::string desc_) { Option o; o.desc_ = desc_; o.desc = makeDescription(name, "number", desc_); o.parser = [=](std::string word) { if(isOption(word)) *number = popInt(); else *number = readInt(word); }; insertOption(name, o); } template void addUint(std::string name, T* number, std::string desc_) { Option o; o.desc_ = desc_; o.desc = makeDescription(name, "number", desc_); o.parser = [=](std::string word) { if(isOption(word)) *number = popUint(); else *number = readUint(word); }; insertOption(name, o); } template void addDouble(std::string name, T* number, std::string desc_) { Option o; o.desc_ = desc_; o.desc = makeDescription(name, "number", desc_); o.parser = [=](std::string word) { if(isOption(word)) *number = popDouble(); else *number = readDouble(word); }; insertOption(name, o); } void addString(std::string name, std::string* value, std::string desc_) { Option o; o.desc_ = desc_; o.desc = makeDescription(name, "string", desc_); o.parser = [=](std::string word) { if(isOption(word)) *value = popWord(); else *value = word; }; insertOption(name, o); } void addStringVector(std::string name, std::vector* vec, std::string desc_) { Option o; o.desc_ = desc_; o.desc = makeDescription(name, "string (+)", desc_); o.parser = [=](std::string word) { if(isOption(word)) vec->push_back(popWord()); else vec->push_back(word); }; o.repeat = true; insertOption(name, o); } std::map options; std::map descs; std::map sections; std::string curSection = ""; std::vector displayOrder; std::deque