diff options
author | CYBERDEViL | 2023-12-25 18:38:09 +0100 |
---|---|---|
committer | CYBERDEViL | 2023-12-25 18:38:09 +0100 |
commit | 4b4bd525ed40337fcd05872d641dc3e1c0bf95e2 (patch) | |
tree | d235a1b42053a521d0fcf89cef913d2e43f7177c | |
parent | 67d230f7ca8022b95126b550e47b2b9ea097ba06 (diff) | |
download | aur-4b4bd525ed40337fcd05872d641dc3e1c0bf95e2.tar.gz |
New source and patches.
The source of this package (`git.blender.org/blender.git#branch=blender2.7`)
does not exist anymore, Blender moved the repo to
`https://projects.blender.org/blender/blender.git`. There is no branch
`blender2.7` on this new repo, only a `v2.79b` tag which is a different source.
As the new source I choose the 2.79b source tarball from Blender. Patches to
keep Blender 2.79b up-to-date with modern compiler and libs where mostly
derived from Blender upstream commits/code.
-rw-r--r-- | .SRCINFO | 67 | ||||
-rw-r--r-- | 0000_misc.patch | 394 | ||||
-rw-r--r-- | 0001_openexr3.patch | 305 | ||||
-rw-r--r-- | 0002_opencollada1_6_68.patch | 91 | ||||
-rw-r--r-- | 0003_openvdb.patch | 112 | ||||
-rw-r--r-- | 0004_openimageio.patch | 375 | ||||
-rw-r--r-- | 0005_cycles.patch | 155 | ||||
-rw-r--r-- | 0006_python3_7.patch | 66 | ||||
-rw-r--r-- | 0007_python3_8.patch | 608 | ||||
-rw-r--r-- | 0008_python3_9.patch | 229 | ||||
-rw-r--r-- | 0009_python3_10.patch | 1124 | ||||
-rw-r--r-- | 0010_python3_11.patch | 122 | ||||
-rw-r--r-- | 0011_ffmpeg.patch | 4805 | ||||
-rw-r--r-- | PKGBUILD | 125 | ||||
-rw-r--r-- | SelectCudaComputeArch.patch | 4 | ||||
-rw-r--r-- | cycles.patch | 22 | ||||
-rw-r--r-- | opencolorio1.patch | 32 | ||||
-rw-r--r-- | openexr3.patch | 57 | ||||
-rw-r--r-- | openvdb7.patch | 29 | ||||
-rw-r--r-- | openvdb8.patch | 16 | ||||
-rw-r--r-- | python3.7.patch | 13 | ||||
-rw-r--r-- | python3.8.patch | 73 | ||||
-rw-r--r-- | python3.9.patch | 141 | ||||
-rw-r--r-- | python3.9_2.patch | 23 | ||||
-rw-r--r-- | stl_export_iter.patch | 13 |
25 files changed, 8497 insertions, 504 deletions
@@ -1,13 +1,13 @@ pkgbase = blender-2.7 - pkgdesc = Maintnance version of Blenders blender2.7 branch - pkgver = 2.79b.r71421.e045fe53f1b - pkgrel = 3 + pkgdesc = Keeping Blender 2.79b up-to-date with modern compiler and libs + pkgver = 2.79b + pkgrel = 4 url = https://blender.org/ arch = i686 arch = x86_64 license = GPL makedepends = ninja - makedepends = git + makedepends = cuda makedepends = cmake makedepends = boost makedepends = mesa @@ -30,39 +30,36 @@ pkgbase = blender-2.7 depends = openshadinglanguage depends = libtiff depends = libpng - optdepends = cuda: CUDA support in Cycles provides = blender-2.7 - source = git://git.blender.org/blender.git#branch=blender2.7 - source = blender-addons.git::git://git.blender.org/blender-addons.git - source = blender-addons-contrib.git::git://git.blender.org/blender-addons-contrib.git - source = blender-translations.git::git://git.blender.org/blender-translations.git - source = blender-dev-tools.git::git://git.blender.org/blender-dev-tools.git + source = https://download.blender.org/source/blender-2.79b.tar.gz source = SelectCudaComputeArch.patch - source = stl_export_iter.patch - source = python3.7.patch - source = python3.8.patch - source = python3.9.patch - source = python3.9_2.patch - source = openvdb7.patch - source = openvdb8.patch - source = cycles.patch - source = openexr3.patch source = opencolorio1.patch - sha256sums = SKIP - sha256sums = SKIP - sha256sums = SKIP - sha256sums = SKIP - sha256sums = SKIP - sha256sums = 28e407e3aefdd9bd76805b6033ada0b5b41dd6183bcf4f58a642c109f10c1876 - sha256sums = 649c21a12a1bfc0207078e1e58b4813a3e898c6dbbbb35d21e1de7c9e8f1985a - sha256sums = 47811284f080e38bcfbfb1f7346279245815a064df092989336b0bf3fe4530e9 - sha256sums = 229853b98bb62e1dec835aea6b2eab4c3dabbc8be591206573a3c1b85f10be59 - sha256sums = d106248d55045f5ef913bf6243ad74a76f6282264d9ee4c9b87ec4a3d2e2064b - sha256sums = b2a2bc5de8d3b730e49d1f50cb025c1dfdbcb66c58ead573322585b6a887d3a7 - sha256sums = c4079c4c142516d9cd476f5a3cafddf4068f0950c3c11ea4da9cf999c5ccc1f9 - sha256sums = edfd784f8497417660c0b9fdc97893fd0d77764d0bc10f4cb92a9082f41bae75 - sha256sums = d245f02d73bd5b767ffa49d369383d7cd6ae5e57b89c2975a78c1015e1884864 - sha256sums = e7d75a5ef5cb6452b45f6e1e80b6fe69e2630878b1f4f6d53bf0e36ced237712 - sha256sums = b3fa6ef21383287d0f8e7c3b848f3cf02186f9e3a0e8f194f3ca1323935e5e0e + source = 0000_misc.patch + source = 0001_openexr3.patch + source = 0002_opencollada1_6_68.patch + source = 0003_openvdb.patch + source = 0004_openimageio.patch + source = 0005_cycles.patch + source = 0006_python3_7.patch + source = 0007_python3_8.patch + source = 0008_python3_9.patch + source = 0009_python3_10.patch + source = 0010_python3_11.patch + source = 0011_ffmpeg.patch + sha512sums = 2db21ace446168dd683cdb5aad9dec001f8888ae4e9603a04ddb44fb78489ded827deb07e83712b0f1118a0e7bf66f2a5d935dc4ebb3a6703d72672ff414367f + sha512sums = 15b10bf91c759a8ab6519f3c02f54e7d3ad105eb915663e0de2a65b38d1e42b55cc383bae96a1507f1eb55200eb14ebe904b6a7b772b4073aa6a53ac5d4dd194 + sha512sums = 4126ddaaab2dc8c45cd850353a2e4a0e6ff2ef4476f9a533916e59fc57e426ca3110f7b3d38685fffd97b969208f941359122b693584c2a70a3f8420a832214b + sha512sums = d7b6f1707ad902743a3f08c6423aabd7abd0841eb78404419884d7c0b02affc1b6c3eafea55f9db04bce5e27d22cfd0ec63153c61a5fa2c3227de54a09f0895d + sha512sums = 0a8bd2ad7e199f95145bd0a66471686e0c545b071c73e6a659b570c001a860504f0970818fd686f52be9f5c18bd294c0efbede5c058ac96a4682e54b6235aac0 + sha512sums = 435e33926766a143cb6445a0c3219c9126b5d77e8114601a1f07848120b823ef2d1789bccb10079436b89eb9f894df54571ed50cde0713af857a8148be8f18ae + sha512sums = fc86d7a9a46e521ec22b2d87dfb023a71bfde624c4a6ddcf137038c7f46b97d614f8cb99951489a251cb2ea28460690cc0e5eb9ac6f2ccacc27c0052d137dcc9 + sha512sums = c8bd5ee00f062760ae3a2493750b2eb66d0368955ebb443aad5313f91c1fd0680df239eb1ca957e79cda482c084a023efc60e4341c198d55f897415cf79de35d + sha512sums = 3e3bef5e27279fc9c4f66398cd04a51a1ed268b7b99df2cf0151ed63994b742e39917e525ddac666d12a3df02a3ecef7dbe03da52c6be1aa143a3be960acbc5f + sha512sums = 7c98cf29fa22e7e816789254e43ed0f5595529f8ed37c88abac8667a80bf2bee9f020fa204a45800586e4d0c2de977df9ceda6d8bc0b77c806743f761b6ffa9f + sha512sums = 7effbd675b2167cc4c25a36d58f08824b2770e7b57fee93fd909a715003ee076ffcfc7e91cf965b9836da2fa54246fb68bbe613e44d312702298a5386b124dfa + sha512sums = a556445f27eaaba839d0efcfa70c530c269c7189e194c93b929044a54697f3606401dfdf5dbec05b181c26ba82d2b16560f2db7cd579104e0a0a322525cecaff + sha512sums = ecae55f642bf7f08edc56f8740a9fec650a3617f0ce7c7ba5b3211994ad8c46dc8fbbe897405699d46cb01c15129c0d4d9184657daeaf41172533195cdbbb104 + sha512sums = de254cb5e43fe05c3b5e70df881c1ab847b58c383d8df28be6d044c058d4776a5a3d57f710eb3cf0a83b43c95fac29f772c446a23e0f9c2bf73d1dcc8b23b67c + sha512sums = a0ff4f4dbc3624692c16d45f632cda1362173a5685c85e62d54af1d63d5a421867a5eb89b5b1c5b72bbceef98664d96b54901790470cbe67f701c582858af0ed pkgname = blender-2.7 diff --git a/0000_misc.patch b/0000_misc.patch new file mode 100644 index 000000000000..009368b3fbec --- /dev/null +++ b/0000_misc.patch @@ -0,0 +1,394 @@ +commit 1a734229a8ed6f35f953349bc9bc09cb37d2f5c8 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sun Dec 17 18:29:28 2023 +0100 + + Fix some compiler warnings (invalid header definitions) + +commit 5aa7fe5e858dbd5adfc6bf8fb31549050f9cacc1 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sun Dec 17 03:01:40 2023 +0100 + + "Cleanup: remove use of deprecated uint32, utin16 types" + + Fully applied Blender upstream ref: e12a8aedce52a05a635a4a70721a33352fe5de58 + +commit ebed5793e447501c1d6d60b643f6e6cd3a6ca0b0 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sun Dec 17 02:57:35 2023 +0100 + + misc: "Cleanup: pass arguments as const" + + Partially applied Blender upstream ref: 357acd1d5053b2ff9c8a09b9b6ad2e170c10b875 + +commit 6d64717fdb0e3d74af99ee824fe364619424cd0b +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sun Dec 17 01:03:16 2023 +0100 + + "Cleanup: compiler warnings, use const" + + Partially applied Blender upstream ref: e159ec8bc1871da8766b319fcda5c76eff1c0a48 + +commit e586b0156029339b3d651746ff27f818f4ab22d6 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Fri Dec 15 22:43:37 2023 +0100 + + inter: fix missing include (could not find std::cout) + + "error: ‘cout’ is not a member of ‘std’" + +commit 06a03f283d71a7eb6a1595476fb186638c6f1141 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Fri Dec 15 22:35:50 2023 +0100 + + intern: "Added extra "const" to satisfy the strict clang version in Xcode 9" + + Fully applied Blender upstream ref: ee30a4381f8989ed9f39b4baae9f74e45c9dcdc9 + +commit a7bfbf39c45757df1fc866418595e48f9d99c242 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Fri Dec 15 22:28:33 2023 +0100 + + intern: "Fix for GCC9 new OpenMP data sharing" + + Applied whole Blender upstream ref: d780409156e838e366f4da5126e6aeab44174d62 + +diff --git a/blender-2.79b/intern/elbeem/intern/solver_main.cpp b/blender-2.79b/intern/elbeem/intern/solver_main.cpp +index 68f7c04..514087b 100644 +--- a/blender-2.79b/intern/elbeem/intern/solver_main.cpp ++++ b/blender-2.79b/intern/elbeem/intern/solver_main.cpp +@@ -381,7 +381,7 @@ LbmFsgrSolver::mainLoop(const int lev) + GRID_REGION_INIT(); + #if PARALLEL==1 + const int gDebugLevel = ::gDebugLevel; +-#pragma omp parallel default(none) num_threads(mNumOMPThreads) \ ++#pragma omp parallel num_threads(mNumOMPThreads) \ + reduction(+: \ + calcCurrentMass,calcCurrentVolume, \ + calcCellsFilled,calcCellsEmptied, \ +@@ -1126,7 +1126,7 @@ LbmFsgrSolver::preinitGrids() + GRID_REGION_INIT(); + #if PARALLEL==1 + const int gDebugLevel = ::gDebugLevel; +-#pragma omp parallel default(none) num_threads(mNumOMPThreads) \ ++#pragma omp parallel num_threads(mNumOMPThreads) \ + reduction(+: \ + calcCurrentMass,calcCurrentVolume, \ + calcCellsFilled,calcCellsEmptied, \ +@@ -1164,7 +1164,7 @@ LbmFsgrSolver::standingFluidPreinit() + GRID_REGION_INIT(); + #if PARALLEL==1 + const int gDebugLevel = ::gDebugLevel; +-#pragma omp parallel default(none) num_threads(mNumOMPThreads) \ ++#pragma omp parallel num_threads(mNumOMPThreads) \ + reduction(+: \ + calcCurrentMass,calcCurrentVolume, \ + calcCellsFilled,calcCellsEmptied, \ +diff --git a/blender-2.79b/intern/itasc/kdl/tree.hpp b/blender-2.79b/intern/itasc/kdl/tree.hpp +index c8a253f..bd35f82 100644 +--- a/blender-2.79b/intern/itasc/kdl/tree.hpp ++++ b/blender-2.79b/intern/itasc/kdl/tree.hpp +@@ -34,7 +34,7 @@ namespace KDL + //Forward declaration + class TreeElement; + // Eigen allocator is needed for alignment of Eigen data types +- typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<std::string, TreeElement> > > SegmentMap; ++ typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<const std::string, TreeElement> > > SegmentMap; + + class TreeElement + { +diff --git a/blender-2.79b/intern/locale/boost_locale_wrapper.cpp b/blender-2.79b/intern/locale/boost_locale_wrapper.cpp +index 0707c0d..580c7a4 100644 +--- a/blender-2.79b/intern/locale/boost_locale_wrapper.cpp ++++ b/blender-2.79b/intern/locale/boost_locale_wrapper.cpp +@@ -27,6 +27,7 @@ + */ + + #include <stdio.h> ++#include <iostream> // std::cout + #include <boost/locale.hpp> + + #include "boost_locale_wrapper.h" +diff --git a/blender-2.79b/intern/mikktspace/mikktspace.c b/blender-2.79b/intern/mikktspace/mikktspace.c +index 99e945d..67f0c2b 100644 +--- a/blender-2.79b/intern/mikktspace/mikktspace.c ++++ b/blender-2.79b/intern/mikktspace/mikktspace.c +@@ -1193,7 +1193,7 @@ static tbool AssignRecur(const int piTriListIn[], STriInfo psTriInfos[], + + static tbool CompareSubGroups(const SSubGroup * pg1, const SSubGroup * pg2); + static void QuickSort(int* pSortBuffer, int iLeft, int iRight, unsigned int uSeed); +-static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], const SMikkTSpaceContext * pContext, const int iVertexRepresentitive); ++static STSpace EvalTspace(const int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], const SMikkTSpaceContext * pContext, const int iVertexRepresentitive); + + static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], const SGroup pGroups[], + const int iNrActiveGroups, const int piTriListIn[], const float fThresCos, +@@ -1364,7 +1364,7 @@ static tbool GenerateTSpaces(STSpace psTspace[], const STriInfo pTriInfos[], con + return TTRUE; + } + +-static STSpace EvalTspace(int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], ++static STSpace EvalTspace(const int face_indices[], const int iFaces, const int piTriListIn[], const STriInfo pTriInfos[], + const SMikkTSpaceContext * pContext, const int iVertexRepresentitive) + { + STSpace res; +diff --git a/blender-2.79b/source/blender/blenlib/BLI_math_geom.h b/blender-2.79b/source/blender/blenlib/BLI_math_geom.h +index 0fef849..7e06fff 100644 +--- a/blender-2.79b/source/blender/blenlib/BLI_math_geom.h ++++ b/blender-2.79b/source/blender/blenlib/BLI_math_geom.h +@@ -429,9 +429,9 @@ MINLINE void add_sh_shsh(float r[9], const float a[9], const float b[9]); + MINLINE float dot_shsh(const float a[9], const float b[9]); + + MINLINE float eval_shv3(float r[9], const float v[3]); +-MINLINE float diffuse_shv3(float r[9], const float v[3]); ++MINLINE float diffuse_shv3(const float r[9], const float v[3]); + MINLINE void vec_fac_to_sh(float r[9], const float v[3], const float f); +-MINLINE void madd_sh_shfl(float r[9], const float sh[3], const float f); ++MINLINE void madd_sh_shfl(float r[9], const float sh[9], const float f); + + /********************************* Form Factor *******************************/ + +diff --git a/blender-2.79b/source/blender/blenlib/BLI_math_vector.h b/blender-2.79b/source/blender/blenlib/BLI_math_vector.h +index 4fdb339..c5f286f 100644 +--- a/blender-2.79b/source/blender/blenlib/BLI_math_vector.h ++++ b/blender-2.79b/source/blender/blenlib/BLI_math_vector.h +@@ -120,16 +120,16 @@ MINLINE void mul_v2_v2(float r[2], const float a[2]); + MINLINE void mul_v3_v3(float r[3], const float a[3]); + MINLINE void mul_v3_v3v3(float r[3], const float a[3], const float b[3]); + MINLINE void mul_v4_fl(float r[4], float f); +-MINLINE void mul_v4_v4fl(float r[3], const float a[3], float f); ++MINLINE void mul_v4_v4fl(float r[4], const float a[3], float f); + MINLINE void mul_v2_v2_cw(float r[2], const float mat[2], const float vec[2]); + MINLINE void mul_v2_v2_ccw(float r[2], const float mat[2], const float vec[2]); + MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT; +-MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT; +-MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT; +-MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT; +-MINLINE float dot_m4_v3_row_x(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT; +-MINLINE float dot_m4_v3_row_y(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT; +-MINLINE float dot_m4_v3_row_z(float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT; ++MINLINE float dot_m3_v3_row_x(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT; ++MINLINE float dot_m3_v3_row_y(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT; ++MINLINE float dot_m3_v3_row_z(const float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT; ++MINLINE float dot_m4_v3_row_x(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT; ++MINLINE float dot_m4_v3_row_y(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT; ++MINLINE float dot_m4_v3_row_z(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT; + + MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f); + MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f); +@@ -145,7 +145,7 @@ MINLINE void negate_v2_v2(float r[2], const float a[2]); + MINLINE void negate_v3(float r[3]); + MINLINE void negate_v3_v3(float r[3], const float a[3]); + MINLINE void negate_v4(float r[4]); +-MINLINE void negate_v4_v4(float r[4], const float a[3]); ++MINLINE void negate_v4_v4(float r[4], const float a[4]); + + MINLINE void negate_v3_short(short r[3]); + MINLINE void negate_v3_db(double r[3]); +@@ -171,7 +171,7 @@ MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3]); + + MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3]); + +-MINLINE void star_m3_v3(float rmat[3][3], float a[3]); ++MINLINE void star_m3_v3(float rmat[3][3], const float a[3]); + + /*********************************** Length **********************************/ + +@@ -246,7 +246,7 @@ void flip_v2_v2v2(float v[2], const float v1[2], const float v2[2]); + + /********************************* Comparison ********************************/ + +-MINLINE bool is_zero_v2(const float a[3]) ATTR_WARN_UNUSED_RESULT; ++MINLINE bool is_zero_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT; + MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT; + MINLINE bool is_zero_v4(const float a[4]) ATTR_WARN_UNUSED_RESULT; + +diff --git a/blender-2.79b/source/blender/blenlib/intern/math_geom_inline.c b/blender-2.79b/source/blender/blenlib/intern/math_geom_inline.c +index 68a2e68..3b672e2 100644 +--- a/blender-2.79b/source/blender/blenlib/intern/math_geom_inline.c ++++ b/blender-2.79b/source/blender/blenlib/intern/math_geom_inline.c +@@ -99,7 +99,7 @@ MINLINE float dot_shsh(const float a[9], const float b[9]) + return r; + } + +-MINLINE float diffuse_shv3(float sh[9], const float v[3]) ++MINLINE float diffuse_shv3(const float sh[9], const float v[3]) + { + /* See formula (13) in: + * "An Efficient Representation for Irradiance Environment Maps" */ +diff --git a/blender-2.79b/source/blender/blenlib/intern/math_vector_inline.c b/blender-2.79b/source/blender/blenlib/intern/math_vector_inline.c +index ee5e865..3f8f2c5 100644 +--- a/blender-2.79b/source/blender/blenlib/intern/math_vector_inline.c ++++ b/blender-2.79b/source/blender/blenlib/intern/math_vector_inline.c +@@ -501,15 +501,15 @@ MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]) + /** + * Has the effect of #mul_m3_v3(), on a single axis. + */ +-MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]) ++MINLINE float dot_m3_v3_row_x(const float M[3][3], const float a[3]) + { + return M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2]; + } +-MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]) ++MINLINE float dot_m3_v3_row_y(const float M[3][3], const float a[3]) + { + return M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2]; + } +-MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) ++MINLINE float dot_m3_v3_row_z(const float M[3][3], const float a[3]) + { + return M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2]; + } +@@ -518,15 +518,15 @@ MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) + * Has the effect of #mul_mat3_m4_v3(), on a single axis. + * (no adding translation) + */ +-MINLINE float dot_m4_v3_row_x(float M[4][4], const float a[3]) ++MINLINE float dot_m4_v3_row_x(const float M[4][4], const float a[3]) + { + return M[0][0] * a[0] + M[1][0] * a[1] + M[2][0] * a[2]; + } +-MINLINE float dot_m4_v3_row_y(float M[4][4], const float a[3]) ++MINLINE float dot_m4_v3_row_y(const float M[4][4], const float a[3]) + { + return M[0][1] * a[0] + M[1][1] * a[1] + M[2][1] * a[2]; + } +-MINLINE float dot_m4_v3_row_z(float M[4][4], const float a[3]) ++MINLINE float dot_m4_v3_row_z(const float M[4][4], const float a[3]) + { + return M[0][2] * a[0] + M[1][2] * a[1] + M[2][2] * a[2]; + } +@@ -756,7 +756,7 @@ MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const f + n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]); + } + +-MINLINE void star_m3_v3(float rmat[3][3], float a[3]) ++MINLINE void star_m3_v3(float rmat[3][3], const float a[3]) + { + rmat[0][0] = rmat[1][1] = rmat[2][2] = 0.0; + rmat[0][1] = -a[2]; +diff --git a/blender-2.79b/source/blender/editors/transform/transform.h b/blender-2.79b/source/blender/editors/transform/transform.h +index d60eb2f..b2a308a 100644 +--- a/blender-2.79b/source/blender/editors/transform/transform.h ++++ b/blender-2.79b/source/blender/editors/transform/transform.h +@@ -120,12 +120,12 @@ typedef struct TransCon { + void (*drawExtra)(struct TransInfo *t); + /* For constraints that needs to draw differently from the other + * uses this instead of the generic draw function */ +- void (*applyVec)(struct TransInfo *t, struct TransData *td, const float in[3], float out[3], float pvec[3]); ++ void (*applyVec)(struct TransInfo *t, const struct TransData *td, const float in[3], float out[3], float pvec[3]); + /* Apply function pointer for linear vectorial transformation */ + /* The last three parameters are pointers to the in/out/printable vectors */ +- void (*applySize)(struct TransInfo *t, struct TransData *td, float smat[3][3]); ++ void (*applySize)(struct TransInfo *t, const struct TransData *td, float smat[3][3]); + /* Apply function pointer for size transformation */ +- void (*applyRot)(struct TransInfo *t, struct TransData *td, float vec[3], float *angle); ++ void (*applyRot)(struct TransInfo *t, const struct TransData *td, float vec[3], float *angle); + /* Apply function pointer for rotation transformation */ + } TransCon; + +diff --git a/blender-2.79b/source/blender/editors/transform/transform_constraints.c b/blender-2.79b/source/blender/editors/transform/transform_constraints.c +index 5621eed..a06e15f 100644 +--- a/blender-2.79b/source/blender/editors/transform/transform_constraints.c ++++ b/blender-2.79b/source/blender/editors/transform/transform_constraints.c +@@ -331,7 +331,7 @@ static void planeProjection(TransInfo *t, const float in[3], float out[3]) + * + */ + +-static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3]) ++static void applyAxisConstraintVec(TransInfo *t, const TransData *td, const float in[3], float out[3], float pvec[3]) + { + copy_v3_v3(out, in); + if (!td && t->con.mode & CON_APPLY) { +@@ -378,7 +378,7 @@ static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3 + * Further down, that vector is mapped to each data's space. + */ + +-static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3]) ++static void applyObjectConstraintVec(TransInfo *t, const TransData *td, const float in[3], float out[3], float pvec[3]) + { + copy_v3_v3(out, in); + if (t->con.mode & CON_APPLY) { +@@ -436,7 +436,7 @@ static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in + * Generic callback for constant spatial constraints applied to resize motion + */ + +-static void applyAxisConstraintSize(TransInfo *t, TransData *td, float smat[3][3]) ++static void applyAxisConstraintSize(TransInfo *t, const TransData *td, float smat[3][3]) + { + if (!td && t->con.mode & CON_APPLY) { + float tmat[3][3]; +@@ -460,7 +460,7 @@ static void applyAxisConstraintSize(TransInfo *t, TransData *td, float smat[3][3 + * Callback for object based spatial constraints applied to resize motion + */ + +-static void applyObjectConstraintSize(TransInfo *t, TransData *td, float smat[3][3]) ++static void applyObjectConstraintSize(TransInfo *t, const TransData *td, float smat[3][3]) + { + if (td && t->con.mode & CON_APPLY) { + float tmat[3][3]; +@@ -500,7 +500,7 @@ static void applyObjectConstraintSize(TransInfo *t, TransData *td, float smat[3] + * (ie: not doing counterclockwise rotations when the mouse moves clockwise). + */ + +-static void applyAxisConstraintRot(TransInfo *t, TransData *td, float vec[3], float *angle) ++static void applyAxisConstraintRot(TransInfo *t, const TransData *td, float vec[3], float *angle) + { + if (!td && t->con.mode & CON_APPLY) { + int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2); +@@ -542,7 +542,7 @@ static void applyAxisConstraintRot(TransInfo *t, TransData *td, float vec[3], fl + * (ie: not doing counterclockwise rotations when the mouse moves clockwise). + */ + +-static void applyObjectConstraintRot(TransInfo *t, TransData *td, float vec[3], float *angle) ++static void applyObjectConstraintRot(TransInfo *t, const TransData *td, float vec[3], float *angle) + { + if (t->con.mode & CON_APPLY) { + int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2); +diff --git a/blender-2.79b/source/blender/imbuf/intern/tiff.c b/blender-2.79b/source/blender/imbuf/intern/tiff.c +index afd28bb..110cbef 100644 +--- a/blender-2.79b/source/blender/imbuf/intern/tiff.c ++++ b/blender-2.79b/source/blender/imbuf/intern/tiff.c +@@ -351,7 +351,7 @@ static void scanline_separate_32bit(float *rectf, const float *fbuf, int scanlin + + static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image) + { +- uint16 unit; ++ uint16_t unit; + float xres; + float yres; + +@@ -535,7 +535,7 @@ ImBuf *imb_loadtiff(const unsigned char *mem, size_t size, int flags, char color + TIFF *image = NULL; + ImBuf *ibuf = NULL, *hbuf; + ImbTIFFMemFile memFile; +- uint32 width, height; ++ uint32_t width, height; + char *format = NULL; + int level; + short spp; +@@ -656,7 +656,7 @@ ImBuf *imb_loadtiff(const unsigned char *mem, size_t size, int flags, char color + void imb_loadtiletiff(ImBuf *ibuf, const unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect) + { + TIFF *image = NULL; +- uint32 width, height; ++ uint32_t width, height; + ImbTIFFMemFile memFile; + + image = imb_tiff_client_open(&memFile, mem, size); +@@ -710,7 +710,7 @@ void imb_loadtiletiff(ImBuf *ibuf, const unsigned char *mem, size_t size, int tx + int imb_savetiff(ImBuf *ibuf, const char *name, int flags) + { + TIFF *image = NULL; +- uint16 samplesperpixel, bitspersample; ++ uint16_t samplesperpixel, bitspersample; + size_t npixels; + unsigned char *pixels = NULL; + unsigned char *from = NULL, *to = NULL; +@@ -723,7 +723,7 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags) + /* check for a valid number of bytes per pixel. Like the PNG writer, + * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding + * to gray, RGB, RGBA respectively. */ +- samplesperpixel = (uint16)((ibuf->planes + 7) >> 3); ++ samplesperpixel = (uint16_t)((ibuf->planes + 7) >> 3); + if ((samplesperpixel > 4) || (samplesperpixel == 2)) { + fprintf(stderr, + "imb_savetiff: unsupported number of bytes per " diff --git a/0001_openexr3.patch b/0001_openexr3.patch new file mode 100644 index 000000000000..b8c868720154 --- /dev/null +++ b/0001_openexr3.patch @@ -0,0 +1,305 @@ +commit ade5af81ba7b039b42eff6efeb580b78bd54b6b3 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 02:23:16 2023 +0100 + + openexr: fix header include + + Thanks to this patch: https://aur.archlinux.org/cgit/aur.git/tree/openexr3.patch?h=blender-2.7 + +commit e00532824f88fbf8d6215df1509dd13ab33b8628 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Fri Dec 15 23:30:59 2023 +0100 + + openexr: "Images: update code to support OpenEXR 3" + + Adjusted Blender ref: cd7550cfe7 + +commit 7af9405f175999f38df80a421bde7166641183fd +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Fri Dec 15 22:23:21 2023 +0100 + + openexr: "Build: update CMake to support OpenEXR 3" + + Applied whole Blender upstream ref: 2c9931699e2080639bb836357e116b8e340335d9 + +diff --git a/blender-2.79b/build_files/cmake/Modules/FindOpenEXR.cmake b/blender-2.79b/build_files/cmake/Modules/FindOpenEXR.cmake +index 41e60a7..7e1fdbd 100644 +--- a/blender-2.79b/build_files/cmake/Modules/FindOpenEXR.cmake ++++ b/blender-2.79b/build_files/cmake/Modules/FindOpenEXR.cmake +@@ -37,14 +37,6 @@ ENDIF() + # Old versions (before 2.0?) do not have any version string, just assuming this should be fine though. + SET(_openexr_libs_ver_init "2.0") + +-SET(_openexr_FIND_COMPONENTS +- Half +- Iex +- IlmImf +- IlmThread +- Imath +-) +- + SET(_openexr_SEARCH_DIRS + ${OPENEXR_ROOT_DIR} + /usr/local +@@ -101,6 +93,24 @@ UNSET(_openexr_libs_ver_init) + + STRING(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _openexr_libs_ver ${OPENEXR_VERSION}) + ++# Different library names in 3.0, and Imath and Half moved out. ++IF(OPENEXR_VERSION VERSION_GREATER_EQUAL "3.0.0") ++ SET(_openexr_FIND_COMPONENTS ++ Iex ++ IlmThread ++ OpenEXR ++ OpenEXRCore ++ ) ++ELSE() ++ SET(_openexr_FIND_COMPONENTS ++ Half ++ Iex ++ IlmImf ++ IlmThread ++ Imath ++ ) ++ENDIF() ++ + SET(_openexr_LIBRARIES) + FOREACH(COMPONENT ${_openexr_FIND_COMPONENTS}) + STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT) +@@ -118,6 +128,57 @@ ENDFOREACH() + + UNSET(_openexr_libs_ver) + ++IF(OPENEXR_VERSION VERSION_GREATER_EQUAL "3.0.0") ++ # For OpenEXR 3.x, we also need to find the now separate Imath library. ++ # For simplicity we add it to the OpenEXR includes and libraries, as we ++ # have no direct dependency on Imath and it's simpler to support both ++ # 2.x and 3.x this way. ++ ++ # Find include directory ++ FIND_PATH(IMATH_INCLUDE_DIR ++ NAMES ++ Imath/ImathMath.h ++ HINTS ++ ${_openexr_SEARCH_DIRS} ++ PATH_SUFFIXES ++ include ++ ) ++ ++ # Find version ++ FIND_FILE(_imath_config ++ NAMES ++ ImathConfig.h ++ PATHS ++ ${IMATH_INCLUDE_DIR}/Imath ++ NO_DEFAULT_PATH ++ ) ++ ++ # Find line with version, extract string, and format for library suffix. ++ FILE(STRINGS "${_imath_config}" _imath_build_specification ++ REGEX "^[ \t]*#define[ \t]+IMATH_VERSION_STRING[ \t]+\"[.0-9]+\".*$") ++ STRING(REGEX REPLACE ".*#define[ \t]+IMATH_VERSION_STRING[ \t]+\"([.0-9]+)\".*" ++ "\\1" _imath_libs_ver ${_imath_build_specification}) ++ STRING(REGEX REPLACE "([0-9]+)[.]([0-9]+).*" "\\1_\\2" _imath_libs_ver ${_imath_libs_ver}) ++ ++ # Find library, with or without version number. ++ FIND_LIBRARY(IMATH_LIBRARY ++ NAMES ++ Imath-${_imath_libs_ver} Imath ++ NAMES_PER_DIR ++ HINTS ++ ${_openexr_SEARCH_DIRS} ++ PATH_SUFFIXES ++ lib64 lib ++ ) ++ LIST(APPEND _openexr_LIBRARIES "${IMATH_LIBRARY}") ++ ++ # In cmake version 3.21 and up, we can instead use the NO_CACHE option for ++ # FIND_FILE so we don't need to clear it from the cache here. ++ UNSET(_imath_config CACHE) ++ UNSET(_imath_libs_ver) ++ UNSET(_imath_build_specification) ++ENDIF() ++ + # handle the QUIETLY and REQUIRED arguments and set OPENEXR_FOUND to TRUE if + # all listed variables are TRUE + INCLUDE(FindPackageHandleStandardArgs) +@@ -126,13 +187,25 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenEXR DEFAULT_MSG + + IF(OPENEXR_FOUND) + SET(OPENEXR_LIBRARIES ${_openexr_LIBRARIES}) +- # Both include paths are needed because of dummy OSL headers mixing #include <OpenEXR/foo.h> and #include <foo.h> :( +- SET(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR}/OpenEXR) ++ # Both include paths are needed because of dummy OSL headers mixing ++ # #include <OpenEXR/foo.h> and #include <foo.h>, as well as Alembic ++ # include <half.h> directly. ++ SET(OPENEXR_INCLUDE_DIRS ++ ${OPENEXR_INCLUDE_DIR} ++ ${OPENEXR_INCLUDE_DIR}/OpenEXR) ++ ++ IF(OPENEXR_VERSION VERSION_GREATER_EQUAL "3.0.0") ++ LIST(APPEND OPENEXR_INCLUDE_DIRS ++ ${IMATH_INCLUDE_DIR} ++ ${IMATH_INCLUDE_DIR}/Imath) ++ ENDIF() + ENDIF() + + MARK_AS_ADVANCED( + OPENEXR_INCLUDE_DIR + OPENEXR_VERSION ++ IMATH_INCLUDE_DIR ++ IMATH_LIBRARY + ) + FOREACH(COMPONENT ${_openexr_FIND_COMPONENTS}) + STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT) +diff --git a/blender-2.79b/source/blender/alembic/intern/abc_transform.cc b/blender-2.79b/source/blender/alembic/intern/abc_transform.cc +index 5392387..9dc3200 100644 +--- a/blender-2.79b/source/blender/alembic/intern/abc_transform.cc ++++ b/blender-2.79b/source/blender/alembic/intern/abc_transform.cc +@@ -22,7 +22,7 @@ + + #include "abc_transform.h" + +-#include <OpenEXR/ImathBoxAlgo.h> ++#include <Imath/ImathBoxAlgo.h> + + #include "abc_util.h" + +diff --git a/blender-2.79b/source/blender/imbuf/intern/openexr/openexr_api.cpp b/blender-2.79b/source/blender/imbuf/intern/openexr/openexr_api.cpp +index 5ad42bd..94c2232 100644 +--- a/blender-2.79b/source/blender/imbuf/intern/openexr/openexr_api.cpp ++++ b/blender-2.79b/source/blender/imbuf/intern/openexr/openexr_api.cpp +@@ -40,30 +40,46 @@ + #include <algorithm> + #include <iostream> + +-#include <half.h> +-#include <Iex.h> +-#include <ImfVersion.h> +-#include <ImathBox.h> +-#include <ImfArray.h> +-#include <ImfIO.h> +-#include <ImfChannelList.h> +-#include <ImfPixelType.h> +-#include <ImfInputFile.h> +-#include <ImfOutputFile.h> +-#include <ImfCompression.h> +-#include <ImfCompressionAttribute.h> +-#include <ImfStringAttribute.h> +-#include <ImfStandardAttributes.h> ++/* The OpenEXR version can reliably be found in this header file from OpenEXR, ++ * for both 2.x and 3.x: ++ */ ++#include <OpenEXR/OpenEXRConfig.h> ++#define COMBINED_OPENEXR_VERSION \ ++ ((10000 * OPENEXR_VERSION_MAJOR) + (100 * OPENEXR_VERSION_MINOR) + OPENEXR_VERSION_PATCH) ++ ++#if COMBINED_OPENEXR_VERSION >= 20599 ++/* >=2.5.99 -> OpenEXR >=3.0 */ ++# include <Imath/half.h> ++# include <OpenEXR/ImfFrameBuffer.h> ++# define exr_file_offset_t uint64_t ++#else ++/* OpenEXR 2.x, use the old locations. */ ++# include <OpenEXR/half.h> ++# define exr_file_offset_t Int64 ++#endif ++ ++#include <OpenEXR/Iex.h> ++#include <OpenEXR/ImfArray.h> ++#include <OpenEXR/ImfChannelList.h> ++#include <OpenEXR/ImfCompression.h> ++#include <OpenEXR/ImfCompressionAttribute.h> ++#include <OpenEXR/ImfIO.h> ++#include <OpenEXR/ImfInputFile.h> ++#include <OpenEXR/ImfOutputFile.h> ++#include <OpenEXR/ImfPixelType.h> ++#include <OpenEXR/ImfStandardAttributes.h> ++#include <OpenEXR/ImfStringAttribute.h> ++#include <OpenEXR/ImfVersion.h> + + /* multiview/multipart */ +-#include <ImfMultiView.h> +-#include <ImfMultiPartInputFile.h> +-#include <ImfInputPart.h> +-#include <ImfOutputPart.h> +-#include <ImfMultiPartOutputFile.h> +-#include <ImfTiledOutputPart.h> +-#include <ImfPartType.h> +-#include <ImfPartHelper.h> ++#include <OpenEXR/ImfInputPart.h> ++#include <OpenEXR/ImfMultiPartInputFile.h> ++#include <OpenEXR/ImfMultiPartOutputFile.h> ++#include <OpenEXR/ImfMultiView.h> ++#include <OpenEXR/ImfOutputPart.h> ++#include <OpenEXR/ImfPartHelper.h> ++#include <OpenEXR/ImfPartType.h> ++#include <OpenEXR/ImfTiledOutputPart.h> + + #include "DNA_scene_types.h" /* For OpenEXR compression constants */ + +@@ -134,15 +150,15 @@ public: + } + + virtual bool read(char c[], int n); +- virtual Int64 tellg(); +- virtual void seekg(Int64 pos); ++ virtual exr_file_offset_t tellg(); ++ virtual void seekg(exr_file_offset_t pos); + virtual void clear(); + //virtual ~Mem_IStream() {}; // unused + + private: + +- Int64 _exrpos; +- Int64 _exrsize; ++ exr_file_offset_t _exrpos; ++ exr_file_offset_t _exrsize; + unsigned char *_exrbuf; + }; + +@@ -157,12 +173,12 @@ bool Mem_IStream::read(char c[], int n) + return false; + } + +-Int64 Mem_IStream::tellg() ++exr_file_offset_t Mem_IStream::tellg() + { + return _exrpos; + } + +-void Mem_IStream::seekg(Int64 pos) ++void Mem_IStream::seekg(exr_file_offset_t pos) + { + _exrpos = pos; + } +@@ -202,12 +218,12 @@ public: + return check_error(); + } + +- virtual Int64 tellg() ++ virtual exr_file_offset_t tellg() + { + return std::streamoff(ifs.tellg()); + } + +- virtual void seekg(Int64 pos) ++ virtual void seekg(exr_file_offset_t pos) + { + ifs.seekg(pos); + check_error(); +@@ -262,12 +278,12 @@ public: + check_error(); + } + +- virtual Int64 tellp() ++ virtual exr_file_offset_t tellp() + { + return std::streamoff(ofs.tellp()); + } + +- virtual void seekp(Int64 pos) ++ virtual void seekp(exr_file_offset_t pos) + { + ofs.seekp(pos); + check_error(); diff --git a/0002_opencollada1_6_68.patch b/0002_opencollada1_6_68.patch new file mode 100644 index 000000000000..93bdfbca9219 --- /dev/null +++ b/0002_opencollada1_6_68.patch @@ -0,0 +1,91 @@ +commit 7d92888cacde2d345fc2f4f6f69e9c78cb81db65 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 14:54:22 2023 +0100 + + opencollada: "Fix (devtalk 4053): Collada build with older cmake ver.." + + Fully applied Blender upstream ref: 3552731551ef1845b493ffebf78be5a42527e9f2 + +commit bd0befaf99b42881a72eb68257bb7b6632ef0ebe +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 14:50:12 2023 +0100 + + opencollada: "fix T58568 build errors when using collada 1.6.68 or n.." + + Fully applied Blender upstream ref: 10c50d7dbf7578b35b3bf19a1948f556f9eb203b + +diff --git a/blender-2.79b/source/blender/collada/CMakeLists.txt b/blender-2.79b/source/blender/collada/CMakeLists.txt +index 293049a..03ccf3b 100644 +--- a/blender-2.79b/source/blender/collada/CMakeLists.txt ++++ b/blender-2.79b/source/blender/collada/CMakeLists.txt +@@ -25,6 +25,21 @@ + + remove_strict_flags() + ++FIND_FILE(OPENCOLLADA_ANIMATION_CLIP ++ NAMES ++ COLLADAFWAnimationClip.h ++ PATHS ++ ${OPENCOLLADA_INCLUDE_DIRS} ++ NO_DEFAULT_PATH ++ ) ++ ++IF(OPENCOLLADA_ANIMATION_CLIP) ++ message(STATUS "Found opencollada: ${OPENCOLLADA_ANIMATION_CLIP} ") ++ add_definitions(-DWITH_OPENCOLLADA_ANIMATION_CLIP) ++ELSE() ++ message(STATUS "opencollada: Build without animation clip support") ++ENDIF() ++ + set(INC + . + ../blenkernel +diff --git a/blender-2.79b/source/blender/collada/DocumentImporter.cpp b/blender-2.79b/source/blender/collada/DocumentImporter.cpp +index 435eaa0..c55305a 100644 +--- a/blender-2.79b/source/blender/collada/DocumentImporter.cpp ++++ b/blender-2.79b/source/blender/collada/DocumentImporter.cpp +@@ -1340,6 +1340,19 @@ bool DocumentImporter::writeAnimationList(const COLLADAFW::AnimationList *animat + return anim_importer.write_animation_list(animationList); + } + ++#if WITH_OPENCOLLADA_ANIMATION_CLIP ++// Since opencollada 1.6.68 ++// called on post-process stage after writeVisualScenes ++bool DocumentImporter::writeAnimationClip(const COLLADAFW::AnimationClip *AnimationClip) ++{ ++ if (mImportStage != General) ++ return true; ++ ++ return true; ++ //return animation_clip_importer.write_animation_clip(animationClip); // TODO: implement import of AnimationClips ++} ++#endif ++ + /** When this method is called, the writer must write the skin controller data. + * \return The writer should return true, if writing succeeded, false otherwise.*/ + bool DocumentImporter::writeSkinControllerData(const COLLADAFW::SkinControllerData *skin) +diff --git a/blender-2.79b/source/blender/collada/DocumentImporter.h b/blender-2.79b/source/blender/collada/DocumentImporter.h +index 62f76db..5ad938f 100644 +--- a/blender-2.79b/source/blender/collada/DocumentImporter.h ++++ b/blender-2.79b/source/blender/collada/DocumentImporter.h +@@ -49,8 +49,6 @@ + #include "MeshImporter.h" + #include "ImportSettings.h" + +- +- + struct bContext; + + /** Importer class. */ +@@ -108,6 +106,11 @@ public: + + bool writeAnimationList(const COLLADAFW::AnimationList*); + ++#if WITH_OPENCOLLADA_ANIMATION_CLIP ++ // Please enable this when building with Collada 1.6.65 or newer (also in DocumentImporter.cpp) ++ bool DocumentImporter::writeAnimationClip(const COLLADAFW::AnimationClip *AnimationClip); ++#endif ++ + bool writeGeometry(const COLLADAFW::Geometry*); + + bool writeMaterial(const COLLADAFW::Material*); diff --git a/0003_openvdb.patch b/0003_openvdb.patch new file mode 100644 index 000000000000..8dd5b13215d8 --- /dev/null +++ b/0003_openvdb.patch @@ -0,0 +1,112 @@ +commit 5fbaf5a402b4e54b4cc9803c1da6ee01ffa939a4 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 15:13:10 2023 +0100 + + openvdb: compile with C++17 (openvdb 11) + +commit ffa4ddd68e586a7cce81a79e8fc95413268d73a7 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 15:09:21 2023 +0100 + + openvdb: "Cleanup: fix compiler warnings" + + Partially applied Blender upstream ref: 37889011070ff2ec52159690f652238d2b325185 + +commit 73a16ea250d7cd8b46fc16b824a54d238de66f0d +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 15:03:43 2023 +0100 + + openvdb: "Build: add WITH_OPENVDB_3_ABI_COMPATIBLE option." + + Fully applied Blender upstream ref: 71d7d6cd8c431b7f4fac8d65a4eaedf3cff6c8f6 + +diff --git a/blender-2.79b/CMakeLists.txt b/blender-2.79b/CMakeLists.txt +index bfea2dd..6ad2480 100644 +--- a/blender-2.79b/CMakeLists.txt ++++ b/blender-2.79b/CMakeLists.txt +@@ -98,6 +98,9 @@ cmake_policy(SET CMP0010 NEW) + # Input directories must have CMakeLists.txt + cmake_policy(SET CMP0014 NEW) + ++# Silence draco warning on macOS, new policy works fine. ++cmake_policy(SET CMP0068 NEW) ++ + #----------------------------------------------------------------------------- + # Load some macros. + include(build_files/cmake/macros.cmake) +@@ -251,6 +254,8 @@ option(WITH_OPENSUBDIV "Enable OpenSubdiv for surface subdivision" _init_OPEN + + option(WITH_OPENVDB "Enable features relying on OpenVDB" OFF) + option(WITH_OPENVDB_BLOSC "Enable blosc compression for OpenVDB, only enable if OpenVDB was built with blosc support" OFF) ++option(WITH_OPENVDB_3_ABI_COMPATIBLE "Assume OpenVDB library has been compiled with version 3 ABI compatibility" OFF) ++mark_as_advanced(WITH_OPENVDB_3_ABI_COMPATIBLE) + + # GHOST Windowing Library Options + option(WITH_GHOST_DEBUG "Enable debugging output for the GHOST library" OFF) +diff --git a/blender-2.79b/intern/opensubdiv/CMakeLists.txt b/blender-2.79b/intern/opensubdiv/CMakeLists.txt +index 876b5c0..bf23acf 100644 +--- a/blender-2.79b/intern/opensubdiv/CMakeLists.txt ++++ b/blender-2.79b/intern/opensubdiv/CMakeLists.txt +@@ -69,6 +69,7 @@ data_to_c_simple(gpu_shader_opensubdiv_geometry.glsl SRC) + data_to_c_simple(gpu_shader_opensubdiv_fragment.glsl SRC) + + add_definitions(-DGLEW_STATIC) ++add_definitions(-DOSD_USES_GLEW) + + if(WIN32) + add_definitions(-DNOMINMAX) +diff --git a/blender-2.79b/intern/openvdb/CMakeLists.txt b/blender-2.79b/intern/openvdb/CMakeLists.txt +index e0ecdb5..1695dc6 100644 +--- a/blender-2.79b/intern/openvdb/CMakeLists.txt ++++ b/blender-2.79b/intern/openvdb/CMakeLists.txt +@@ -23,6 +23,8 @@ + # + # ***** END GPL LICENSE BLOCK ***** + ++set(CMAKE_CXX_STANDARD 17) ++ + set(INC + . + intern +@@ -40,6 +42,12 @@ if(WITH_OPENVDB) + -DWITH_OPENVDB + ) + ++ if(WITH_OPENVDB_3_ABI_COMPATIBLE) ++ add_definitions( ++ -DOPENVDB_3_ABI_COMPATIBLE ++ ) ++ endif() ++ + list(APPEND INC_SYS + ${BOOST_INCLUDE_DIR} + ${TBB_INCLUDE_DIRS} +diff --git a/blender-2.79b/intern/openvdb/intern/openvdb_writer.cc b/blender-2.79b/intern/openvdb/intern/openvdb_writer.cc +index e886c5a..bedcfe6 100644 +--- a/blender-2.79b/intern/openvdb/intern/openvdb_writer.cc ++++ b/blender-2.79b/intern/openvdb/intern/openvdb_writer.cc +@@ -45,7 +45,7 @@ void OpenVDBWriter::insert(const openvdb::GridBase::Ptr &grid) + + void OpenVDBWriter::insert(const openvdb::GridBase &grid) + { +-#if (OPENVDB_LIBRARY_MAJOR_VERSION_NUMBER == 3) ++#if (OPENVDB_LIBRARY_MAJOR_VERSION_NUMBER <= 3) || defined(OPENVDB_3_ABI_COMPATIBLE) + m_grids->push_back(grid.copyGrid()); + #else + m_grids->push_back(grid.copyGridWithNewTree()); +diff --git a/blender-2.79b/intern/openvdb/openvdb_util.cc b/blender-2.79b/intern/openvdb/openvdb_util.cc +index d187f55..a09122d 100644 +--- a/blender-2.79b/intern/openvdb/openvdb_util.cc ++++ b/blender-2.79b/intern/openvdb/openvdb_util.cc +@@ -34,5 +34,10 @@ ScopeTimer::ScopeTimer(const std::string &message) + + ScopeTimer::~ScopeTimer() + { +- std::printf("%s: %fms\n", m_message.c_str(), m_timer.delta()); ++#if OPENVDB_LIBRARY_MAJOR_VERSION_NUMBER >= 7 ++ double delta = m_timer.milliseconds(); ++#else ++ double delta = m_timer.delta(); /* Deprecated in OpenVDB 7. */ ++#endif ++ std::printf("%s: %fms\n", m_message.c_str(), delta); + } diff --git a/0004_openimageio.patch b/0004_openimageio.patch new file mode 100644 index 000000000000..0a03919c2eef --- /dev/null +++ b/0004_openimageio.patch @@ -0,0 +1,375 @@ +commit 6389e1fbc4db6a9d9ee283c93806f8eb5aab26bb +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 16:07:53 2023 +0100 + + oiio: Build with C++14 + +commit 6b0a53306d8b6447288fc703bc6721835bf0a92e +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 15:51:05 2023 +0100 + + oiio: "Build: update CMake to support OpenImageIO 2.3.4" + + Fully applied Blender upstream ref: e5100ca3ad17b1b9a40ffd8a8edccb6cb553e558 + +commit f47f0eb459d739b693043f3980a180b5146fe341 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 15:41:55 2023 +0100 + + oiio: update on OIIO 2.0 compatibility + +commit 97947d9a336da23a984352cdb85cfea23d9a551a +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 15:39:06 2023 +0100 + + oiio: "Update code to be compatible with OIIO 2.0" + + Adjusted Blender upstream ref: 66d8bfb85c61aafe3bad2edf0e7b4d9d694ee2e7 + +diff --git a/blender-2.79b/build_files/cmake/Modules/FindOpenImageIO.cmake b/blender-2.79b/build_files/cmake/Modules/FindOpenImageIO.cmake +index e7527f1..39c296e 100644 +--- a/blender-2.79b/build_files/cmake/Modules/FindOpenImageIO.cmake ++++ b/blender-2.79b/build_files/cmake/Modules/FindOpenImageIO.cmake +@@ -56,6 +56,8 @@ FIND_LIBRARY(OPENIMAGEIO_LIBRARY + lib64 lib + ) + ++set(_openimageio_LIBRARIES ${OPENIMAGEIO_LIBRARY}) ++ + FIND_FILE(OPENIMAGEIO_IDIFF + NAMES + idiff +@@ -65,15 +67,49 @@ FIND_FILE(OPENIMAGEIO_IDIFF + bin + ) + ++# Additionally find util library if needed. In old versions this library was ++# included in libOpenImageIO and linking to both would duplicate symbols. In ++# new versions we need to link to both. ++FIND_FILE(_openimageio_export ++ NAMES ++ export.h ++ PATHS ++ ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO ++ NO_DEFAULT_PATH ++) ++ ++# Use existence of OIIO_UTIL_API to check if it's a separate lib. ++FILE(STRINGS "${_openimageio_export}" _openimageio_util_define ++ REGEX "^[ \t]*#[ \t]*define[ \t]+OIIO_UTIL_API.*$") ++ ++IF(_openimageio_util_define) ++ FIND_LIBRARY(OPENIMAGEIO_UTIL_LIBRARY ++ NAMES ++ OpenImageIO_Util ++ HINTS ++ ${_openimageio_SEARCH_DIRS} ++ PATH_SUFFIXES ++ lib64 lib ++ ) ++ ++ LIST(APPEND _openimageio_LIBRARIES ${OPENIMAGEIO_UTIL_LIBRARY}) ++ENDIF() ++ ++# In cmake version 3.21 and up, we can instead use the NO_CACHE option for ++# FIND_FILE so we don't need to clear it from the cache here. ++UNSET(_openimageio_export CACHE) ++UNSET(_openimageio_util_define) ++ + # handle the QUIETLY and REQUIRED arguments and set OPENIMAGEIO_FOUND to TRUE if + # all listed variables are TRUE + INCLUDE(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenImageIO DEFAULT_MSG +- OPENIMAGEIO_LIBRARY OPENIMAGEIO_INCLUDE_DIR) ++ _openimageio_LIBRARIES OPENIMAGEIO_INCLUDE_DIR) + + IF(OPENIMAGEIO_FOUND) +- SET(OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARY}) ++ SET(OPENIMAGEIO_LIBRARIES ${_openimageio_LIBRARIES}) + SET(OPENIMAGEIO_INCLUDE_DIRS ${OPENIMAGEIO_INCLUDE_DIR}) ++ SET(CMAKE_CXX_STANDARD 14) + IF(EXISTS ${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO/pugixml.hpp) + SET(OPENIMAGEIO_PUGIXML_FOUND TRUE) + ELSE() +@@ -86,7 +122,9 @@ ENDIF() + MARK_AS_ADVANCED( + OPENIMAGEIO_INCLUDE_DIR + OPENIMAGEIO_LIBRARY ++ OPENIMAGEIO_UTIL_LIBRARY + OPENIMAGEIO_IDIFF + ) + + UNSET(_openimageio_SEARCH_DIRS) ++UNSET(_openimageio_LIBRARIES) +diff --git a/blender-2.79b/intern/cycles/blender/blender_python.cpp b/blender-2.79b/intern/cycles/blender/blender_python.cpp +index 54973fd..bee6dd1 100644 +--- a/blender-2.79b/intern/cycles/blender/blender_python.cpp ++++ b/blender-2.79b/intern/cycles/blender/blender_python.cpp +@@ -493,7 +493,7 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) + socket_type = "NodeSocketString"; + data_type = BL::NodeSocket::type_STRING; + if(param->validdefault) +- default_string = param->sdefault[0]; ++ default_string = param->sdefault[0].string(); + } + else + continue; +diff --git a/blender-2.79b/intern/cycles/graph/node_xml.cpp b/blender-2.79b/intern/cycles/graph/node_xml.cpp +index d26b3b2..2a24104 100644 +--- a/blender-2.79b/intern/cycles/graph/node_xml.cpp ++++ b/blender-2.79b/intern/cycles/graph/node_xml.cpp +@@ -250,7 +250,7 @@ void xml_read_node(XMLReader& reader, Node *node, xml_node xml_node) + } + } + +- if(node->name) ++ if(!node->name.empty()) + reader.node_map[node->name] = node; + } + +diff --git a/blender-2.79b/intern/cycles/render/buffers.cpp b/blender-2.79b/intern/cycles/render/buffers.cpp +index cf402c3..6df6325 100644 +--- a/blender-2.79b/intern/cycles/render/buffers.cpp ++++ b/blender-2.79b/intern/cycles/render/buffers.cpp +@@ -27,6 +27,7 @@ + #include "util/util_opengl.h" + #include "util/util_time.h" + #include "util/util_types.h" ++#include "util/util_unique_ptr.h" + + CCL_NAMESPACE_BEGIN + +@@ -453,7 +454,7 @@ void DisplayBuffer::write(Device *device, const string& filename) + device->pixels_copy_from(rgba, 0, w, h); + + /* write image */ +- ImageOutput *out = ImageOutput::create(filename); ++ unique_ptr<ImageOutput> out(ImageOutput::create(filename)); + ImageSpec spec(w, h, 4, TypeDesc::UINT8); + int scanlinesize = w*4*sizeof(uchar); + +@@ -467,8 +468,6 @@ void DisplayBuffer::write(Device *device, const string& filename) + AutoStride); + + out->close(); +- +- delete out; + } + + device_memory& DisplayBuffer::rgba_data() +diff --git a/blender-2.79b/intern/cycles/render/image.cpp b/blender-2.79b/intern/cycles/render/image.cpp +index 595eb46..7829df9 100644 +--- a/blender-2.79b/intern/cycles/render/image.cpp ++++ b/blender-2.79b/intern/cycles/render/image.cpp +@@ -23,6 +23,7 @@ + #include "util/util_path.h" + #include "util/util_progress.h" + #include "util/util_texture.h" ++#include "util/util_unique_ptr.h" + + #ifdef WITH_OSL + #include <OSL/oslexec.h> +@@ -148,7 +149,7 @@ ImageDataType ImageManager::get_image_metadata(const string& filename, + return IMAGE_DATA_TYPE_BYTE4; + } + +- ImageInput *in = ImageInput::create(filename); ++ unique_ptr<ImageInput> in(ImageInput::create(filename)); + + if(in) { + ImageSpec spec; +@@ -194,7 +195,6 @@ ImageDataType ImageManager::get_image_metadata(const string& filename, + in->close(); + } + +- delete in; + } + + if(is_half) { +@@ -449,7 +449,7 @@ void ImageManager::tag_reload_image(const string& filename, + } + + bool ImageManager::file_load_image_generic(Image *img, +- ImageInput **in, ++ unique_ptr<ImageInput> *in, + int &width, + int &height, + int &depth, +@@ -465,7 +465,7 @@ bool ImageManager::file_load_image_generic(Image *img, + } + + /* load image from file through OIIO */ +- *in = ImageInput::create(img->filename); ++ *in = unique_ptr<ImageInput>(ImageInput::create(img->filename)); + + if(!*in) + return false; +@@ -477,8 +477,6 @@ bool ImageManager::file_load_image_generic(Image *img, + config.attribute("oiio:UnassociatedAlpha", 1); + + if(!(*in)->open(img->filename, spec, config)) { +- delete *in; +- *in = NULL; + return false; + } + +@@ -500,10 +498,7 @@ bool ImageManager::file_load_image_generic(Image *img, + if(!(components >= 1 && components <= 4)) { + if(*in) { + (*in)->close(); +- delete *in; +- *in = NULL; + } +- + return false; + } + +@@ -519,7 +514,7 @@ bool ImageManager::file_load_image(Image *img, + device_vector<DeviceType>& tex_img) + { + const StorageType alpha_one = (FileFormat == TypeDesc::UINT8)? 255 : 1; +- ImageInput *in = NULL; ++ unique_ptr<ImageInput> in = NULL; + int width, height, depth, components; + if(!file_load_image_generic(img, &in, width, height, depth, components)) { + return false; +@@ -575,7 +570,6 @@ bool ImageManager::file_load_image(Image *img, + } + cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4; + in->close(); +- delete in; + } + else { + if(FileFormat == TypeDesc::FLOAT) { +diff --git a/blender-2.79b/intern/cycles/render/image.h b/blender-2.79b/intern/cycles/render/image.h +index db7e28a..f4a14f4 100644 +--- a/blender-2.79b/intern/cycles/render/image.h ++++ b/blender-2.79b/intern/cycles/render/image.h +@@ -23,6 +23,7 @@ + #include "util/util_image.h" + #include "util/util_string.h" + #include "util/util_thread.h" ++#include "util/util_unique_ptr.h" + #include "util/util_vector.h" + + CCL_NAMESPACE_BEGIN +@@ -133,7 +134,7 @@ private: + bool pack_images; + + bool file_load_image_generic(Image *img, +- ImageInput **in, ++ unique_ptr<ImageInput> *in, + int &width, + int &height, + int &depth, +diff --git a/blender-2.79b/intern/cycles/util/util_unique_ptr.h b/blender-2.79b/intern/cycles/util/util_unique_ptr.h +new file mode 100644 +index 0000000..1ceae73 +--- /dev/null ++++ b/blender-2.79b/intern/cycles/util/util_unique_ptr.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright 2011-2013 Blender Foundation ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#ifndef __UTIL_UNIQUE_PTR_H__ ++#define __UTIL_UNIQUE_PTR_H__ ++ ++#include <memory> ++ ++CCL_NAMESPACE_BEGIN ++ ++using std::unique_ptr; ++ ++CCL_NAMESPACE_END ++ ++#endif /* __UTIL_UNIQUE_PTR_H__ */ +diff --git a/blender-2.79b/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/blender-2.79b/source/blender/imbuf/intern/oiio/openimageio_api.cpp +index b123d50..c31dc38 100644 +--- a/blender-2.79b/source/blender/imbuf/intern/oiio/openimageio_api.cpp ++++ b/blender-2.79b/source/blender/imbuf/intern/oiio/openimageio_api.cpp +@@ -35,6 +35,11 @@ + #include "utfconv.h" + #endif + ++// NOTE: Keep first, BLI_path_util conflicts with OIIO's format. ++#include <memory> ++#include <openimageio_api.h> ++#include <OpenImageIO/imageio.h> ++ + extern "C" + { + #include "MEM_guardedalloc.h" +@@ -48,12 +53,11 @@ extern "C" + #include "IMB_colormanagement_intern.h" + } + +-#include <openimageio_api.h> +-#include <OpenImageIO/imageio.h> + + OIIO_NAMESPACE_USING + + using std::string; ++using std::unique_ptr; + + typedef unsigned char uchar; + +@@ -197,7 +201,6 @@ int imb_save_photoshop(struct ImBuf *ibuf, const char * /*name*/, int flags) + + struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspace[IM_MAX_SPACE]) + { +- ImageInput *in = NULL; + struct ImBuf *ibuf = NULL; + int width, height, components; + bool is_float, is_alpha; +@@ -210,7 +213,7 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac + + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + +- in = ImageInput::create(filename); ++ unique_ptr<ImageInput> in(ImageInput::create(filename)); + if (!in) { + std::cerr << __func__ << ": ImageInput::create() failed:" << std::endl + << OIIO_NAMESPACE::geterror() << std::endl; +@@ -223,7 +226,6 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac + if (!in->open(filename, spec, config)) { + std::cerr << __func__ << ": ImageInput::open() failed:" << std::endl + << in->geterror() << std::endl; +- delete in; + return NULL; + } + +@@ -249,19 +251,17 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac + if (!(components >= 1 && components <= 4)) { + if (in) { + in->close(); +- delete in; + } + return NULL; + } + + if (is_float) +- ibuf = imb_oiio_load_image_float(in, width, height, components, flags, is_alpha); ++ ibuf = imb_oiio_load_image_float(in.get(), width, height, components, flags, is_alpha); + else +- ibuf = imb_oiio_load_image(in, width, height, components, flags, is_alpha); ++ ibuf = imb_oiio_load_image(in.get(), width, height, components, flags, is_alpha); + + if (in) { + in->close(); +- delete in; + } + + if (!ibuf) diff --git a/0005_cycles.patch b/0005_cycles.patch new file mode 100644 index 000000000000..483f1c4c42a2 --- /dev/null +++ b/0005_cycles.patch @@ -0,0 +1,155 @@ +commit c4818aa2fc716446ff3a109b18e63ff4ef79ff4c +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 17:21:32 2023 +0100 + + cycles: "Cycles: Cleanup, silence strict compiler warning" + + Partially applied Blender upstream ref: b763c34e80d3b20f9a7f0a592e479e5fa7ab295f + +commit c9f8cf23a076854f5dddae5f72a8182be2468118 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 17:07:44 2023 +0100 + + cycles: "Fix Cycles build error with OSL 1.12" + + Fully applied Blender upstream ref: 340529a8453ca9c2715c545245379e442f6006c8 + +commit e47121b7cbfdbde9c9eb39b5e1bcf1c54a5e3a29 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 17:05:53 2023 +0100 + + cycles: "Cycles: Fix bad register cast in sseb" + + Fully applied Blender upstream ref: be587d76efff6610f3b6d65cf42f1ee31ec3bdee + +diff --git a/blender-2.79b/intern/cycles/blender/blender_camera.cpp b/blender-2.79b/intern/cycles/blender/blender_camera.cpp +index b29711d..0c4a48f 100644 +--- a/blender-2.79b/intern/cycles/blender/blender_camera.cpp ++++ b/blender-2.79b/intern/cycles/blender/blender_camera.cpp +@@ -86,7 +86,7 @@ struct BlenderCamera { + static void blender_camera_init(BlenderCamera *bcam, + BL::RenderSettings& b_render) + { +- memset(bcam, 0, sizeof(BlenderCamera)); ++ memset((void *)bcam, 0, sizeof(BlenderCamera)); + + bcam->type = CAMERA_PERSPECTIVE; + bcam->zoom = 1.0f; +diff --git a/blender-2.79b/intern/cycles/blender/blender_util.h b/blender-2.79b/intern/cycles/blender/blender_util.h +index 363e19f..f697156 100644 +--- a/blender-2.79b/intern/cycles/blender/blender_util.h ++++ b/blender-2.79b/intern/cycles/blender/blender_util.h +@@ -251,7 +251,7 @@ static inline Transform get_transform(const BL::Array<float, 16>& array) + + /* we assume both types to be just 16 floats, and transpose because blender + * use column major matrix order while we use row major */ +- memcpy(&tfm, &array, sizeof(float)*16); ++ memcpy((void *)&tfm, &array, sizeof(float)*16); + tfm = transform_transpose(tfm); + + return tfm; +diff --git a/blender-2.79b/intern/cycles/bvh/bvh_params.h b/blender-2.79b/intern/cycles/bvh/bvh_params.h +index 7dd699b..75bf5ab 100644 +--- a/blender-2.79b/intern/cycles/bvh/bvh_params.h ++++ b/blender-2.79b/intern/cycles/bvh/bvh_params.h +@@ -156,7 +156,10 @@ public: + + BVHReference& operator=(const BVHReference &arg) { + if(&arg != this) { +- memcpy(this, &arg, sizeof(BVHReference)); ++ /* TODO(sergey): Check if it is still faster to memcpy() with ++ * modern compilers. ++ */ ++ memcpy((void *)this, &arg, sizeof(BVHReference)); + } + return *this; + } +diff --git a/blender-2.79b/intern/cycles/kernel/closure/alloc.h b/blender-2.79b/intern/cycles/kernel/closure/alloc.h +index e799855..ff1de14 100644 +--- a/blender-2.79b/intern/cycles/kernel/closure/alloc.h ++++ b/blender-2.79b/intern/cycles/kernel/closure/alloc.h +@@ -78,7 +78,7 @@ ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd, int size, float3 + if(!sc) + return NULL; + +- memcpy(sc, data, size); ++ memcpy((void *)sc, data, size); + + float sample_weight = fabsf(average(weight)); + sc->weight = weight; +diff --git a/blender-2.79b/intern/cycles/kernel/osl/osl_services.h b/blender-2.79b/intern/cycles/kernel/osl/osl_services.h +index ec34ca7..29055ea 100644 +--- a/blender-2.79b/intern/cycles/kernel/osl/osl_services.h ++++ b/blender-2.79b/intern/cycles/kernel/osl/osl_services.h +@@ -25,8 +25,9 @@ + * attributes. + */ + +-#include <OSL/oslexec.h> + #include <OSL/oslclosure.h> ++#include <OSL/oslexec.h> ++#include <OSL/rendererservices.h> + + #ifdef WITH_PTEX + class PtexCache; +diff --git a/blender-2.79b/intern/cycles/kernel/osl/osl_shader.cpp b/blender-2.79b/intern/cycles/kernel/osl/osl_shader.cpp +index 13b19d8..4ad6b74 100644 +--- a/blender-2.79b/intern/cycles/kernel/osl/osl_shader.cpp ++++ b/blender-2.79b/intern/cycles/kernel/osl/osl_shader.cpp +@@ -53,7 +53,7 @@ void OSLShader::thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OS + OSL::ShadingSystem *ss = kg->osl->ss; + OSLThreadData *tdata = new OSLThreadData(); + +- memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals)); ++ memset((void *)&tdata->globals, 0, sizeof(OSL::ShaderGlobals)); + tdata->globals.tracedata = &tdata->tracedata; + tdata->globals.flipHandedness = false; + tdata->osl_thread_info = ss->create_thread_info(); +diff --git a/blender-2.79b/intern/cycles/render/svm.cpp b/blender-2.79b/intern/cycles/render/svm.cpp +index 48287d8..0111d75 100644 +--- a/blender-2.79b/intern/cycles/render/svm.cpp ++++ b/blender-2.79b/intern/cycles/render/svm.cpp +@@ -721,7 +721,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty + } + + /* clear all compiler state */ +- memset(&active_stack, 0, sizeof(active_stack)); ++ memset((void *)&active_stack, 0, sizeof(active_stack)); + current_svm_nodes.clear(); + + foreach(ShaderNode *node_iter, graph->nodes) { +diff --git a/blender-2.79b/intern/cycles/util/util_sseb.h b/blender-2.79b/intern/cycles/util/util_sseb.h +index 6e66970..9ffe391 100644 +--- a/blender-2.79b/intern/cycles/util/util_sseb.h ++++ b/blender-2.79b/intern/cycles/util/util_sseb.h +@@ -116,7 +116,7 @@ __forceinline const sseb unpacklo( const sseb& a, const sseb& b ) { return _mm_u + __forceinline const sseb unpackhi( const sseb& a, const sseb& b ) { return _mm_unpackhi_ps(a, b); } + + template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const sseb shuffle( const sseb& a ) { +- return _mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0)); ++ return _mm_castsi128_ps(_mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0))); + } + + template<> __forceinline const sseb shuffle<0, 1, 0, 1>( const sseb& a ) { +diff --git a/blender-2.79b/intern/cycles/util/util_vector.h b/blender-2.79b/intern/cycles/util/util_vector.h +index 4add91a..caa6490 100644 +--- a/blender-2.79b/intern/cycles/util/util_vector.h ++++ b/blender-2.79b/intern/cycles/util/util_vector.h +@@ -131,7 +131,7 @@ public: + { + if(this != &from) { + resize(from.size()); +- memcpy(data_, from.data_, datasize_*sizeof(T)); ++ memcpy((void*)data_, from.data_, datasize_*sizeof(T)); + } + + return *this; +@@ -191,7 +191,7 @@ public: + return NULL; + } + else if(data_ != NULL) { +- memcpy(newdata, data_, ((datasize_ < newsize)? datasize_: newsize)*sizeof(T)); ++ memcpy((void *)newdata, data_, ((datasize_ < newsize)? datasize_: newsize)*sizeof(T)); + mem_free(data_, capacity_); + } + data_ = newdata; diff --git a/0006_python3_7.patch b/0006_python3_7.patch new file mode 100644 index 000000000000..f00e0d6611ae --- /dev/null +++ b/0006_python3_7.patch @@ -0,0 +1,66 @@ +commit 00f84e4cb1efc02149d9c04df79048c04351e46a +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sun Dec 17 01:13:47 2023 +0100 + + python3.7: "Cleanup: remove deprecated PyEval_InitThreads use" + + Fully applied Blender upstream ref: d377b1fe762c24ee74805ea8c1f666f121399698 + +commit a6323887a2db1acd10bd0fd1539fb8c061efc7f3 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 17:51:18 2023 +0100 + + python3.7: "Fix PyRNA class registration w/ Python 3.7" + + Fully applied Blender upstream ref: 1db47a2ccd1e68994bf8140eba6cc2a26a2bc91f + +diff --git a/blender-2.79b/source/blender/python/intern/bpy_interface.c b/blender-2.79b/source/blender/python/intern/bpy_interface.c +index 20cfd36..6077418 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_interface.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_interface.c +@@ -268,6 +268,7 @@ void BPY_python_start(int argc, const char **argv) + + Py_FrozenFlag = 1; + ++ /* Initialize Python (also acquires lock). */ + Py_Initialize(); + + // PySys_SetArgv(argc, argv); /* broken in py3, not a huge deal */ +@@ -284,9 +285,7 @@ void BPY_python_start(int argc, const char **argv) + PySys_SetObject("argv", py_argv); + Py_DECREF(py_argv); + } +- +- /* Initialize thread support (also acquires lock) */ +- PyEval_InitThreads(); ++ + #else + (void)argc; + (void)argv; +diff --git a/blender-2.79b/source/blender/python/intern/bpy_rna.c b/blender-2.79b/source/blender/python/intern/bpy_rna.c +index 0d3781c..832a872 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_rna.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_rna.c +@@ -7385,10 +7385,12 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v + if (!(flag & PROP_REGISTER)) + continue; + ++ /* TODO(campbell): Use Python3.7x _PyObject_LookupAttr(), also in the macro below. */ + identifier = RNA_property_identifier(prop); + item = PyObject_GetAttrString(py_class, identifier); + + if (item == NULL) { ++ PyErr_Clear(); + /* Sneaky workaround to use the class name as the bl_idname */ + + #define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \ +@@ -7404,6 +7406,9 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v + } \ + Py_DECREF(item); \ + } \ ++ else { \ ++ PyErr_Clear(); \ ++ } \ + } /* intentionally allow else here */ + + if (false) {} /* needed for macro */ diff --git a/0007_python3_8.patch b/0007_python3_8.patch new file mode 100644 index 000000000000..f71dd60f4321 --- /dev/null +++ b/0007_python3_8.patch @@ -0,0 +1,608 @@ +commit fce4c8799bcddb8a159d4c3cd1480cf174d02ee4 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 02:43:28 2023 +0100 + + python3.8: "Cleanup: define PY_SSIZE_T_CLEAN for Python" + + Fully applied Blender upstream ref: 9dd5e3b6e89ca0be4207e64439f292519eaf7e6e + +commit 89c9462c0a921b6af37043ee2ab147c60cd0f422 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 01:49:26 2023 +0100 + + python3.8: "PyAPI: use public API's for module & builtin access" + + Partially applied Blender upstream ref: e413b39a936181cc954dfbf054b0a19794d8902c + +commit 2b0312742399a9143f33a78a4f5ceedd08d178d6 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 00:53:34 2023 +0100 + + python3.8: "Cleanup: warnings building with Python 3.8" + + Adjusted Blender upstream ref: 36b6fb5cd600a7067d24cfe836c0af4d94e083e4 + +commit 2093b30818fcddf1f0d2d0011bae023d9124b351 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 00:23:26 2023 +0100 + + python3.8: "Cleanup: use PyImport_GetModuleDict" + + Adjusted Blender upstream ref: 44f719b63238503ef8f933f55383c6d4798995cc + +diff --git a/blender-2.79b/source/blender/python/bmesh/bmesh_py_api.c b/blender-2.79b/source/blender/python/bmesh/bmesh_py_api.c +index d5973ba..d7324ea 100644 +--- a/blender-2.79b/source/blender/python/bmesh/bmesh_py_api.c ++++ b/blender-2.79b/source/blender/python/bmesh/bmesh_py_api.c +@@ -196,7 +196,7 @@ PyObject *BPyInit_bmesh(void) + { + PyObject *mod; + PyObject *submodule; +- PyObject *sys_modules = PyThreadState_GET()->interp->modules; ++ PyObject *sys_modules = PyImport_GetModuleDict(); + + BPy_BM_init_types(); + BPy_BM_init_types_select(); +diff --git a/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops.c b/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops.c +index ee96c85..ea37159 100644 +--- a/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops.c ++++ b/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops.c +@@ -142,7 +142,7 @@ static PyTypeObject bmesh_op_Type = { + 0, /* tp_itemsize */ + /* methods */ + NULL, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ +@@ -260,7 +260,7 @@ static PyTypeObject bmesh_ops_fakemod_Type = { + 0, /* tp_itemsize */ + /* methods */ + NULL, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ +diff --git a/blender-2.79b/source/blender/python/generic/blf_py_api.c b/blender-2.79b/source/blender/python/generic/blf_py_api.c +index 69f1e29..bf8259f 100644 +--- a/blender-2.79b/source/blender/python/generic/blf_py_api.c ++++ b/blender-2.79b/source/blender/python/generic/blf_py_api.c +@@ -26,6 +26,9 @@ + * This file defines the 'bgl' module, used for drawing text in OpenGL. + */ + ++/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */ ++#define PY_SSIZE_T_CLEAN ++ + #include <Python.h> + #include "blf_py_api.h" + +@@ -150,7 +153,7 @@ PyDoc_STRVAR(py_blf_draw_doc, + static PyObject *py_blf_draw(PyObject *UNUSED(self), PyObject *args) + { + const char *text; +- int text_length; ++ Py_ssize_t text_length; + int fontid; + + if (!PyArg_ParseTuple(args, "is#:blf.draw", &fontid, &text, &text_length)) +diff --git a/blender-2.79b/source/blender/python/generic/idprop_py_api.c b/blender-2.79b/source/blender/python/generic/idprop_py_api.c +index 5d6a7c5..576f114 100644 +--- a/blender-2.79b/source/blender/python/generic/idprop_py_api.c ++++ b/blender-2.79b/source/blender/python/generic/idprop_py_api.c +@@ -1166,7 +1166,7 @@ PyTypeObject BPy_IDGroup_Type = { + /* Methods to implement standard operations */ + + NULL, /* destructor tp_dealloc; */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* cmpfunc tp_compare; */ +@@ -1560,7 +1560,7 @@ PyTypeObject BPy_IDArray_Type = { + /* Methods to implement standard operations */ + + NULL, /* destructor tp_dealloc; */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* cmpfunc tp_compare; */ +@@ -1675,7 +1675,7 @@ PyTypeObject BPy_IDGroup_Iter_Type = { + /* Methods to implement standard operations */ + + NULL, /* destructor tp_dealloc; */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* cmpfunc tp_compare; */ +@@ -1792,7 +1792,7 @@ PyObject *BPyInit_idprop(void) + { + PyObject *mod; + PyObject *submodule; +- PyObject *sys_modules = PyThreadState_GET()->interp->modules; ++ PyObject *sys_modules = PyImport_GetModuleDict(); + + mod = PyModule_Create(&IDProp_module_def); + +diff --git a/blender-2.79b/source/blender/python/generic/py_capi_utils.c b/blender-2.79b/source/blender/python/generic/py_capi_utils.c +index 861e2db..f4a2595 100644 +--- a/blender-2.79b/source/blender/python/generic/py_capi_utils.c ++++ b/blender-2.79b/source/blender/python/generic/py_capi_utils.c +@@ -29,6 +29,9 @@ + * BLI_string_utf8() for unicode conversion. + */ + ++/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */ ++#define PY_SSIZE_T_CLEAN ++ + #include <Python.h> + #include <frameobject.h> + +@@ -638,9 +641,10 @@ PyObject *PyC_UnicodeFromByte(const char *str) + ****************************************************************************/ + PyObject *PyC_DefaultNameSpace(const char *filename) + { +- PyInterpreterState *interp = PyThreadState_GET()->interp; ++ PyObject *modules = PyImport_GetModuleDict(); ++ PyObject *builtins = PyEval_GetBuiltins(); + PyObject *mod_main = PyModule_New("__main__"); +- PyDict_SetItemString(interp->modules, "__main__", mod_main); ++ PyDict_SetItemString(modules, "__main__", mod_main); + Py_DECREF(mod_main); /* sys.modules owns now */ + PyModule_AddStringConstant(mod_main, "__name__", "__main__"); + if (filename) { +@@ -648,23 +652,23 @@ PyObject *PyC_DefaultNameSpace(const char *filename) + * note: this wont map to a real file when executing text-blocks and buttons. */ + PyModule_AddObject(mod_main, "__file__", PyC_UnicodeFromByte(filename)); + } +- PyModule_AddObject(mod_main, "__builtins__", interp->builtins); +- Py_INCREF(interp->builtins); /* AddObject steals a reference */ ++ PyModule_AddObject(mod_main, "__builtins__", builtins); ++ Py_INCREF(builtins); /* AddObject steals a reference */ + return PyModule_GetDict(mod_main); + } + + /* restore MUST be called after this */ + void PyC_MainModule_Backup(PyObject **main_mod) + { +- PyInterpreterState *interp = PyThreadState_GET()->interp; +- *main_mod = PyDict_GetItemString(interp->modules, "__main__"); ++ PyObject *modules = PyImport_GetModuleDict(); ++ *main_mod = PyDict_GetItemString(modules, "__main__"); + Py_XINCREF(*main_mod); /* don't free */ + } + + void PyC_MainModule_Restore(PyObject *main_mod) + { +- PyInterpreterState *interp = PyThreadState_GET()->interp; +- PyDict_SetItemString(interp->modules, "__main__", main_mod); ++ PyObject *modules = PyImport_GetModuleDict(); ++ PyDict_SetItemString(modules, "__main__", main_mod); + Py_XDECREF(main_mod); + } + +@@ -732,7 +736,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...) + + va_list vargs; + +- int *sizes = PyMem_MALLOC(sizeof(int) * (n / 2)); ++ Py_ssize_t *sizes = PyMem_MALLOC(sizeof(*sizes) * (n / 2)); + int i; + + PyObject *py_dict = PyC_DefaultNameSpace(filepath); +diff --git a/blender-2.79b/source/blender/python/intern/bpy_app_translations.c b/blender-2.79b/source/blender/python/intern/bpy_app_translations.c +index 6ba858f..1b853be 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_app_translations.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_app_translations.c +@@ -714,7 +714,7 @@ static PyTypeObject BlenderAppTranslationsType = { + /* methods */ + /* No destructor, this is a singleton! */ + NULL, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ +diff --git a/blender-2.79b/source/blender/python/intern/bpy_interface.c b/blender-2.79b/source/blender/python/intern/bpy_interface.c +index 6077418..0d36ba1 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_interface.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_interface.c +@@ -529,7 +529,7 @@ static bool python_script_exec( + + if (py_dict) { + #ifdef PYMODULE_CLEAR_WORKAROUND +- PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItemString(PyThreadState_GET()->interp->modules, "__main__"); ++ PyModuleObject *mmod = (PyModuleObject *)PyDict_GetItemString(PyImport_GetModuleDict(), "__main__"); + PyObject *dict_back = mmod->md_dict; + /* freeing the module will clear the namespace, + * gives problems running classes defined in this namespace being used later. */ +diff --git a/blender-2.79b/source/blender/python/intern/bpy_library_load.c b/blender-2.79b/source/blender/python/intern/bpy_library_load.c +index cb6a714..c8fd392 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_library_load.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_library_load.c +@@ -98,7 +98,7 @@ static PyTypeObject bpy_lib_Type = { + 0, /* tp_itemsize */ + /* methods */ + (destructor)bpy_lib_dealloc, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ +diff --git a/blender-2.79b/source/blender/python/intern/bpy_props.c b/blender-2.79b/source/blender/python/intern/bpy_props.c +index 3a18167..2b8e356 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_props.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_props.c +@@ -28,6 +28,8 @@ + * existing blender types. + */ + ++/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */ ++#define PY_SSIZE_T_CLEAN + + #include <Python.h> + +@@ -2012,7 +2014,7 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) + static const char *kwlist[] = {"attr", "name", "description", "default", + "options", "subtype", "update", "get", "set", NULL}; + const char *id = NULL, *name = NULL, *description = ""; +- int id_len; ++ Py_ssize_t id_len; + bool def = false; + PropertyRNA *prop; + PyObject *pyopts = NULL; +@@ -2094,7 +2096,7 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject + static const char *kwlist[] = {"attr", "name", "description", "default", + "options", "subtype", "size", "update", "get", "set", NULL}; + const char *id = NULL, *name = NULL, *description = ""; +- int id_len; ++ Py_ssize_t id_len; + int def[PYRNA_STACK_ARRAY] = {0}; + int size = 3; + PropertyRNA *prop; +@@ -2199,7 +2201,7 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) + "min", "max", "soft_min", "soft_max", + "step", "options", "subtype", "update", "get", "set", NULL}; + const char *id = NULL, *name = NULL, *description = ""; +- int id_len; ++ Py_ssize_t id_len; + int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1, def = 0; + PropertyRNA *prop; + PyObject *pyopts = NULL; +@@ -2296,7 +2298,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject + "min", "max", "soft_min", "soft_max", + "step", "options", "subtype", "size", "update", "get", "set", NULL}; + const char *id = NULL, *name = NULL, *description = ""; +- int id_len; ++ Py_ssize_t id_len; + int min = INT_MIN, max = INT_MAX, soft_min = INT_MIN, soft_max = INT_MAX, step = 1; + int def[PYRNA_STACK_ARRAY] = {0}; + int size = 3; +@@ -2410,7 +2412,7 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) + "step", "precision", "options", "subtype", + "unit", "update", "get", "set", NULL}; + const char *id = NULL, *name = NULL, *description = ""; +- int id_len; ++ Py_ssize_t id_len; + float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3, def = 0.0f; + int precision = 2; + PropertyRNA *prop; +@@ -2521,7 +2523,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec + "step", "precision", "options", "subtype", + "unit", "size", "update", "get", "set", NULL}; + const char *id = NULL, *name = NULL, *description = ""; +- int id_len; ++ Py_ssize_t id_len; + float min = -FLT_MAX, max = FLT_MAX, soft_min = -FLT_MAX, soft_max = FLT_MAX, step = 3; + float def[PYRNA_STACK_ARRAY] = {0.0f}; + int precision = 2, size = 3; +@@ -2628,7 +2630,7 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw + static const char *kwlist[] = {"attr", "name", "description", "default", + "maxlen", "options", "subtype", "update", "get", "set", NULL}; + const char *id = NULL, *name = NULL, *description = "", *def = ""; +- int id_len; ++ Py_ssize_t id_len; + int maxlen = 0; + PropertyRNA *prop; + PyObject *pyopts = NULL; +@@ -2738,7 +2740,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) + "options", "update", "get", "set", NULL}; + const char *id = NULL, *name = NULL, *description = ""; + PyObject *def = NULL; +- int id_len; ++ Py_ssize_t id_len; + int defvalue = 0; + PyObject *items, *items_fast; + EnumPropertyItem *eitems; +@@ -2886,7 +2888,7 @@ PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw) + if (srna) { + static const char *kwlist[] = {"attr", "type", "name", "description", "options", "poll", "update", NULL}; + const char *id = NULL, *name = NULL, *description = ""; +- int id_len; ++ Py_ssize_t id_len; + PropertyRNA *prop; + StructRNA *ptype; + PyObject *type = Py_None; +@@ -2960,7 +2962,7 @@ PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw) + if (srna) { + static const char *kwlist[] = {"attr", "type", "name", "description", "options", NULL}; + const char *id = NULL, *name = NULL, *description = ""; +- int id_len; ++ Py_ssize_t id_len; + PropertyRNA *prop; + StructRNA *ptype; + PyObject *type = Py_None; +diff --git a/blender-2.79b/source/blender/python/intern/bpy_rna.c b/blender-2.79b/source/blender/python/intern/bpy_rna.c +index 832a872..b473398 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_rna.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_rna.c +@@ -5647,7 +5647,7 @@ PyTypeObject pyrna_struct_meta_idprop_Type = { + 0, /* tp_itemsize */ + /* methods */ + NULL, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* deprecated in python 3.0! */ +@@ -5729,7 +5729,7 @@ PyTypeObject pyrna_struct_Type = { + 0, /* tp_itemsize */ + /* methods */ + (destructor) pyrna_struct_dealloc, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ +@@ -5818,7 +5818,7 @@ PyTypeObject pyrna_prop_Type = { + 0, /* tp_itemsize */ + /* methods */ + (destructor) pyrna_prop_dealloc, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ +@@ -5902,7 +5902,7 @@ PyTypeObject pyrna_prop_array_Type = { + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_array_dealloc, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ +@@ -5985,7 +5985,7 @@ PyTypeObject pyrna_prop_collection_Type = { + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_dealloc, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ +@@ -6070,7 +6070,7 @@ static PyTypeObject pyrna_prop_collection_idprop_Type = { + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_dealloc, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ +@@ -6155,7 +6155,7 @@ PyTypeObject pyrna_func_Type = { + 0, /* tp_itemsize */ + /* methods */ + NULL, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ +@@ -6251,7 +6251,7 @@ static PyTypeObject pyrna_prop_collection_iter_Type = { + 0, /* tp_itemsize */ + /* methods */ + (destructor)pyrna_prop_collection_iter_dealloc, /* tp_dealloc */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ +diff --git a/blender-2.79b/source/blender/python/intern/gpu.c b/blender-2.79b/source/blender/python/intern/gpu.c +index 48230a7..25016c5 100644 +--- a/blender-2.79b/source/blender/python/intern/gpu.c ++++ b/blender-2.79b/source/blender/python/intern/gpu.c +@@ -323,7 +323,7 @@ PyObject *GPU_initPython(void) + { + PyObject *module; + PyObject *submodule; +- PyObject *sys_modules = PyThreadState_GET()->interp->modules; ++ PyObject *sys_modules = PyImport_GetModuleDict(); + + module = PyInit_gpu(); + +@@ -334,7 +334,7 @@ PyObject *GPU_initPython(void) + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); + Py_INCREF(submodule); + +- PyDict_SetItem(PyImport_GetModuleDict(), PyModule_GetNameObject(module), module); ++ PyDict_SetItem(sys_modules, PyModule_GetNameObject(module), module); + return module; + } + +diff --git a/blender-2.79b/source/blender/python/intern/gpu_offscreen.c b/blender-2.79b/source/blender/python/intern/gpu_offscreen.c +index 7711ce1..d301599 100644 +--- a/blender-2.79b/source/blender/python/intern/gpu_offscreen.c ++++ b/blender-2.79b/source/blender/python/intern/gpu_offscreen.c +@@ -293,7 +293,7 @@ static PyTypeObject BPy_GPUOffScreen_Type = { + 0, /* tp_itemsize */ + /* methods */ + (destructor)BPy_GPUOffScreen__tp_dealloc, /* tp_dealloc */ +- NULL, /* tp_print */ ++ (printfunc)NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils.c b/blender-2.79b/source/blender/python/mathutils/mathutils.c +index 96ae0a9..21d3624 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils.c +@@ -622,7 +622,7 @@ PyMODINIT_FUNC PyInit_mathutils(void) + { + PyObject *mod; + PyObject *submodule; +- PyObject *sys_modules = PyThreadState_GET()->interp->modules; ++ PyObject *sys_modules = PyImport_GetModuleDict(); + + if (PyType_Ready(&vector_Type) < 0) + return NULL; +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_Color.c b/blender-2.79b/source/blender/python/mathutils/mathutils_Color.c +index 9997cd9..b12982e 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_Color.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_Color.c +@@ -846,7 +846,7 @@ PyTypeObject color_Type = { + sizeof(ColorObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BaseMathObject_dealloc, /* tp_dealloc */ +- NULL, /* tp_print */ ++ (printfunc)NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_Euler.c b/blender-2.79b/source/blender/python/mathutils/mathutils_Euler.c +index 9492b6d..494b5ea 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_Euler.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_Euler.c +@@ -700,7 +700,7 @@ PyTypeObject euler_Type = { + sizeof(EulerObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BaseMathObject_dealloc, /* tp_dealloc */ +- NULL, /* tp_print */ ++ (printfunc)NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c b/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c +index e368e88..1b05aae 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c +@@ -2768,7 +2768,7 @@ PyTypeObject matrix_Type = { + sizeof(MatrixObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)BaseMathObject_dealloc, /*tp_dealloc*/ +- NULL, /*tp_print*/ ++ (printfunc)NULL, /*tp_print*/ + NULL, /*tp_getattr*/ + NULL, /*tp_setattr*/ + NULL, /*tp_compare*/ +@@ -3092,7 +3092,7 @@ PyTypeObject matrix_access_Type = { + sizeof(MatrixAccessObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)MatrixAccess_dealloc, /*tp_dealloc*/ +- NULL, /*tp_print*/ ++ (printfunc)NULL, /*tp_print*/ + NULL, /*tp_getattr*/ + NULL, /*tp_setattr*/ + NULL, /*tp_compare*/ +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_Quaternion.c b/blender-2.79b/source/blender/python/mathutils/mathutils_Quaternion.c +index d283c71..02aabd0 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_Quaternion.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_Quaternion.c +@@ -1275,7 +1275,7 @@ PyTypeObject quaternion_Type = { + sizeof(QuaternionObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BaseMathObject_dealloc, /* tp_dealloc */ +- NULL, /* tp_print */ ++ (printfunc)NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_Vector.c b/blender-2.79b/source/blender/python/mathutils/mathutils_Vector.c +index afc8a30..af73aa2 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_Vector.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_Vector.c +@@ -2887,7 +2887,7 @@ PyTypeObject vector_Type = { + /* Methods to implement standard operations */ + + (destructor) BaseMathObject_dealloc, /* destructor tp_dealloc; */ +- NULL, /* printfunc tp_print; */ ++ (printfunc)NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* cmpfunc tp_compare; */ +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_bvhtree.c b/blender-2.79b/source/blender/python/mathutils/mathutils_bvhtree.c +index 30c0cda..c3b28e7 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_bvhtree.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_bvhtree.c +@@ -1243,7 +1243,7 @@ PyTypeObject PyBVHTree_Type = { + 0, /* tp_itemsize */ + /* methods */ + (destructor)py_bvhtree__tp_dealloc, /* tp_dealloc */ +- NULL, /* tp_print */ ++ (printfunc)NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_kdtree.c b/blender-2.79b/source/blender/python/mathutils/mathutils_kdtree.c +index ca66c19..2e36a08 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_kdtree.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_kdtree.c +@@ -415,7 +415,7 @@ PyTypeObject PyKDTree_Type = { + 0, /* tp_itemsize */ + /* methods */ + (destructor)PyKDTree__tp_dealloc, /* tp_dealloc */ +- NULL, /* tp_print */ ++ (printfunc)NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_noise.c b/blender-2.79b/source/blender/python/mathutils/mathutils_noise.c +index 143e51e..f9d128f 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_noise.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_noise.c +@@ -842,16 +842,17 @@ PyMODINIT_FUNC PyInit_mathutils_noise(void) + { + PyObject *submodule = PyModule_Create(&M_Noise_module_def); + PyObject *item_types, *item_metrics; ++ PyObject *sys_modules = PyImport_GetModuleDict(); + + /* use current time as seed for random number generator by default */ + setRndSeed(0); + + PyModule_AddObject(submodule, "types", (item_types = PyInit_mathutils_noise_types())); +- PyDict_SetItemString(PyThreadState_GET()->interp->modules, "noise.types", item_types); ++ PyDict_SetItemString(sys_modules, "noise.types", item_types); + Py_INCREF(item_types); + + PyModule_AddObject(submodule, "distance_metrics", (item_metrics = PyInit_mathutils_noise_metrics())); +- PyDict_SetItemString(PyThreadState_GET()->interp->modules, "noise.distance_metrics", item_metrics); ++ PyDict_SetItemString(sys_modules, "noise.distance_metrics", item_metrics); + Py_INCREF(item_metrics); + + return submodule; +diff --git a/blender-2.79b/source/gameengine/Ketsji/KX_PythonInit.cpp b/blender-2.79b/source/gameengine/Ketsji/KX_PythonInit.cpp +index 97a7e16..71e610d 100644 +--- a/blender-2.79b/source/gameengine/Ketsji/KX_PythonInit.cpp ++++ b/blender-2.79b/source/gameengine/Ketsji/KX_PythonInit.cpp +@@ -1569,7 +1569,7 @@ PyTypeObject PyRASOffScreen_Type = { + 0, /* tp_itemsize */ + /* methods */ + (destructor)PyRASOffScreen__tp_dealloc, /* tp_dealloc */ +- NULL, /* tp_print */ ++ (printfunc)NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ +@@ -2239,7 +2239,7 @@ PyMODINIT_FUNC initBGE(void) + { + PyObject *mod; + PyObject *submodule; +- PyObject *sys_modules = PyThreadState_GET()->interp->modules; ++ PyObject *sys_modules = PyImport_GetModuleDict(); + const char *mod_full; + + mod = PyModule_Create(&BGE_module_def); diff --git a/0008_python3_9.patch b/0008_python3_9.patch new file mode 100644 index 000000000000..46644957a874 --- /dev/null +++ b/0008_python3_9.patch @@ -0,0 +1,229 @@ +commit cef9646dbecd745b70f10501477fd7497e874f19 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sun Dec 17 01:22:11 2023 +0100 + + python3.9: "Fix crash starting Blender with Python 3.9" + + Fully applied Blender upstream ref: 0133bcaf38f6ecb5d6937c9b762026cc452720de + +commit 500ea8f791406747ec430e654cabe8a5a90f5dad +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sun Dec 17 01:07:33 2023 +0100 + + python3.9: "Fix T81688: BPY_thread_save crashes with Python 3.9" + + Fully applied Blender upstream ref: 5edba9b42f684bf8b99894bb6988e7f46180e12c + +commit 1a02a89e57a5fcd61da7cf7c2949250ccc88c6bf +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 02:10:10 2023 +0100 + + python3.9: "Python: support building again version 3.9 (unreleased)" + + Fully applied Blender upstream ref: 56d0df51a36fdce7ec2d1fbb7b47b1d95b591b5f + +diff --git a/blender-2.79b/source/blender/python/generic/bpy_threads.c b/blender-2.79b/source/blender/python/generic/bpy_threads.c +index fbc1456..628e28f 100644 +--- a/blender-2.79b/source/blender/python/generic/bpy_threads.c ++++ b/blender-2.79b/source/blender/python/generic/bpy_threads.c +@@ -35,14 +35,11 @@ + /* analogue of PyEval_SaveThread() */ + BPy_ThreadStatePtr BPY_thread_save(void) + { +- PyThreadState *tstate = PyThreadState_Swap(NULL); +- /* note: tstate can be NULL when quitting Blender */ +- +- if (tstate && PyEval_ThreadsInitialized()) { +- PyEval_ReleaseLock(); ++ /* The thread-state can be NULL when quitting Blender. */ ++ if (_PyThreadState_UncheckedGet()) { ++ return (BPy_ThreadStatePtr)PyEval_SaveThread(); + } +- +- return (BPy_ThreadStatePtr)tstate; ++ return NULL; + } + + /* analogue of PyEval_RestoreThread() */ +diff --git a/blender-2.79b/source/blender/python/intern/bpy_rna.c b/blender-2.79b/source/blender/python/intern/bpy_rna.c +index b473398..26a4351 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_rna.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_rna.c +@@ -7321,13 +7321,15 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v + PyErr_Clear(); + } + else { +- Py_DECREF(item); /* no need to keep a ref, the class owns it (technically we should keep a ref but...) */ ++ /* Store original so we can decrement it's reference before returning. */ ++ PyObject *item_orig = item; + if (is_staticmethod) { + if (PyMethod_Check(item) == 0) { + PyErr_Format(PyExc_TypeError, + "expected %.200s, %.200s class \"%.200s\" " + "attribute to be a static/class method, not a %.200s", + class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name); ++ Py_DECREF(item_orig); + return -1; + } + item = ((PyMethodObject *)item)->im_func; +@@ -7338,6 +7340,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v + "expected %.200s, %.200s class \"%.200s\" " + "attribute to be a function, not a %.200s", + class_type, py_class_name, RNA_function_identifier(func), Py_TYPE(item)->tp_name); ++ Py_DECREF(item_orig); + return -1; + } + } +@@ -7369,9 +7372,11 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v + class_type, py_class_name, RNA_function_identifier(func), + func_arg_count, arg_count); + } ++ Py_DECREF(item_orig); + return -1; + } + } ++ Py_DECREF(item_orig); + } + } + +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c b/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c +index 1b05aae..0805ab1 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c +@@ -48,7 +48,8 @@ static PyObject *Matrix_copy_notest(MatrixObject *self, const float *matrix); + static PyObject *Matrix_copy(MatrixObject *self); + static PyObject *Matrix_deepcopy(MatrixObject *self, PyObject *args); + static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value); +-static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self); ++static PyObject *matrix__apply_to_copy(PyObject *(*matrix_func)(MatrixObject *), ++ MatrixObject *self); + static PyObject *MatrixAccess_CreatePyObject(MatrixObject *matrix, const eMatrixAccess_t type); + + static int matrix_row_vector_check(MatrixObject *mat, VectorObject *vec, int row) +@@ -385,14 +386,15 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + return NULL; + } + +-static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self) ++static PyObject *matrix__apply_to_copy(PyObject *(*matrix_func)(MatrixObject *), ++ MatrixObject *self) + { + PyObject *ret = Matrix_copy(self); + if (ret) { +- PyObject *ret_dummy = matrix_func(ret); ++ PyObject *ret_dummy = matrix_func((MatrixObject *)ret); + if (ret_dummy) { + Py_DECREF(ret_dummy); +- return (PyObject *)ret; ++ return ret; + } + else { /* error */ + Py_DECREF(ret); +@@ -1598,7 +1600,7 @@ PyDoc_STRVAR(Matrix_adjugated_doc, + ); + static PyObject *Matrix_adjugated(MatrixObject *self) + { +- return matrix__apply_to_copy((PyNoArgsFunction)Matrix_adjugate, self); ++ return matrix__apply_to_copy(Matrix_adjugate, self); + } + + PyDoc_STRVAR(Matrix_rotate_doc, +@@ -1795,7 +1797,7 @@ PyDoc_STRVAR(Matrix_transposed_doc, + ); + static PyObject *Matrix_transposed(MatrixObject *self) + { +- return matrix__apply_to_copy((PyNoArgsFunction)Matrix_transpose, self); ++ return matrix__apply_to_copy(Matrix_transpose, self); + } + + /*---------------------------matrix.normalize() ------------------*/ +@@ -1842,7 +1844,7 @@ PyDoc_STRVAR(Matrix_normalized_doc, + ); + static PyObject *Matrix_normalized(MatrixObject *self) + { +- return matrix__apply_to_copy((PyNoArgsFunction)Matrix_normalize, self); ++ return matrix__apply_to_copy(Matrix_normalize, self); + } + + /*---------------------------matrix.zero() -----------------------*/ +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_Quaternion.c b/blender-2.79b/source/blender/python/mathutils/mathutils_Quaternion.c +index 02aabd0..c8eeaa2 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_Quaternion.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_Quaternion.c +@@ -40,7 +40,8 @@ + + #define QUAT_SIZE 4 + +-static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self); ++static PyObject *quat__apply_to_copy(PyObject *(*quat_func)(QuaternionObject *), ++ QuaternionObject *self); + static void quat__axis_angle_sanitize(float axis[3], float *angle); + static PyObject *Quaternion_copy(QuaternionObject *self); + static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args); +@@ -381,7 +382,7 @@ PyDoc_STRVAR(Quaternion_normalized_doc, + ); + static PyObject *Quaternion_normalized(QuaternionObject *self) + { +- return quat__apply_to_copy((PyNoArgsFunction)Quaternion_normalize, self); ++ return quat__apply_to_copy(Quaternion_normalize, self); + } + + PyDoc_STRVAR(Quaternion_invert_doc, +@@ -409,7 +410,7 @@ PyDoc_STRVAR(Quaternion_inverted_doc, + ); + static PyObject *Quaternion_inverted(QuaternionObject *self) + { +- return quat__apply_to_copy((PyNoArgsFunction)Quaternion_invert, self); ++ return quat__apply_to_copy(Quaternion_invert, self); + } + + PyDoc_STRVAR(Quaternion_identity_doc, +@@ -473,7 +474,7 @@ PyDoc_STRVAR(Quaternion_conjugated_doc, + ); + static PyObject *Quaternion_conjugated(QuaternionObject *self) + { +- return quat__apply_to_copy((PyNoArgsFunction)Quaternion_conjugate, self); ++ return quat__apply_to_copy(Quaternion_conjugate, self); + } + + PyDoc_STRVAR(Quaternion_copy_doc, +@@ -1146,10 +1147,11 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw + return Quaternion_CreatePyObject(quat, type); + } + +-static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self) ++static PyObject *quat__apply_to_copy(PyObject *(*quat_func)(QuaternionObject *), ++ QuaternionObject *self) + { + PyObject *ret = Quaternion_copy(self); +- PyObject *ret_dummy = quat_func(ret); ++ PyObject *ret_dummy = quat_func((QuaternionObject *)ret); + if (ret_dummy) { + Py_DECREF(ret_dummy); + return ret; +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_Vector.c b/blender-2.79b/source/blender/python/mathutils/mathutils_Vector.c +index af73aa2..18ecf2f 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_Vector.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_Vector.c +@@ -92,10 +92,10 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + return Vector_CreatePyObject_alloc(vec, size, type); + } + +-static PyObject *vec__apply_to_copy(PyNoArgsFunction vec_func, VectorObject *self) ++static PyObject *vec__apply_to_copy(PyObject *(*vec_func)(VectorObject *), VectorObject *self) + { + PyObject *ret = Vector_copy(self); +- PyObject *ret_dummy = vec_func(ret); ++ PyObject *ret_dummy = vec_func((VectorObject *)ret); + if (ret_dummy) { + Py_DECREF(ret_dummy); + return (PyObject *)ret; +@@ -378,7 +378,7 @@ PyDoc_STRVAR(Vector_normalized_doc, + ); + static PyObject *Vector_normalized(VectorObject *self) + { +- return vec__apply_to_copy((PyNoArgsFunction)Vector_normalize, self); ++ return vec__apply_to_copy(Vector_normalize, self); + } + + PyDoc_STRVAR(Vector_resize_doc, diff --git a/0009_python3_10.patch b/0009_python3_10.patch new file mode 100644 index 000000000000..a5c63da8e58f --- /dev/null +++ b/0009_python3_10.patch @@ -0,0 +1,1124 @@ +commit 5a4f5d69d90dc497e7a0dd8df56e7b3757edf6d4 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 00:33:17 2023 +0100 + + python3.10: "Fix T85573: Building with Python 3.10a5 fails" + + Adjusted Blender upstream ref: dae445d94a7a5e1ad38719ea05e5bb0bc76ede84 + + Command used: + + grep -rIlZ _PyUnicode_AsString ./blender-2.79b/ | xargs -0 sed -i 's/_PyUnicode_AsString/PyUnicode_AsUTF8/g' + +commit 5009c95b82cab0bddefce14d915303634c7369ee +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 00:30:30 2023 +0100 + + python3.10: "PyAPI: resolve build error with Python 3.10" + + Fully applied Blender upstream ref: 6fe00939b0a471cc149ea5b3c63ca57b049b4a37 + +diff --git a/blender-2.79b/intern/cycles/blender/blender_python.cpp b/blender-2.79b/intern/cycles/blender/blender_python.cpp +index bee6dd1..88fbf8a 100644 +--- a/blender-2.79b/intern/cycles/blender/blender_python.cpp ++++ b/blender-2.79b/intern/cycles/blender/blender_python.cpp +@@ -141,7 +141,7 @@ void python_thread_state_restore(void **python_thread_state) + + static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) + { +- const char *result = _PyUnicode_AsString(py_str); ++ const char *result = PyUnicode_AsUTF8(py_str); + if(result) { + /* 99% of the time this is enough but we better support non unicode + * chars since blender doesnt limit this. +diff --git a/blender-2.79b/source/blender/freestyle/intern/python/BPy_SShape.cpp b/blender-2.79b/source/blender/freestyle/intern/python/BPy_SShape.cpp +index 9169adf..eabfc07 100644 +--- a/blender-2.79b/source/blender/freestyle/intern/python/BPy_SShape.cpp ++++ b/blender-2.79b/source/blender/freestyle/intern/python/BPy_SShape.cpp +@@ -194,7 +194,7 @@ static int SShape_name_set(BPy_SShape *self, PyObject *value, void *UNUSED(closu + PyErr_SetString(PyExc_TypeError, "value must be a string"); + return -1; + } +- const char *name = _PyUnicode_AsString(value); ++ const char *name = PyUnicode_AsUTF8(value); + self->ss->setName(name); + return 0; + } +diff --git a/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops.c b/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops.c +index ea37159..8543c8f 100644 +--- a/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops.c ++++ b/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops.c +@@ -220,7 +220,7 @@ static PyTypeObject bmesh_op_Type = { + + static PyObject *bpy_bmesh_ops_fakemod_getattro(PyObject *UNUSED(self), PyObject *pyname) + { +- const char *opname = _PyUnicode_AsString(pyname); ++ const char *opname = PyUnicode_AsUTF8(pyname); + + if (BMO_opcode_from_opname(opname) != -1) { + return bpy_bmesh_op_CreatePyObject(opname); +diff --git a/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops_call.c b/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops_call.c +index 8f28791..7f2cab3 100644 +--- a/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops_call.c ++++ b/blender-2.79b/source/blender/python/bmesh/bmesh_py_ops_call.c +@@ -724,7 +724,7 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw) + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(kw, &pos, &key, &value)) { +- const char *slot_name = _PyUnicode_AsString(key); ++ const char *slot_name = PyUnicode_AsUTF8(key); + BMOpSlot *slot; + + if (!BMO_slot_exists(bmop.slots_in, slot_name)) { +diff --git a/blender-2.79b/source/blender/python/bmesh/bmesh_py_types_customdata.c b/blender-2.79b/source/blender/python/bmesh/bmesh_py_types_customdata.c +index 908f6b5..9b0d7b9 100644 +--- a/blender-2.79b/source/blender/python/bmesh/bmesh_py_types_customdata.c ++++ b/blender-2.79b/source/blender/python/bmesh/bmesh_py_types_customdata.c +@@ -658,7 +658,7 @@ static PyObject *bpy_bmlayercollection_subscript(BPy_BMLayerCollection *self, Py + { + /* don't need error check here */ + if (PyUnicode_Check(key)) { +- return bpy_bmlayercollection_subscript_str(self, _PyUnicode_AsString(key)); ++ return bpy_bmlayercollection_subscript_str(self, PyUnicode_AsUTF8(key)); + } + else if (PyIndex_Check(key)) { + Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); +@@ -712,7 +712,7 @@ static PyObject *bpy_bmlayercollection_subscript(BPy_BMLayerCollection *self, Py + + static int bpy_bmlayercollection_contains(BPy_BMLayerCollection *self, PyObject *value) + { +- const char *keyname = _PyUnicode_AsString(value); ++ const char *keyname = PyUnicode_AsUTF8(value); + CustomData *data; + int index; + +diff --git a/blender-2.79b/source/blender/python/generic/bpy_internal_import.c b/blender-2.79b/source/blender/python/generic/bpy_internal_import.c +index 7ab6447..78f7b84 100644 +--- a/blender-2.79b/source/blender/python/generic/bpy_internal_import.c ++++ b/blender-2.79b/source/blender/python/generic/bpy_internal_import.c +@@ -253,7 +253,7 @@ PyObject *bpy_text_reimport(PyObject *module, int *found) + if (module_file == NULL) { + return NULL; + } +- filepath = (char *)_PyUnicode_AsString(module_file); ++ filepath = (char *)PyUnicode_AsUTF8(module_file); + Py_DECREF(module_file); + if (filepath == NULL) { + return NULL; +diff --git a/blender-2.79b/source/blender/python/generic/idprop_py_api.c b/blender-2.79b/source/blender/python/generic/idprop_py_api.c +index 576f114..a8fea1d 100644 +--- a/blender-2.79b/source/blender/python/generic/idprop_py_api.c ++++ b/blender-2.79b/source/blender/python/generic/idprop_py_api.c +@@ -181,13 +181,13 @@ static int BPy_IDGroup_SetData(BPy_IDProperty *self, IDProperty *prop, PyObject + st = (char *)PyC_UnicodeAsByte(value, &value_coerce); + alloc_len = strlen(st) + 1; + +- st = _PyUnicode_AsString(value); ++ st = PyUnicode_AsUTF8(value); + IDP_ResizeArray(prop, alloc_len); + memcpy(IDP_Array(prop), st, alloc_len); + Py_XDECREF(value_coerce); + } + #else +- st = _PyUnicode_AsString(value); ++ st = PyUnicode_AsUTF8(value); + IDP_ResizeArray(prop, strlen(st) + 1); + strcpy(IDP_Array(prop), st); + #endif +@@ -248,7 +248,7 @@ static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *UNUS + return -1; + } + +- name = _PyUnicode_AsStringAndSize(value, &name_size); ++ name = PyUnicode_AsUTF8AndSize(value, &name_size); + + if (name_size > MAX_IDPROP_NAME) { + PyErr_SetString(PyExc_TypeError, "string length cannot exceed 63 characters!"); +@@ -291,7 +291,7 @@ static PyObject *BPy_IDGroup_Map_GetItem(BPy_IDProperty *self, PyObject *item) + return NULL; + } + +- name = _PyUnicode_AsString(item); ++ name = PyUnicode_AsUTF8(item); + + if (name == NULL) { + PyErr_SetString(PyExc_TypeError, "only strings are allowed as keys of ID properties"); +@@ -349,7 +349,7 @@ static const char *idp_try_read_name(PyObject *name_obj) + const char *name = NULL; + if (name_obj) { + Py_ssize_t name_size; +- name = _PyUnicode_AsStringAndSize(name_obj, &name_size); ++ name = PyUnicode_AsUTF8AndSize(name_obj, &name_size); + + if (name == NULL) { + PyErr_Format(PyExc_KeyError, +@@ -406,7 +406,7 @@ static IDProperty *idp_from_PyUnicode(const char *name, PyObject *ob) + prop = IDP_New(IDP_STRING, &val, name); + Py_XDECREF(value_coerce); + #else +- val.str = _PyUnicode_AsString(ob); ++ val.str = PyUnicode_AsUTF8(ob); + prop = IDP_New(IDP_STRING, val, name); + #endif + return prop; +@@ -693,7 +693,7 @@ int BPy_Wrap_SetMapItem(IDProperty *prop, PyObject *key, PyObject *val) + + if (val == NULL) { /* del idprop[key] */ + IDProperty *pkey; +- const char *name = _PyUnicode_AsString(key); ++ const char *name = PyUnicode_AsUTF8(key); + + if (name == NULL) { + PyErr_Format(PyExc_KeyError, +@@ -867,7 +867,7 @@ static PyObject *BPy_IDGroup_pop(BPy_IDProperty *self, PyObject *value) + { + IDProperty *idprop; + PyObject *pyform; +- const char *name = _PyUnicode_AsString(value); ++ const char *name = PyUnicode_AsUTF8(value); + + if (!name) { + PyErr_Format(PyExc_TypeError, +@@ -1027,7 +1027,7 @@ static PyObject *BPy_IDGroup_items(BPy_IDProperty *self) + + static int BPy_IDGroup_Contains(BPy_IDProperty *self, PyObject *value) + { +- const char *name = _PyUnicode_AsString(value); ++ const char *name = PyUnicode_AsUTF8(value); + + if (!name) { + PyErr_Format(PyExc_TypeError, +@@ -1826,7 +1826,7 @@ void IDP_spit(IDProperty *prop) + ret_str = PyObject_Repr(ret_dict); + Py_DECREF(ret_dict); + +- printf("IDProperty(%p): %s\n", prop, _PyUnicode_AsString(ret_str)); ++ printf("IDProperty(%p): %s\n", prop, PyUnicode_AsUTF8(ret_str)); + + Py_DECREF(ret_str); + +diff --git a/blender-2.79b/source/blender/python/generic/py_capi_utils.c b/blender-2.79b/source/blender/python/generic/py_capi_utils.c +index f4a2595..17cb657 100644 +--- a/blender-2.79b/source/blender/python/generic/py_capi_utils.c ++++ b/blender-2.79b/source/blender/python/generic/py_capi_utils.c +@@ -292,7 +292,7 @@ void PyC_FileAndNum(const char **filename, int *lineno) + + /* when executing a script */ + if (filename) { +- *filename = _PyUnicode_AsString(frame->f_code->co_filename); ++ *filename = PyUnicode_AsUTF8(frame->f_code->co_filename); + } + + /* when executing a module */ +@@ -305,7 +305,7 @@ void PyC_FileAndNum(const char **filename, int *lineno) + if (mod) { + PyObject *mod_file = PyModule_GetFilenameObject(mod); + if (mod_file) { +- *filename = _PyUnicode_AsString(mod_name); ++ *filename = PyUnicode_AsUTF8(mod_name); + Py_DECREF(mod_file); + } + else { +@@ -315,7 +315,7 @@ void PyC_FileAndNum(const char **filename, int *lineno) + + /* unlikely, fallback */ + if (*filename == NULL) { +- *filename = _PyUnicode_AsString(mod_name); ++ *filename = PyUnicode_AsUTF8(mod_name); + } + } + } +@@ -554,7 +554,7 @@ const char *PyC_UnicodeAsByteAndSize(PyObject *py_str, Py_ssize_t *size, PyObjec + { + const char *result; + +- result = _PyUnicode_AsStringAndSize(py_str, size); ++ result = PyUnicode_AsUTF8AndSize(py_str, size); + + if (result) { + /* 99% of the time this is enough but we better support non unicode +@@ -583,7 +583,7 @@ const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) + { + const char *result; + +- result = _PyUnicode_AsString(py_str); ++ result = PyUnicode_AsUTF8(py_str); + + if (result) { + /* 99% of the time this is enough but we better support non unicode +@@ -975,7 +975,7 @@ int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int *r_value, co + *r_value = 0; + + while (_PySet_NextEntry(value, &pos, &key, &hash)) { +- const char *param = _PyUnicode_AsString(key); ++ const char *param = PyUnicode_AsUTF8(key); + + if (param == NULL) { + PyErr_Format(PyExc_TypeError, +@@ -1100,7 +1100,7 @@ bool PyC_RunString_AsString(const char *expr, const char *filename, char **r_val + const char *val; + Py_ssize_t val_len; + +- val = _PyUnicode_AsStringAndSize(retval, &val_len); ++ val = PyUnicode_AsUTF8AndSize(retval, &val_len); + if (val == NULL && PyErr_Occurred()) { + ok = false; + } +diff --git a/blender-2.79b/source/blender/python/intern/bpy.c b/blender-2.79b/source/blender/python/intern/bpy.c +index 5bbfb49..a8e2187 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy.c ++++ b/blender-2.79b/source/blender/python/intern/bpy.c +@@ -232,7 +232,7 @@ static PyObject *bpy_escape_identifier(PyObject *UNUSED(self), PyObject *value) + PyObject *value_escape; + size_t size; + +- value_str = _PyUnicode_AsStringAndSize(value, &value_str_len); ++ value_str = PyUnicode_AsUTF8AndSize(value, &value_str_len); + + if (value_str == NULL) { + PyErr_SetString(PyExc_TypeError, "expected a string"); +diff --git a/blender-2.79b/source/blender/python/intern/bpy_app_translations.c b/blender-2.79b/source/blender/python/intern/bpy_app_translations.c +index 1b853be..6f1e67b 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_app_translations.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_app_translations.c +@@ -193,7 +193,7 @@ static void _build_translations_cache(PyObject *py_messages, const char *locale) + msgctxt = BLT_I18NCONTEXT_DEFAULT_BPYRNA; + } + else if (PyUnicode_Check(tmp)) { +- msgctxt = _PyUnicode_AsString(tmp); ++ msgctxt = PyUnicode_AsUTF8(tmp); + } + else { + invalid_key = true; +@@ -201,7 +201,7 @@ static void _build_translations_cache(PyObject *py_messages, const char *locale) + + tmp = PyTuple_GET_ITEM(pykey, 1); + if (PyUnicode_Check(tmp)) { +- msgid = _PyUnicode_AsString(tmp); ++ msgid = PyUnicode_AsUTF8(tmp); + } + else { + invalid_key = true; +@@ -231,7 +231,7 @@ static void _build_translations_cache(PyObject *py_messages, const char *locale) + /* Do not overwrite existing keys! */ + if (BPY_app_translations_py_pgettext(msgctxt, msgid) == msgid) { + GHashKey *key = _ghashutil_keyalloc(msgctxt, msgid); +- BLI_ghash_insert(_translations_cache, key, BLI_strdup(_PyUnicode_AsString(trans))); ++ BLI_ghash_insert(_translations_cache, key, BLI_strdup(PyUnicode_AsUTF8(trans))); + } + } + } +@@ -313,7 +313,7 @@ static PyObject *app_translations_py_messages_register(BlenderAppTranslations *s + if (PyDict_Contains(self->py_messages, module_name)) { + PyErr_Format(PyExc_ValueError, + "bpy.app.translations.register: translations message cache already contains some data for " +- "addon '%s'", (const char *)_PyUnicode_AsString(module_name)); ++ "addon '%s'", (const char *)PyUnicode_AsUTF8(module_name)); + return NULL; + } + +diff --git a/blender-2.79b/source/blender/python/intern/bpy_interface.c b/blender-2.79b/source/blender/python/intern/bpy_interface.c +index 0d36ba1..5653ba4 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_interface.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_interface.c +@@ -863,7 +863,7 @@ static void bpy_module_delay_init(PyObject *bpy_proxy) + /* updating the module dict below will loose the reference to __file__ */ + PyObject *filename_obj = PyModule_GetFilenameObject(bpy_proxy); + +- const char *filename_rel = _PyUnicode_AsString(filename_obj); /* can be relative */ ++ const char *filename_rel = PyUnicode_AsUTF8(filename_obj); /* can be relative */ + char filename_abs[1024]; + + BLI_strncpy(filename_abs, filename_rel, sizeof(filename_abs)); +diff --git a/blender-2.79b/source/blender/python/intern/bpy_library_load.c b/blender-2.79b/source/blender/python/intern/bpy_library_load.c +index c8fd392..6ae5318 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_library_load.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_library_load.c +@@ -353,7 +353,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) + for (i = 0; i < size; i++) { + PyObject *item_src = PyList_GET_ITEM(ls, i); + PyObject *item_dst; /* must be set below */ +- const char *item_idname = _PyUnicode_AsString(item_src); ++ const char *item_idname = PyUnicode_AsUTF8(item_src); + + // printf(" %s\n", item_idname); + +diff --git a/blender-2.79b/source/blender/python/intern/bpy_operator.c b/blender-2.79b/source/blender/python/intern/bpy_operator.c +index c1fcb07..ad6f6cb 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_operator.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_operator.c +@@ -398,7 +398,7 @@ static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value) + { + wmOperatorType *ot; + PointerRNA ptr; +- const char *opname = _PyUnicode_AsString(value); ++ const char *opname = PyUnicode_AsUTF8(value); + BPy_StructRNA *pyrna = NULL; + + if (opname == NULL) { +@@ -431,7 +431,7 @@ static PyObject *pyop_getinstance(PyObject *UNUSED(self), PyObject *value) + wmOperatorType *ot; + wmOperator *op; + PointerRNA ptr; +- const char *opname = _PyUnicode_AsString(value); ++ const char *opname = PyUnicode_AsUTF8(value); + BPy_StructRNA *pyrna = NULL; + + if (opname == NULL) { +diff --git a/blender-2.79b/source/blender/python/intern/bpy_operator_wrap.c b/blender-2.79b/source/blender/python/intern/bpy_operator_wrap.c +index 9071990..5d7e56b 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_operator_wrap.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_operator_wrap.c +@@ -70,7 +70,7 @@ static void operator_properties_init(wmOperatorType *ot) + if (bl_property) { + if (PyUnicode_Check(bl_property)) { + /* since the property is explicitly given, raise an error if its not found */ +- prop_id = _PyUnicode_AsString(bl_property); ++ prop_id = PyUnicode_AsUTF8(bl_property); + prop_raise_error = true; + } + else { +diff --git a/blender-2.79b/source/blender/python/intern/bpy_props.c b/blender-2.79b/source/blender/python/intern/bpy_props.c +index 2b8e356..aab4276 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_props.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_props.c +@@ -192,9 +192,9 @@ static void printf_func_error(PyObject *py_func) + + /* use py style error */ + fprintf(stderr, "File \"%s\", line %d, in %s\n", +- _PyUnicode_AsString(f_code->co_filename), ++ PyUnicode_AsUTF8(f_code->co_filename), + f_code->co_firstlineno, +- _PyUnicode_AsString(((PyFunctionObject *)py_func)->func_name) ++ PyUnicode_AsUTF8(((PyFunctionObject *)py_func)->func_name) + ); + } + +@@ -1074,7 +1074,7 @@ static void bpy_prop_string_get_cb(struct PointerRNA *ptr, struct PropertyRNA *p + } + else { + Py_ssize_t length; +- const char *buffer = _PyUnicode_AsStringAndSize(ret, &length); ++ const char *buffer = PyUnicode_AsUTF8AndSize(ret, &length); + memcpy(value, buffer, length + 1); + Py_DECREF(ret); + } +@@ -1134,7 +1134,7 @@ static int bpy_prop_string_length_cb(struct PointerRNA *ptr, struct PropertyRNA + } + else { + Py_ssize_t length_ssize_t = 0; +- _PyUnicode_AsStringAndSize(ret, &length_ssize_t); ++ PyUnicode_AsUTF8AndSize(ret, &length_ssize_t); + length = length_ssize_t; + Py_DECREF(ret); + } +@@ -1392,7 +1392,7 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i + } + else { + if (def) { +- def_cmp = _PyUnicode_AsString(def); ++ def_cmp = PyUnicode_AsUTF8(def); + if (def_cmp == NULL) { + PyErr_Format(PyExc_TypeError, + "EnumProperty(...): default option must be a 'str' " +@@ -1421,13 +1421,13 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i + if ((PyTuple_CheckExact(item)) && + (item_size = PyTuple_GET_SIZE(item)) && + (item_size >= 3 && item_size <= 5) && +- (tmp.identifier = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) && +- (tmp.name = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) && +- (tmp.description = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) && ++ (tmp.identifier = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) && ++ (tmp.name = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) && ++ (tmp.description = PyUnicode_AsUTF8AndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) && + /* TODO, number isn't ensured to be unique from the script author */ + (item_size != 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1) && + (item_size != 5 || ((py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.icon) != -1 || +- (tmp_icon = _PyUnicode_AsString(PyTuple_GET_ITEM(item, 3)))) && ++ (tmp_icon = PyUnicode_AsUTF8(PyTuple_GET_ITEM(item, 3)))) && + py_long_as_int(PyTuple_GET_ITEM(item, 4), &tmp.value) != -1))) + { + if (is_enum_flag) { +@@ -2845,7 +2845,7 @@ StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix) + if (!srna) { + if (PyErr_Occurred()) { + PyObject *msg = PyC_ExceptionBuffer(); +- const char *msg_char = _PyUnicode_AsString(msg); ++ const char *msg_char = PyUnicode_AsUTF8(msg); + PyErr_Format(PyExc_TypeError, + "%.200s expected an RNA type, failed with: %s", + error_prefix, msg_char); +diff --git a/blender-2.79b/source/blender/python/intern/bpy_rna.c b/blender-2.79b/source/blender/python/intern/bpy_rna.c +index 26a4351..722e23d 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_rna.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_rna.c +@@ -313,7 +313,7 @@ static bool rna_id_write_error(PointerRNA *ptr, PyObject *key) + if (!ELEM(idcode, ID_WM, ID_SCR)) { /* may need more added here */ + const char *idtype = BKE_idcode_to_name(idcode); + const char *pyname; +- if (key && PyUnicode_Check(key)) pyname = _PyUnicode_AsString(key); ++ if (key && PyUnicode_Check(key)) pyname = PyUnicode_AsUTF8(key); + else pyname = "<UNKNOWN>"; + + /* make a nice string error */ +@@ -1188,7 +1188,7 @@ static int pyrna_string_to_enum( + PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *r_value, + const char *error_prefix) + { +- const char *param = _PyUnicode_AsString(item); ++ const char *param = PyUnicode_AsUTF8(item); + + if (param == NULL) { + PyErr_Format(PyExc_TypeError, +@@ -1232,7 +1232,7 @@ BLI_bitmap *pyrna_set_to_enum_bitmap( + BLI_bitmap *bitmap = BLI_BITMAP_NEW(bitmap_size, __func__); + + while (_PySet_NextEntry(value, &pos, &key, &hash)) { +- const char *param = _PyUnicode_AsString(key); ++ const char *param = PyUnicode_AsUTF8(key); + if (param == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s expected a string, not %.200s", +@@ -1289,7 +1289,7 @@ int pyrna_set_to_enum_bitfield( + *r_value = 0; + + while (_PySet_NextEntry(value, &pos, &key, &hash)) { +- const char *param = _PyUnicode_AsString(key); ++ const char *param = PyUnicode_AsUTF8(key); + + if (param == NULL) { + PyErr_Format(PyExc_TypeError, +@@ -1590,7 +1590,7 @@ int pyrna_pydict_to_props( + Py_ssize_t pos = 0; + + while (PyDict_Next(kw, &pos, &key, &value)) { +- arg_name = _PyUnicode_AsString(key); ++ arg_name = PyUnicode_AsUTF8(key); + if (RNA_struct_find_property(ptr, arg_name) == NULL) break; + arg_name = NULL; + } +@@ -1761,10 +1761,10 @@ static int pyrna_py_to_prop( + param = PyC_UnicodeAsByte(value, &value_coerce); + } + else { +- param = _PyUnicode_AsString(value); ++ param = PyUnicode_AsUTF8(value); + } + #else /* USE_STRING_COERCE */ +- param = _PyUnicode_AsString(value); ++ param = PyUnicode_AsUTF8(value); + #endif /* USE_STRING_COERCE */ + + if (param == NULL) { +@@ -2019,7 +2019,7 @@ static int pyrna_py_to_prop( + "Converting a python list to an RNA collection") == -1) + { + PyObject *msg = PyC_ExceptionBuffer(); +- const char *msg_char = _PyUnicode_AsString(msg); ++ const char *msg_char = PyUnicode_AsUTF8(msg); + + PyErr_Format(PyExc_TypeError, + "%.200s %.200s.%.200s error converting a member of a collection " +@@ -2310,7 +2310,7 @@ static int pyrna_prop_collection_subscript_str_lib_pair_ptr( + err_prefix, RNA_struct_identifier(self->ptr.type)); + return -1; + } +- else if ((keyname = _PyUnicode_AsString(PyTuple_GET_ITEM(key, 0))) == NULL) { ++ else if ((keyname = PyUnicode_AsUTF8(PyTuple_GET_ITEM(key, 0))) == NULL) { + PyErr_Format(PyExc_KeyError, + "%s: id must be a string, not %.200s", + err_prefix, Py_TYPE(PyTuple_GET_ITEM(key, 0))->tp_name); +@@ -2326,7 +2326,7 @@ static int pyrna_prop_collection_subscript_str_lib_pair_ptr( + } + else if (PyUnicode_Check(keylib)) { + Main *bmain = self->ptr.data; +- const char *keylib_str = _PyUnicode_AsString(keylib); ++ const char *keylib_str = PyUnicode_AsUTF8(keylib); + lib = BLI_findstring(&bmain->library, keylib_str, offsetof(Library, name)); + if (lib == NULL) { + if (err_not_found) { +@@ -2517,7 +2517,7 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject + PYRNA_PROP_CHECK_OBJ(self); + + if (PyUnicode_Check(key)) { +- return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); ++ return pyrna_prop_collection_subscript_str(self, PyUnicode_AsUTF8(key)); + } + else if (PyIndex_Check(key)) { + Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError); +@@ -2640,7 +2640,7 @@ static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, PyObject * + + #if 0 + if (PyUnicode_Check(key)) { +- return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key)); ++ return pyrna_prop_collection_subscript_str(self, PyUnicode_AsUTF8(key)); + } + else + #endif +@@ -2704,7 +2704,7 @@ static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject + + #if 0 + if (PyUnicode_Check(key)) { +- return pyrna_prop_array_subscript_str(self, _PyUnicode_AsString(key)); ++ return pyrna_prop_array_subscript_str(self, PyUnicode_AsUTF8(key)); + } + else + #endif +@@ -3141,7 +3141,7 @@ static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *key) + else { + + /* key in dict style check */ +- const char *keyname = _PyUnicode_AsString(key); ++ const char *keyname = PyUnicode_AsUTF8(key); + + if (keyname == NULL) { + PyErr_SetString(PyExc_TypeError, +@@ -3159,7 +3159,7 @@ static int pyrna_prop_collection_contains(BPy_PropertyRNA *self, PyObject *key) + static int pyrna_struct_contains(BPy_StructRNA *self, PyObject *value) + { + IDProperty *group; +- const char *name = _PyUnicode_AsString(value); ++ const char *name = PyUnicode_AsUTF8(value); + + PYRNA_STRUCT_CHECK_INT(self); + +@@ -3224,7 +3224,7 @@ static PyObject *pyrna_struct_subscript(BPy_StructRNA *self, PyObject *key) + { + /* mostly copied from BPy_IDGroup_Map_GetItem */ + IDProperty *group, *idprop; +- const char *name = _PyUnicode_AsString(key); ++ const char *name = PyUnicode_AsUTF8(key); + + PYRNA_STRUCT_CHECK_OBJ(self); + +@@ -3841,7 +3841,7 @@ static PyObject *pyrna_struct_dir(BPy_StructRNA *self) + /* ---------------getattr-------------------------------------------- */ + static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) + { +- const char *name = _PyUnicode_AsString(pyname); ++ const char *name = PyUnicode_AsUTF8(pyname); + PyObject *ret; + PropertyRNA *prop; + FunctionRNA *func; +@@ -3985,7 +3985,7 @@ static PyObject *pyrna_struct_meta_idprop_getattro(PyObject *cls, PyObject *attr + if (ret == NULL) { // || pyrna_is_deferred_prop(ret) + StructRNA *srna = srna_from_self(cls, "StructRNA.__getattr__"); + if (srna) { +- PropertyRNA *prop = RNA_struct_type_find_property(srna, _PyUnicode_AsString(attr)); ++ PropertyRNA *prop = RNA_struct_type_find_property(srna, PyUnicode_AsUTF8(attr)); + if (prop) { + PointerRNA tptr; + PyErr_Clear(); /* clear error from tp_getattro */ +@@ -4004,7 +4004,7 @@ static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyOb + { + StructRNA *srna = srna_from_self(cls, "StructRNA.__setattr__"); + const bool is_deferred_prop = (value && pyrna_is_deferred_prop(value)); +- const char *attr_str = _PyUnicode_AsString(attr); ++ const char *attr_str = PyUnicode_AsUTF8(attr); + + if (srna && !pyrna_write_check() && (is_deferred_prop || RNA_struct_type_find_property(srna, attr_str))) { + PyErr_Format(PyExc_AttributeError, +@@ -4064,7 +4064,7 @@ static int pyrna_struct_meta_idprop_setattro(PyObject *cls, PyObject *attr, PyOb + + static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject *value) + { +- const char *name = _PyUnicode_AsString(pyname); ++ const char *name = PyUnicode_AsUTF8(pyname); + PropertyRNA *prop = NULL; + + PYRNA_STRUCT_CHECK_INT(self); +@@ -4159,7 +4159,7 @@ static PyObject *pyrna_prop_array_getattro(BPy_PropertyRNA *self, PyObject *pyna + + static PyObject *pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject *pyname) + { +- const char *name = _PyUnicode_AsString(pyname); ++ const char *name = PyUnicode_AsUTF8(pyname); + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy_prop_collection: __getattr__ must be a string"); +@@ -4227,7 +4227,7 @@ static PyObject *pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject + /* --------------- setattr------------------------------------------- */ + static int pyrna_prop_collection_setattro(BPy_PropertyRNA *self, PyObject *pyname, PyObject *value) + { +- const char *name = _PyUnicode_AsString(pyname); ++ const char *name = PyUnicode_AsUTF8(pyname); + PropertyRNA *prop; + PointerRNA r_ptr; + +@@ -4573,7 +4573,7 @@ static PyObject *pyrna_prop_collection_get(BPy_PropertyRNA *self, PyObject *args + return NULL; + + if (PyUnicode_Check(key_ob)) { +- const char *key = _PyUnicode_AsString(key_ob); ++ const char *key = PyUnicode_AsUTF8(key_ob); + + if (RNA_property_collection_lookup_string(&self->ptr, self->prop, key, &newptr)) + return pyrna_struct_CreatePyObject(&newptr); +@@ -4608,7 +4608,7 @@ PyDoc_STRVAR(pyrna_prop_collection_find_doc, + static PyObject *pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key_ob) + { + Py_ssize_t key_len_ssize_t; +- const char *key = _PyUnicode_AsStringAndSize(key_ob, &key_len_ssize_t); ++ const char *key = PyUnicode_AsUTF8AndSize(key_ob, &key_len_ssize_t); + const int key_len = (int)key_len_ssize_t; /* comare with same type */ + + char name[256], *nameptr; +@@ -5308,7 +5308,7 @@ static PyObject *small_dict_get_item_string(PyObject *dict, const char *key_look + + while (PyDict_Next(dict, &pos, &key, &value)) { + if (PyUnicode_Check(key)) { +- if (STREQ(key_lookup, _PyUnicode_AsString(key))) { ++ if (STREQ(key_lookup, PyUnicode_AsUTF8(key))) { + return value; + } + } +@@ -5444,7 +5444,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject + #ifdef DEBUG_STRING_FREE + if (item) { + if (PyUnicode_Check(item)) { +- PyList_APPEND(string_free_ls, PyUnicode_FromString(_PyUnicode_AsString(item))); ++ PyList_APPEND(string_free_ls, PyUnicode_FromString(PyUnicode_AsUTF8(item))); + } + } + #endif +@@ -5495,7 +5495,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject + + while (PyDict_Next(kw, &pos, &key, &value)) { + +- arg_name = _PyUnicode_AsString(key); ++ arg_name = PyUnicode_AsUTF8(key); + found = false; + + if (arg_name == NULL) { /* unlikely the argname is not a string but ignore if it is*/ +@@ -6862,7 +6862,7 @@ static PyObject *pyrna_basetype_getattro(BPy_BaseTypeRNA *self, PyObject *pyname + { + PointerRNA newptr; + PyObject *ret; +- const char *name = _PyUnicode_AsString(pyname); ++ const char *name = PyUnicode_AsUTF8(pyname); + + if (name == NULL) { + PyErr_SetString(PyExc_AttributeError, "bpy.types: __getattr__ must be a string"); +@@ -6873,14 +6873,14 @@ static PyObject *pyrna_basetype_getattro(BPy_BaseTypeRNA *self, PyObject *pyname + if (ret == NULL) { + PyErr_Format(PyExc_RuntimeError, + "bpy.types.%.200s subtype could not be generated, this is a bug!", +- _PyUnicode_AsString(pyname)); ++ PyUnicode_AsUTF8(pyname)); + } + } + else { + #if 0 + PyErr_Format(PyExc_AttributeError, + "bpy.types.%.200s RNA_Struct does not exist", +- _PyUnicode_AsString(pyname)); ++ PyUnicode_AsUTF8(pyname)); + return NULL; + #endif + /* The error raised here will be displayed */ +@@ -7090,11 +7090,11 @@ static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item + if (PyArg_ParseTuple(item, "OO!", &py_func, &PyDict_Type, &py_kw)) { + PyObject *args_fake; + +- if (*_PyUnicode_AsString(key) == '_') { ++ if (*PyUnicode_AsUTF8(key) == '_') { + PyErr_Format(PyExc_ValueError, + "bpy_struct \"%.200s\" registration error: " + "%.200s could not register because the property starts with an '_'\n", +- RNA_struct_identifier(srna), _PyUnicode_AsString(key)); ++ RNA_struct_identifier(srna), PyUnicode_AsUTF8(key)); + return -1; + } + py_srna_cobject = PyCapsule_New(srna, NULL, NULL); +@@ -7137,7 +7137,7 @@ static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item + PyErr_Format(PyExc_ValueError, + "bpy_struct \"%.200s\" registration error: " + "%.200s could not register\n", +- RNA_struct_identifier(srna), _PyUnicode_AsString(key)); ++ RNA_struct_identifier(srna), PyUnicode_AsUTF8(key)); + return -1; + } + } +diff --git a/blender-2.79b/source/blender/python/intern/bpy_traceback.c b/blender-2.79b/source/blender/python/intern/bpy_traceback.c +index bff778b..fedf889 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_traceback.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_traceback.c +@@ -143,7 +143,7 @@ void python_script_error_jump(const char *filepath, int *lineno, int *offset) + PyObject *filename_py, *text_py; + + if (parse_syntax_error(value, &message, &filename_py, lineno, offset, &text_py)) { +- const char *filename = _PyUnicode_AsString(filename_py); ++ const char *filename = PyUnicode_AsUTF8(filename_py); + /* python adds a '/', prefix, so check for both */ + if ((BLI_path_cmp(filename, filepath) == 0) || + ((filename[0] == '\\' || filename[0] == '/') && BLI_path_cmp(filename + 1, filepath) == 0)) +diff --git a/blender-2.79b/source/blender/python/intern/bpy_util.c b/blender-2.79b/source/blender/python/intern/bpy_util.c +index 2b8ad6c..a292147 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_util.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_util.c +@@ -121,13 +121,13 @@ bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const boo + } + + #if 0 /* ARG!. workaround for a bug in blenders use of vsnprintf */ +- BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", _PyUnicode_AsString(pystring), filename, lineno); ++ BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", PyUnicode_AsUTF8(pystring), filename, lineno); + #else + pystring_format = PyUnicode_FromFormat( + TIP_("%s\nlocation: %s:%d\n"), +- _PyUnicode_AsString(pystring), filename, lineno); ++ PyUnicode_AsUTF8(pystring), filename, lineno); + +- cstring = _PyUnicode_AsString(pystring_format); ++ cstring = PyUnicode_AsUTF8(pystring_format); + BKE_report(reports, RPT_ERROR, cstring); + + /* not exactly needed. just for testing */ +@@ -137,7 +137,7 @@ bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const boo + #endif + } + else { +- BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(pystring)); ++ BKE_report(reports, RPT_ERROR, PyUnicode_AsUTF8(pystring)); + } + + +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils.c b/blender-2.79b/source/blender/python/mathutils/mathutils.c +index 21d3624..8b0959e 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils.c +@@ -110,7 +110,11 @@ Py_hash_t mathutils_array_hash(const float *array, size_t array_len) + x = 0x345678UL; + i = 0; + while (--len >= 0) { ++#if PY_VERSION_HEX >= 0x30a0000 /* Version: 3.10. */ ++ y = _Py_HashDouble(NULL, (double)(array[i++])); ++#else + y = _Py_HashDouble((double)(array[i++])); ++#endif + if (y == -1) + return -1; + x = (x ^ y) * mult; +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_Euler.c b/blender-2.79b/source/blender/python/mathutils/mathutils_Euler.c +index 494b5ea..d4200fb 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_Euler.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_Euler.c +@@ -639,7 +639,7 @@ static int Euler_order_set(EulerObject *self, PyObject *value, void *UNUSED(clos + if (BaseMath_Prepare_ForWrite(self) == -1) + return -1; + +- if (((order_str = _PyUnicode_AsString(value)) == NULL) || ++ if (((order_str = PyUnicode_AsUTF8(value)) == NULL) || + ((order = euler_order_from_string(order_str, "euler.order")) == -1)) + { + return -1; +diff --git a/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c b/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c +index 0805ab1..d535e17 100644 +--- a/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c ++++ b/blender-2.79b/source/blender/python/mathutils/mathutils_Matrix.c +@@ -482,7 +482,7 @@ static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args) + } + + if (vec && PyUnicode_Check(vec)) { +- axis = _PyUnicode_AsString((PyObject *)vec); ++ axis = PyUnicode_AsUTF8((PyObject *)vec); + if (axis == NULL || axis[0] == '\0' || axis[1] != '\0' || axis[0] < 'X' || axis[0] > 'Z') { + PyErr_SetString(PyExc_ValueError, + "Matrix.Rotation(): " +@@ -695,7 +695,7 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) + + if (PyUnicode_Check(axis)) { /* ortho projection onto cardinal plane */ + Py_ssize_t plane_len; +- const char *plane = _PyUnicode_AsStringAndSize(axis, &plane_len); ++ const char *plane = PyUnicode_AsUTF8AndSize(axis, &plane_len); + if (matSize == 2) { + if (plane_len == 1 && plane[0] == 'X') { + mat[0] = 1.0f; +diff --git a/blender-2.79b/source/gameengine/Converter/BL_ActionActuator.cpp b/blender-2.79b/source/gameengine/Converter/BL_ActionActuator.cpp +index d28cdb8..abbcd38 100644 +--- a/blender-2.79b/source/gameengine/Converter/BL_ActionActuator.cpp ++++ b/blender-2.79b/source/gameengine/Converter/BL_ActionActuator.cpp +@@ -358,7 +358,7 @@ PyObject *BL_ActionActuator::PyGetChannel(PyObject *value) + PyErr_SetString(PyExc_NotImplementedError, "BL_ActionActuator.getChannel() no longer works, please use BL_ArmatureObject.channels instead"); + return NULL; + #if 0 // XXX To be removed in a later version (first removed in 2.64) +- const char *string= _PyUnicode_AsString(value); ++ const char *string= PyUnicode_AsUTF8(value); + + if (GetParent()->GetGameObjectType() != SCA_IObject::OBJ_ARMATURE) + { +@@ -580,7 +580,7 @@ int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF + } + + bAction *action= NULL; +- STR_String val = _PyUnicode_AsString(value); ++ STR_String val = PyUnicode_AsUTF8(value); + + if (val != "") + { +diff --git a/blender-2.79b/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/blender-2.79b/source/gameengine/Converter/BL_ShapeActionActuator.cpp +index f21db41..dcb6433 100644 +--- a/blender-2.79b/source/gameengine/Converter/BL_ShapeActionActuator.cpp ++++ b/blender-2.79b/source/gameengine/Converter/BL_ShapeActionActuator.cpp +@@ -543,7 +543,7 @@ int BL_ShapeActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE + } + + bAction *action= NULL; +- STR_String val = _PyUnicode_AsString(value); ++ STR_String val = PyUnicode_AsUTF8(value); + + if (val != "") + { +diff --git a/blender-2.79b/source/gameengine/Expressions/intern/ListValue.cpp b/blender-2.79b/source/gameengine/Expressions/intern/ListValue.cpp +index 557ce7b..7111fc8 100644 +--- a/blender-2.79b/source/gameengine/Expressions/intern/ListValue.cpp ++++ b/blender-2.79b/source/gameengine/Expressions/intern/ListValue.cpp +@@ -362,7 +362,7 @@ static PyObject *listvalue_mapping_subscript(PyObject *self, PyObject *key) + } + + if (PyUnicode_Check(key)) { +- CValue *item = ((CListValue*) list)->FindValue(_PyUnicode_AsString(key)); ++ CValue *item = ((CListValue*) list)->FindValue(PyUnicode_AsUTF8(key)); + if (item) { + PyObject *pyobj = item->ConvertValueToPython(); + if (pyobj) +@@ -483,7 +483,7 @@ static int listvalue_buffer_contains(PyObject *self_v, PyObject *value) + } + + if (PyUnicode_Check(value)) { +- if (self->FindValue((const char *)_PyUnicode_AsString(value))) { ++ if (self->FindValue((const char *)PyUnicode_AsUTF8(value))) { + return 1; + } + } +diff --git a/blender-2.79b/source/gameengine/Expressions/intern/ListWrapper.cpp b/blender-2.79b/source/gameengine/Expressions/intern/ListWrapper.cpp +index db1518a..92737cf 100644 +--- a/blender-2.79b/source/gameengine/Expressions/intern/ListWrapper.cpp ++++ b/blender-2.79b/source/gameengine/Expressions/intern/ListWrapper.cpp +@@ -240,7 +240,7 @@ PyObject *CListWrapper::py_mapping_subscript(PyObject *self, PyObject *key) + return NULL; + } + +- const char *name = _PyUnicode_AsString(key); ++ const char *name = PyUnicode_AsUTF8(key); + int size = list->GetSize(); + + for (unsigned int i = 0; i < size; ++i) { +@@ -281,7 +281,7 @@ int CListWrapper::py_mapping_ass_subscript(PyObject *self, PyObject *key, PyObje + return -1; + } + +- const char *name = _PyUnicode_AsString(key); ++ const char *name = PyUnicode_AsUTF8(key); + int size = list->GetSize(); + + for (unsigned int i = 0; i < size; ++i) { +@@ -320,7 +320,7 @@ int CListWrapper::py_contains(PyObject *self, PyObject *key) + return -1; + } + +- const char *name = _PyUnicode_AsString(key); ++ const char *name = PyUnicode_AsUTF8(key); + int size = list->GetSize(); + + for (unsigned int i = 0; i < size; ++i) { +diff --git a/blender-2.79b/source/gameengine/Expressions/intern/PyObjectPlus.cpp b/blender-2.79b/source/gameengine/Expressions/intern/PyObjectPlus.cpp +index 1e4a59a..8c0f056 100644 +--- a/blender-2.79b/source/gameengine/Expressions/intern/PyObjectPlus.cpp ++++ b/blender-2.79b/source/gameengine/Expressions/intern/PyObjectPlus.cpp +@@ -1021,7 +1021,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt + if (PyUnicode_Check(value)) + { + Py_ssize_t val_size; +- const char *val = _PyUnicode_AsStringAndSize(value, &val_size); ++ const char *val = PyUnicode_AsUTF8AndSize(value, &val_size); + strncpy(ptr, val, attrdef->m_size); + ptr[attrdef->m_size-1] = 0; + } +@@ -1038,7 +1038,7 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt + if (PyUnicode_Check(value)) + { + Py_ssize_t val_len; +- const char *val = _PyUnicode_AsStringAndSize(value, &val_len); /* XXX, should be 'const' but we do a silly trick to have a shorter string */ ++ const char *val = PyUnicode_AsUTF8AndSize(value, &val_len); /* XXX, should be 'const' but we do a silly trick to have a shorter string */ + if (attrdef->m_clamp) + { + if (val_len < attrdef->m_imin) +diff --git a/blender-2.79b/source/gameengine/Expressions/intern/Value.cpp b/blender-2.79b/source/gameengine/Expressions/intern/Value.cpp +index f8796a7..ecc5142 100644 +--- a/blender-2.79b/source/gameengine/Expressions/intern/Value.cpp ++++ b/blender-2.79b/source/gameengine/Expressions/intern/Value.cpp +@@ -612,7 +612,7 @@ CValue *CValue::ConvertPythonToValue(PyObject *pyobj, const bool do_type_excepti + } else + if (PyUnicode_Check(pyobj)) + { +- vallie = new CStringValue(_PyUnicode_AsString(pyobj),""); ++ vallie = new CStringValue(PyUnicode_AsUTF8(pyobj),""); + } else + if (PyObject_TypeCheck(pyobj, &CValue::Type)) /* Note, don't let these get assigned to GameObject props, must check elsewhere */ + { +diff --git a/blender-2.79b/source/gameengine/GameLogic/SCA_PythonController.cpp b/blender-2.79b/source/gameengine/GameLogic/SCA_PythonController.cpp +index fd2e723..6aaf6f0 100644 +--- a/blender-2.79b/source/gameengine/GameLogic/SCA_PythonController.cpp ++++ b/blender-2.79b/source/gameengine/GameLogic/SCA_PythonController.cpp +@@ -204,7 +204,7 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) + + if (PyUnicode_Check(value)) { + /* get the actuator from the name */ +- const char *name= _PyUnicode_AsString(value); ++ const char *name= PyUnicode_AsUTF8(value); + for (it = lacts.begin(); it!= lacts.end(); ++it) { + if ( name == (*it)->GetName() ) { + return *it; +@@ -513,7 +513,7 @@ int SCA_PythonController::pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_D + { + SCA_PythonController* self = static_cast<SCA_PythonController*>(self_v); + +- const char *scriptArg = _PyUnicode_AsString(value); ++ const char *scriptArg = PyUnicode_AsUTF8(value); + + if (scriptArg==NULL) { + PyErr_SetString(PyExc_TypeError, "controller.script = string: Python Controller, expected a string script text"); +diff --git a/blender-2.79b/source/gameengine/Ketsji/KX_Camera.cpp b/blender-2.79b/source/gameengine/Ketsji/KX_Camera.cpp +index 89aea80..51b2272 100644 +--- a/blender-2.79b/source/gameengine/Ketsji/KX_Camera.cpp ++++ b/blender-2.79b/source/gameengine/Ketsji/KX_Camera.cpp +@@ -987,7 +987,7 @@ bool ConvertPythonToCamera(PyObject *value, KX_Camera **object, bool py_none_ok, + } + + if (PyUnicode_Check(value)) { +- STR_String value_str = _PyUnicode_AsString(value); ++ STR_String value_str = PyUnicode_AsUTF8(value); + *object = KX_GetActiveScene()->FindCamera(value_str); + + if (*object) { +@@ -995,7 +995,7 @@ bool ConvertPythonToCamera(PyObject *value, KX_Camera **object, bool py_none_ok, + } else { + PyErr_Format(PyExc_ValueError, + "%s, requested name \"%s\" did not match any KX_Camera in this scene", +- error_prefix, _PyUnicode_AsString(value)); ++ error_prefix, PyUnicode_AsUTF8(value)); + return false; + } + } +diff --git a/blender-2.79b/source/gameengine/Ketsji/KX_FontObject.cpp b/blender-2.79b/source/gameengine/Ketsji/KX_FontObject.cpp +index 91e8e4f..62ad415 100644 +--- a/blender-2.79b/source/gameengine/Ketsji/KX_FontObject.cpp ++++ b/blender-2.79b/source/gameengine/Ketsji/KX_FontObject.cpp +@@ -281,7 +281,7 @@ int KX_FontObject::pyattr_set_text(void *self_v, const KX_PYATTRIBUTE_DEF *attrd + KX_FontObject* self = static_cast<KX_FontObject*>(self_v); + if (!PyUnicode_Check(value)) + return PY_SET_ATTR_FAIL; +- const char *chars = _PyUnicode_AsString(value); ++ const char *chars = PyUnicode_AsUTF8(value); + + /* Allow for some logic brick control */ + CValue* tprop = self->GetProperty("Text"); +diff --git a/blender-2.79b/source/gameengine/Ketsji/KX_GameObject.cpp b/blender-2.79b/source/gameengine/Ketsji/KX_GameObject.cpp +index 3244400..e6f8e00 100644 +--- a/blender-2.79b/source/gameengine/Ketsji/KX_GameObject.cpp ++++ b/blender-2.79b/source/gameengine/Ketsji/KX_GameObject.cpp +@@ -2087,7 +2087,7 @@ PyObject *KX_GameObject::PyReinstancePhysicsMesh(PyObject *args) + static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) + { + KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); +- const char *attr_str= _PyUnicode_AsString(item); ++ const char *attr_str= PyUnicode_AsUTF8(item); + CValue* resultattr; + PyObject *pyconvert; + +@@ -2121,7 +2121,7 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) + static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) + { + KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); +- const char *attr_str= _PyUnicode_AsString(key); ++ const char *attr_str= PyUnicode_AsUTF8(key); + if (attr_str==NULL) + PyErr_Clear(); + +@@ -2214,7 +2214,7 @@ static int Seq_Contains(PyObject *self_v, PyObject *value) + return -1; + } + +- if (PyUnicode_Check(value) && self->GetProperty(_PyUnicode_AsString(value))) ++ if (PyUnicode_Check(value) && self->GetProperty(PyUnicode_AsUTF8(value))) + return 1; + + if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value)) +@@ -4124,7 +4124,7 @@ PyObject *KX_GameObject::Pyget(PyObject *args) + + + if (PyUnicode_Check(key)) { +- CValue *item = GetProperty(_PyUnicode_AsString(key)); ++ CValue *item = GetProperty(PyUnicode_AsUTF8(key)); + if (item) { + ret = item->ConvertValueToPython(); + if (ret) +@@ -4163,12 +4163,12 @@ bool ConvertPythonToGameObject(SCA_LogicManager *manager, PyObject *value, KX_Ga + } + + if (PyUnicode_Check(value)) { +- *object = (KX_GameObject*)manager->GetGameObjectByName(STR_String( _PyUnicode_AsString(value) )); ++ *object = (KX_GameObject*)manager->GetGameObjectByName(STR_String( PyUnicode_AsUTF8(value) )); + + if (*object) { + return true; + } else { +- PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, _PyUnicode_AsString(value)); ++ PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, PyUnicode_AsUTF8(value)); + return false; + } + } +diff --git a/blender-2.79b/source/gameengine/Ketsji/KX_MeshProxy.cpp b/blender-2.79b/source/gameengine/Ketsji/KX_MeshProxy.cpp +index 8da3542..0da22dc 100644 +--- a/blender-2.79b/source/gameengine/Ketsji/KX_MeshProxy.cpp ++++ b/blender-2.79b/source/gameengine/Ketsji/KX_MeshProxy.cpp +@@ -427,12 +427,12 @@ bool ConvertPythonToMesh(SCA_LogicManager *logicmgr, PyObject *value, RAS_MeshOb + } + + if (PyUnicode_Check(value)) { +- *object = (RAS_MeshObject*)logicmgr->GetMeshByName(STR_String( _PyUnicode_AsString(value) )); ++ *object = (RAS_MeshObject*)logicmgr->GetMeshByName(STR_String( PyUnicode_AsUTF8(value) )); + + if (*object) { + return true; + } else { +- PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, _PyUnicode_AsString(value)); ++ PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_MeshProxy in this scene", error_prefix, PyUnicode_AsUTF8(value)); + return false; + } + } +diff --git a/blender-2.79b/source/gameengine/Ketsji/KX_PythonInit.cpp b/blender-2.79b/source/gameengine/Ketsji/KX_PythonInit.cpp +index 71e610d..a112a63 100644 +--- a/blender-2.79b/source/gameengine/Ketsji/KX_PythonInit.cpp ++++ b/blender-2.79b/source/gameengine/Ketsji/KX_PythonInit.cpp +@@ -825,7 +825,7 @@ static PyObject *gLibNew(PyObject *, PyObject *args) + PyObject *ret= PyList_New(0); + PyObject *item; + for (Py_ssize_t i= 0; i < PyList_GET_SIZE(names); i++) { +- name= _PyUnicode_AsString(PyList_GET_ITEM(names, i)); ++ name= PyUnicode_AsUTF8(PyList_GET_ITEM(names, i)); + if (name) { + RAS_MeshObject *meshobj= kx_scene->GetSceneConverter()->ConvertMeshSpecial(kx_scene, maggie, name); + if (meshobj) { +diff --git a/blender-2.79b/source/gameengine/Ketsji/KX_Scene.cpp b/blender-2.79b/source/gameengine/Ketsji/KX_Scene.cpp +index b306108..86e51f5 100644 +--- a/blender-2.79b/source/gameengine/Ketsji/KX_Scene.cpp ++++ b/blender-2.79b/source/gameengine/Ketsji/KX_Scene.cpp +@@ -2218,7 +2218,7 @@ PyMethodDef KX_Scene::Methods[] = { + static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) + { + KX_Scene* self = static_cast<KX_Scene*>BGE_PROXY_REF(self_v); +- const char *attr_str= _PyUnicode_AsString(item); ++ const char *attr_str= PyUnicode_AsUTF8(item); + PyObject *pyconvert; + + if (self == NULL) { +@@ -2247,7 +2247,7 @@ static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) + static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) + { + KX_Scene* self = static_cast<KX_Scene*>BGE_PROXY_REF(self_v); +- const char *attr_str= _PyUnicode_AsString(key); ++ const char *attr_str= PyUnicode_AsUTF8(key); + if (attr_str==NULL) + PyErr_Clear(); + diff --git a/0010_python3_11.patch b/0010_python3_11.patch new file mode 100644 index 000000000000..3babb1047744 --- /dev/null +++ b/0010_python3_11.patch @@ -0,0 +1,122 @@ +commit 3e7abb113568b07627e00a7a4e5df5e3cfefccfe +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sun Dec 17 14:37:36 2023 +0100 + + python3.11: eval.h has been removed from Python 3.11 + + And compile.h is included with Python.h + +commit 5b4980bb042bf23779de97f38d6678f483a6f23e +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 02:31:55 2023 +0100 + + python3.11: Remove invalid use of Py_TPFLAGS_HAVE_GC flag + + Error otherwise thrown: + + SystemError: type bpy_struct has the Py_TPFLAGS_HAVE_GC flag but has + no traverse function + + This is for Python 3.11, see https://docs.python.org/3/whatsnew/3.11.html + """ + The PyType_Ready() function now raises an error if a type is defined + with the Py_TPFLAGS_HAVE_GC flag set but has no traverse function + (PyTypeObject.tp_traverse). (Contributed by Victor Stinner in + bpo-44263.) + """ + +commit 54c261ddfcb7221b1e6828c0a6a29a8b07f57043 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sat Dec 16 01:12:28 2023 +0100 + + python3.11: "Python: support v3.11 (beta) with changes to PyFrameObj.." + + Partially applied Blender upstream ref: 780c0ea097444c3be60314dffd203c099720badb + +diff --git a/blender-2.79b/source/blender/python/generic/py_capi_utils.c b/blender-2.79b/source/blender/python/generic/py_capi_utils.c +index 17cb657..10a38da 100644 +--- a/blender-2.79b/source/blender/python/generic/py_capi_utils.c ++++ b/blender-2.79b/source/blender/python/generic/py_capi_utils.c +@@ -282,17 +282,21 @@ void PyC_StackSpit(void) + void PyC_FileAndNum(const char **filename, int *lineno) + { + PyFrameObject *frame; +- ++ PyCodeObject *code; ++ + if (filename) *filename = NULL; + if (lineno) *lineno = -1; + +- if (!(frame = PyThreadState_GET()->frame)) { ++ if (!(frame = PyEval_GetFrame())) { ++ return; ++ } ++ if (!(code = PyFrame_GetCode(frame))) { + return; + } + + /* when executing a script */ + if (filename) { +- *filename = PyUnicode_AsUTF8(frame->f_code->co_filename); ++ *filename = PyUnicode_AsUTF8(code->co_filename); + } + + /* when executing a module */ +diff --git a/blender-2.79b/source/blender/python/intern/bpy_app_handlers.c b/blender-2.79b/source/blender/python/intern/bpy_app_handlers.c +index 90aa22d..bcabd09 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_app_handlers.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_app_handlers.c +@@ -155,8 +155,7 @@ static PyTypeObject BPyPersistent_Type = { + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ +- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | +- Py_TPFLAGS_BASETYPE, /* tp_flags */ ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ +diff --git a/blender-2.79b/source/blender/python/intern/bpy_rna.c b/blender-2.79b/source/blender/python/intern/bpy_rna.c +index 722e23d..f2f0ed7 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_rna.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_rna.c +@@ -5753,7 +5753,7 @@ PyTypeObject pyrna_struct_Type = { + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ +- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* long tp_flags; */ ++ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ +diff --git a/blender-2.79b/source/blender/python/intern/bpy_traceback.c b/blender-2.79b/source/blender/python/intern/bpy_traceback.c +index fedf889..462438f 100644 +--- a/blender-2.79b/source/blender/python/intern/bpy_traceback.c ++++ b/blender-2.79b/source/blender/python/intern/bpy_traceback.c +@@ -39,7 +39,9 @@ + + static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce) + { +- return PyBytes_AS_STRING((*coerce = PyUnicode_EncodeFSDefault(tb->tb_frame->f_code->co_filename))); ++ PyCodeObject *code = PyFrame_GetCode(tb->tb_frame); ++ *coerce = PyUnicode_EncodeFSDefault(code->co_filename); ++ return PyBytes_AS_STRING(*coerce); + } + + /* copied from pythonrun.c, 3.4.0 */ +diff --git a/blender-2.79b/source/gameengine/GameLogic/SCA_PythonController.cpp b/blender-2.79b/source/gameengine/GameLogic/SCA_PythonController.cpp +index 6aaf6f0..f8a9cc4 100644 +--- a/blender-2.79b/source/gameengine/GameLogic/SCA_PythonController.cpp ++++ b/blender-2.79b/source/gameengine/GameLogic/SCA_PythonController.cpp +@@ -41,11 +41,6 @@ + #include "SCA_IActuator.h" + #include "EXP_PyObjectPlus.h" + +-#ifdef WITH_PYTHON +-#include "compile.h" +-#include "eval.h" +-#endif // WITH_PYTHON +- + #include <algorithm> + + diff --git a/0011_ffmpeg.patch b/0011_ffmpeg.patch new file mode 100644 index 000000000000..340dc66d1c80 --- /dev/null +++ b/0011_ffmpeg.patch @@ -0,0 +1,4805 @@ +commit cc06806e12600076b1f7b1de4adcf41f0d7e9a6f +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Sun Dec 24 22:59:30 2023 +0100 + + ffmpeg: fix building BGE with latest FFMpeg + +commit 5e5a2a1eaf4205f10ac25c61358c613b240cc7cc +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Tue Dec 19 21:46:52 2023 +0100 + + ffmpeg: support for FFmpeg 5 + + Used Blender upstream refs: + + - 8d6264ea12 "Cleanup: Remove deprecated variables and functions calls from our ffmpeg code" + - dd2e187344 "Audaspace: add support for latest ffmpeg." + - af6a1b08e3 "VSE: Refactor our code to be compatible with ffmpeg 5.0" + - 08a6321501 "FFmpeg pixel format conversion improvements" + - fba35aa8c5 "Use FFmpeg's own `av_guess_frame_rate()` function instead of guessing ourselves" + + Updated the FFmpeg related code as much as possible to above refs + +commit abec792ffaf1f70ce68c18ff06065ae4224de1b1 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Tue Dec 19 18:09:24 2023 +0100 + + ffmpeg: replace deprecated av_free_packet() with av_packet_unref() + +commit 528f895ac4a3cd9b992c2e0b4e8c742e22b68e28 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Tue Dec 19 18:07:17 2023 +0100 + + ffmpeg: remove use of deprecated av_register_all() + +commit b234ee57030f620b7b5cee5f655cfcac27a5cb91 +Author: CYBERDEViL <cyberdevil@notabug.org> +Date: Mon Dec 18 22:36:24 2023 +0100 + + ffmpeg: "Fix building with latest versions of ffmpeg." + + Fully applied Blender upstream ref: 4e4a93bc454d93ec8523f44b73a42977e2868ecc + +diff --git a/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +index e9eea19..f28fb80 100644 +--- a/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp ++++ b/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +@@ -38,37 +38,36 @@ extern "C" { + #include <libavcodec/avcodec.h> + #include <libavformat/avformat.h> + #include <libavformat/avio.h> ++#include <libavutil/avutil.h> + #include "ffmpeg_compat.h" + } + ++#if LIBAVCODEC_VERSION_MAJOR < 58 ++#define FFMPEG_OLD_CODE ++#endif ++ + int AUD_FFMPEGReader::decode(AVPacket& packet, AUD_Buffer& buffer) + { +-#ifdef FFMPEG_HAVE_DECODE_AUDIO4 +- AVFrame* frame = NULL; ++ int buf_size = buffer.getSize(); ++ int buf_pos = 0; ++ ++#ifdef FFMPEG_OLD_CODE + int got_frame; + int read_length; + uint8_t* orig_data = packet.data; + int orig_size = packet.size; + +- int buf_size = buffer.getSize(); +- int buf_pos = 0; +- + while(packet.size > 0) + { + got_frame = 0; + +- if(!frame) +- frame = av_frame_alloc(); +- else +- av_frame_unref(frame); +- +- read_length = avcodec_decode_audio4(m_codecCtx, frame, &got_frame, &packet); ++ read_length = avcodec_decode_audio4(m_codecCtx, m_frame, &got_frame, &packet); + if(read_length < 0) + break; + + if(got_frame) + { +- int data_size = av_samples_get_buffer_size(NULL, m_codecCtx->channels, frame->nb_samples, m_codecCtx->sample_fmt, 1); ++ int data_size = av_samples_get_buffer_size(nullptr, m_codecCtx->channels, m_frame->nb_samples, m_codecCtx->sample_fmt, 1); + + if(buf_size - buf_pos < data_size) + { +@@ -78,18 +77,18 @@ int AUD_FFMPEGReader::decode(AVPacket& packet, AUD_Buffer& buffer) + + if(m_tointerleave) + { +- int single_size = data_size / m_codecCtx->channels / frame->nb_samples; ++ int single_size = data_size / m_codecCtx->channels / m_frame->nb_samples; + for(int channel = 0; channel < m_codecCtx->channels; channel++) + { +- for(int i = 0; i < frame->nb_samples; i++) ++ for(int i = 0; i < m_frame->nb_samples; i++) + { + memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size, +- frame->data[channel] + i * single_size, single_size); ++ m_frame->data[channel] + i * single_size, single_size); + } + } + } + else +- memcpy(((data_t*)buffer.getBuffer()) + buf_pos, frame->data[0], data_size); ++ memcpy(((data_t*)buffer.getBuffer()) + buf_pos, m_frame->data[0], data_size); + + buf_pos += data_size; + } +@@ -99,57 +98,44 @@ int AUD_FFMPEGReader::decode(AVPacket& packet, AUD_Buffer& buffer) + + packet.data = orig_data; + packet.size = orig_size; +- av_free(frame); +- +- return buf_pos; + #else +- // save packet parameters +- uint8_t *audio_pkg_data = packet.data; +- int audio_pkg_size = packet.size; +- +- int buf_size = buffer.getSize(); +- int buf_pos = 0; ++ avcodec_send_packet(m_codecCtx, &packet); + +- int read_length, data_size; ++ while(true) ++ { ++ auto ret = avcodec_receive_frame(m_codecCtx, m_frame); + +- AVPacket tmp_pkt; ++ if(ret != 0) ++ break; + +- av_init_packet(&tmp_pkt); ++ int data_size = av_samples_get_buffer_size(nullptr, m_codecCtx->channels, m_frame->nb_samples, m_codecCtx->sample_fmt, 1); + +- // as long as there is still data in the package +- while(audio_pkg_size > 0) +- { +- // resize buffer if needed +- if(buf_size - buf_pos < AVCODEC_MAX_AUDIO_FRAME_SIZE) ++ if(buf_size - buf_pos < data_size) + { +- buffer.resize(buf_size + AVCODEC_MAX_AUDIO_FRAME_SIZE, true); +- buf_size += AVCODEC_MAX_AUDIO_FRAME_SIZE; ++ buffer.resize(buf_size + data_size, true); ++ buf_size += data_size; + } + +- // read samples from the packet +- data_size = buf_size - buf_pos; +- +- tmp_pkt.data = audio_pkg_data; +- tmp_pkt.size = audio_pkg_size; +- +- read_length = avcodec_decode_audio3( +- m_codecCtx, +- (int16_t*)(((data_t*)buffer.getBuffer()) + buf_pos), +- &data_size, &tmp_pkt); +- +- // read error, next packet! +- if(read_length < 0) +- break; ++ if(m_tointerleave) ++ { ++ int single_size = data_size / m_codecCtx->channels / m_frame->nb_samples; ++ for(int channel = 0; channel < m_codecCtx->channels; channel++) ++ { ++ for(int i = 0; i < m_frame->nb_samples; i++) ++ { ++ std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size, ++ m_frame->data[channel] + i * single_size, single_size); ++ } ++ } ++ } ++ else ++ std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos, m_frame->data[0], data_size); + + buf_pos += data_size; +- +- // move packet parameters +- audio_pkg_data += read_length; +- audio_pkg_size -= read_length; + } ++#endif + + return buf_pos; +-#endif + } + + static const char* streaminfo_error = "AUD_FFMPEGReader: Stream info couldn't " +@@ -176,7 +162,11 @@ void AUD_FFMPEGReader::init() + + for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++) + { ++#ifdef FFMPEG_OLD_CODE + if((m_formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) ++#else ++ if((m_formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ++#endif + && (m_stream < 0)) + { + m_stream=i; +@@ -187,12 +177,35 @@ void AUD_FFMPEGReader::init() + if(m_stream == -1) + AUD_THROW(AUD_ERROR_FFMPEG, noaudio_error); + +- m_codecCtx = m_formatCtx->streams[m_stream]->codec; +- + // get a decoder and open it +- AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id); +- if(!aCodec) ++#ifndef FFMPEG_OLD_CODE ++ const AVCodec* aCodec = avcodec_find_decoder(m_formatCtx->streams[m_stream]->codecpar->codec_id); ++ ++ if(!aCodec) { + AUD_THROW(AUD_ERROR_FFMPEG, nodecoder_error); ++ } ++#endif ++ ++ m_frame = av_frame_alloc(); ++ ++ if(!m_frame) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be read, ffmpeg frame couldn't be allocated."); ++ ++#ifdef FFMPEG_OLD_CODE ++ m_codecCtx = m_formatCtx->streams[m_stream]->codec; ++ ++ AVCodec* aCodec = avcodec_find_decoder(m_codecCtx->codec_id); ++#else ++ m_codecCtx = avcodec_alloc_context3(aCodec); ++#endif ++ ++ if(!m_codecCtx) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be read, ffmpeg context couldn't be allocated."); ++ ++#ifndef FFMPEG_OLD_CODE ++ if(avcodec_parameters_to_context(m_codecCtx, m_formatCtx->streams[m_stream]->codecpar) < 0) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be read, ffmpeg decoder parameters couldn't be copied to decoder context."); ++#endif + + if(avcodec_open2(m_codecCtx, aCodec, NULL) < 0) + AUD_THROW(AUD_ERROR_FFMPEG, codecopen_error); +@@ -236,8 +249,10 @@ static const char* fileopen_error = "AUD_FFMPEGReader: File couldn't be " + "opened."; + + AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) : +- m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1), ++ m_pkgbuf(), + m_formatCtx(NULL), ++ m_codecCtx(nullptr), ++ m_frame(nullptr), + m_aviocontext(NULL), + m_membuf(NULL) + { +@@ -260,13 +275,15 @@ static const char* streamopen_error = "AUD_FFMPEGReader: Stream couldn't be " + "opened."; + + AUD_FFMPEGReader::AUD_FFMPEGReader(boost::shared_ptr<AUD_Buffer> buffer) : +- m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1), ++ m_pkgbuf(), ++ m_codecCtx(nullptr), ++ m_frame(nullptr), + m_membuffer(buffer), + m_membufferpos(0) + { +- m_membuf = reinterpret_cast<data_t*>(av_malloc(FF_MIN_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE)); ++ m_membuf = reinterpret_cast<data_t*>(av_malloc(AV_INPUT_BUFFER_MIN_SIZE + AV_INPUT_BUFFER_PADDING_SIZE)); + +- m_aviocontext = avio_alloc_context(m_membuf, FF_MIN_BUFFER_SIZE, 0, this, ++ m_aviocontext = avio_alloc_context(m_membuf, AV_INPUT_BUFFER_MIN_SIZE, 0, this, + read_packet, NULL, seek_packet); + + if(!m_aviocontext) +@@ -297,7 +314,14 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(boost::shared_ptr<AUD_Buffer> buffer) : + + AUD_FFMPEGReader::~AUD_FFMPEGReader() + { ++ if(m_frame) ++ av_frame_free(&m_frame); ++#ifdef FFMPEG_OLD_CODE + avcodec_close(m_codecCtx); ++#else ++ if(m_codecCtx) ++ avcodec_free_context(&m_codecCtx); ++#endif + avformat_close_input(&m_formatCtx); + } + +@@ -398,7 +422,7 @@ void AUD_FFMPEGReader::seek(int position) + } + } + } +- av_free_packet(&packet); ++ av_packet_unref(&packet); + } + } + else +@@ -429,7 +453,7 @@ AUD_Specs AUD_FFMPEGReader::getSpecs() const + void AUD_FFMPEGReader::read(int& length, bool& eos, sample_t* buffer) + { + // read packages and decode them +- AVPacket packet; ++ AVPacket packet = {}; + int data_size = 0; + int pkgbuf_pos; + int left = length; +@@ -446,7 +470,7 @@ void AUD_FFMPEGReader::read(int& length, bool& eos, sample_t* buffer) + m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), + data_size / AUD_FORMAT_SIZE(m_specs.format)); + buf += data_size / AUD_FORMAT_SIZE(m_specs.format); +- left -= data_size/sample_size; ++ left -= data_size / sample_size; + } + + // for each frame read as long as there isn't enough data already +@@ -463,9 +487,9 @@ void AUD_FFMPEGReader::read(int& length, bool& eos, sample_t* buffer) + m_convert((data_t*) buf, (data_t*) m_pkgbuf.getBuffer(), + data_size / AUD_FORMAT_SIZE(m_specs.format)); + buf += data_size / AUD_FORMAT_SIZE(m_specs.format); +- left -= data_size/sample_size; ++ left -= data_size / sample_size; + } +- av_free_packet(&packet); ++ av_packet_unref(&packet); + } + // read more data than necessary? + if(pkgbuf_pos > data_size) +diff --git a/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h b/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h +index 377086e..a86be99 100644 +--- a/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h ++++ b/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h +@@ -81,6 +81,11 @@ private: + */ + AVCodecContext* m_codecCtx; + ++ /** ++ * The AVFrame structure for using ffmpeg. ++ */ ++ AVFrame* m_frame; ++ + /** + * The AVIOContext to read the data from. + */ +@@ -129,9 +134,9 @@ private: + */ + void init(); + +- // hide copy constructor and operator= +- AUD_FFMPEGReader(const AUD_FFMPEGReader&); +- AUD_FFMPEGReader& operator=(const AUD_FFMPEGReader&); ++ // delete copy constructor and operator= ++ AUD_FFMPEGReader(const AUD_FFMPEGReader&) = delete; ++ AUD_FFMPEGReader& operator=(const AUD_FFMPEGReader&) = delete; + + public: + /** +diff --git a/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp b/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp +index 3f95ac7..bde90a6 100644 +--- a/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp ++++ b/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp +@@ -36,11 +36,15 @@ + + extern "C" { + #include <libavcodec/avcodec.h> +-#include <libavformat/avformat.h> + #include <libavformat/avio.h> ++#include <libavutil/channel_layout.h> + #include "ffmpeg_compat.h" + } + ++#if LIBAVCODEC_VERSION_MAJOR < 58 ++#define FFMPEG_OLD_CODE ++#endif ++ + static const char* context_error = "AUD_FFMPEGWriter: Couldn't allocate context."; + static const char* codec_error = "AUD_FFMPEGWriter: Invalid codec or codec not found."; + static const char* stream_error = "AUD_FFMPEGWriter: Couldn't allocate stream."; +@@ -51,88 +55,135 @@ static const char* write_error = "AUD_FFMPEGWriter: Error writing packet."; + AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) : + m_position(0), + m_specs(specs), ++ m_formatCtx(nullptr), ++ m_codecCtx(nullptr), ++ m_stream(nullptr), ++ m_packet(nullptr), ++ m_frame(nullptr), ++ m_deinterleave(false), + m_input_samples(0) + { +- static const char* formats[] = { NULL, "ac3", "flac", "matroska", "mp2", "mp3", "ogg", "wav" }; ++ static const char* formats[] = { nullptr, "ac3", "flac", "matroska", "mp2", "mp3", "ogg", "wav" }; + +- m_formatCtx = avformat_alloc_context(); +- if (!m_formatCtx) AUD_THROW(AUD_ERROR_FFMPEG, context_error); ++ if(avformat_alloc_output_context2(&m_formatCtx, nullptr, formats[format], filename.c_str()) < 0) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, format couldn't be found with ffmpeg."); + +- strcpy(m_formatCtx->filename, filename.c_str()); +- m_outputFmt = m_formatCtx->oformat = av_guess_format(formats[format], filename.c_str(), NULL); +- if (!m_outputFmt) { ++ const AVOutputFormat* outputFmt = m_formatCtx->oformat; ++ ++ if(!outputFmt) { + avformat_free_context(m_formatCtx); +- AUD_THROW(AUD_ERROR_FFMPEG, context_error); ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, output format couldn't be found with ffmpeg."); + } + ++ AVCodecID audio_codec = AV_CODEC_ID_NONE; ++ + switch(codec) + { + case AUD_CODEC_AAC: +- m_outputFmt->audio_codec = AV_CODEC_ID_AAC; ++ audio_codec = AV_CODEC_ID_AAC; + break; + case AUD_CODEC_AC3: +- m_outputFmt->audio_codec = AV_CODEC_ID_AC3; ++ audio_codec = AV_CODEC_ID_AC3; + break; + case AUD_CODEC_FLAC: +- m_outputFmt->audio_codec = AV_CODEC_ID_FLAC; ++ audio_codec = AV_CODEC_ID_FLAC; + break; + case AUD_CODEC_MP2: +- m_outputFmt->audio_codec = AV_CODEC_ID_MP2; ++ audio_codec = AV_CODEC_ID_MP2; + break; + case AUD_CODEC_MP3: +- m_outputFmt->audio_codec = AV_CODEC_ID_MP3; ++ audio_codec = AV_CODEC_ID_MP3; ++ break; ++ case AUD_CODEC_OPUS: ++ audio_codec = AV_CODEC_ID_OPUS; + break; + case AUD_CODEC_PCM: + switch(specs.format) + { + case AUD_FORMAT_U8: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_U8; ++ audio_codec = AV_CODEC_ID_PCM_U8; + break; + case AUD_FORMAT_S16: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_S16LE; ++ audio_codec = AV_CODEC_ID_PCM_S16LE; + break; + case AUD_FORMAT_S24: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_S24LE; ++ audio_codec = AV_CODEC_ID_PCM_S24LE; + break; + case AUD_FORMAT_S32: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_S32LE; ++ audio_codec = AV_CODEC_ID_PCM_S32LE; + break; + case AUD_FORMAT_FLOAT32: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_F32LE; ++ audio_codec = AV_CODEC_ID_PCM_F32LE; + break; + case AUD_FORMAT_FLOAT64: +- m_outputFmt->audio_codec = AV_CODEC_ID_PCM_F64LE; ++ audio_codec = AV_CODEC_ID_PCM_F64LE; + break; + default: +- m_outputFmt->audio_codec = AV_CODEC_ID_NONE; ++ audio_codec = AV_CODEC_ID_NONE; + break; + } + break; + case AUD_CODEC_VORBIS: +- m_outputFmt->audio_codec = AV_CODEC_ID_VORBIS; ++ audio_codec = AV_CODEC_ID_VORBIS; + break; + default: +- m_outputFmt->audio_codec = AV_CODEC_ID_NONE; ++ audio_codec = AV_CODEC_ID_NONE; ++ break; ++ } ++ ++ uint64_t channel_layout = 0; ++ ++ switch(m_specs.channels) ++ { ++ case AUD_CHANNELS_MONO: ++ channel_layout = AV_CH_LAYOUT_MONO; ++ break; ++ case AUD_CHANNELS_STEREO: ++ channel_layout = AV_CH_LAYOUT_STEREO; ++ break; ++ case AUD_CHANNELS_STEREO_LFE: ++ channel_layout = AV_CH_LAYOUT_2POINT1; ++ break; ++ case AUD_CHANNELS_SURROUND4: ++ channel_layout = AV_CH_LAYOUT_QUAD; ++ break; ++ case AUD_CHANNELS_SURROUND5: ++ channel_layout = AV_CH_LAYOUT_5POINT0_BACK; ++ break; ++ case AUD_CHANNELS_SURROUND51: ++ channel_layout = AV_CH_LAYOUT_5POINT1_BACK; ++ break; ++ case AUD_CHANNELS_SURROUND61: ++ channel_layout = AV_CH_LAYOUT_6POINT1_BACK; ++ break; ++ case AUD_CHANNELS_SURROUND71: ++ channel_layout = AV_CH_LAYOUT_7POINT1; + break; + } + + try + { +- if(m_outputFmt->audio_codec == AV_CODEC_ID_NONE) +- AUD_THROW(AUD_ERROR_SPECS, codec_error); ++ if(audio_codec == AV_CODEC_ID_NONE) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, audio codec not found with ffmpeg."); ++ ++ const AVCodec* codec = avcodec_find_encoder(audio_codec); ++ if(!codec) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, audio encoder couldn't be found with ffmpeg."); + +- m_stream = avformat_new_stream(m_formatCtx, NULL); ++ m_stream = avformat_new_stream(m_formatCtx, codec); + if(!m_stream) +- AUD_THROW(AUD_ERROR_FFMPEG, stream_error); ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, stream creation failed with ffmpeg."); + ++ m_stream->id = m_formatCtx->nb_streams - 1; ++ ++#ifdef FFMPEG_OLD_CODE + m_codecCtx = m_stream->codec; +- m_codecCtx->codec_id = m_outputFmt->audio_codec; +- m_codecCtx->codec_type = AVMEDIA_TYPE_AUDIO; +- m_codecCtx->bit_rate = bitrate; +- m_codecCtx->sample_rate = int(m_specs.rate); +- m_codecCtx->channels = m_specs.channels; +- m_codecCtx->time_base.num = 1; +- m_codecCtx->time_base.den = m_codecCtx->sample_rate; ++#else ++ m_codecCtx = avcodec_alloc_context3(codec); ++#endif ++ ++ if(!m_codecCtx) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, context creation failed with ffmpeg."); + + switch(m_specs.format) + { +@@ -148,133 +199,182 @@ AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, + m_convert = AUD_convert_float_s32; + m_codecCtx->sample_fmt = AV_SAMPLE_FMT_S32; + break; +- case AUD_FORMAT_FLOAT32: +- m_convert = AUD_convert_copy<float>; +- m_codecCtx->sample_fmt = AV_SAMPLE_FMT_FLT; +- break; + case AUD_FORMAT_FLOAT64: + m_convert = AUD_convert_float_double; + m_codecCtx->sample_fmt = AV_SAMPLE_FMT_DBL; + break; + default: +- AUD_THROW(AUD_ERROR_FFMPEG, format_error); ++ m_convert = AUD_convert_copy<sample_t>; ++ m_codecCtx->sample_fmt = AV_SAMPLE_FMT_FLT; ++ break; + } + +- try +- { +- if(m_formatCtx->oformat->flags & AVFMT_GLOBALHEADER) +- m_codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER; +- +- AVCodec* codec = avcodec_find_encoder(m_codecCtx->codec_id); +- if(!codec) +- AUD_THROW(AUD_ERROR_FFMPEG, codec_error); +- +- if(codec->sample_fmts) { +- // Check if the preferred sample format for this codec is supported. +- const enum AVSampleFormat *p = codec->sample_fmts; +- for(; *p != -1; p++) { +- if(*p == m_stream->codec->sample_fmt) +- break; +- } +- if(*p == -1) { +- // Sample format incompatible with codec. Defaulting to a format known to work. +- m_stream->codec->sample_fmt = codec->sample_fmts[0]; +- } +- } +- +- if(avcodec_open2(m_codecCtx, codec, NULL)) +- AUD_THROW(AUD_ERROR_FFMPEG, codec_error); ++ if(m_formatCtx->oformat->flags & AVFMT_GLOBALHEADER) ++ m_codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + +- m_output_buffer.resize(FF_MIN_BUFFER_SIZE); +- int samplesize = AUD_MAX(AUD_SAMPLE_SIZE(m_specs), AUD_DEVICE_SAMPLE_SIZE(m_specs)); ++ bool format_supported = false; + +- if(m_codecCtx->frame_size <= 1) { +- m_input_size = FF_MIN_BUFFER_SIZE * 8 / m_codecCtx->bits_per_coded_sample / m_codecCtx->channels; +- m_input_buffer.resize(m_input_size * samplesize); +- } +- else ++ for(int i = 0; codec->sample_fmts[i] != -1; i++) ++ { ++ if(av_get_alt_sample_fmt(codec->sample_fmts[i], false) == m_codecCtx->sample_fmt) + { +- m_input_buffer.resize(m_codecCtx->frame_size * samplesize); +- m_input_size = m_codecCtx->frame_size; ++ m_deinterleave = av_sample_fmt_is_planar(codec->sample_fmts[i]); ++ m_codecCtx->sample_fmt = codec->sample_fmts[i]; ++ format_supported = true; + } ++ } + +-#ifdef FFMPEG_HAVE_ENCODE_AUDIO2 +- m_frame = av_frame_alloc(); +- if (!m_frame) +- AUD_THROW(AUD_ERROR_FFMPEG, codec_error); +- av_frame_unref(m_frame); +- m_frame->linesize[0] = m_input_size * samplesize; +- m_frame->format = m_codecCtx->sample_fmt; +- m_frame->nb_samples = m_input_size; +-# ifdef FFMPEG_HAVE_AVFRAME_SAMPLE_RATE +- m_frame->sample_rate = m_codecCtx->sample_rate; +-# endif +-# ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT +- m_frame->channel_layout = m_codecCtx->channel_layout; +-# endif +- m_sample_size = av_get_bytes_per_sample(m_codecCtx->sample_fmt); +- m_frame_pts = 0; +- m_deinterleave = av_sample_fmt_is_planar(m_codecCtx->sample_fmt); +- if(m_deinterleave) +- m_deinterleave_buffer.resize(m_input_size * m_codecCtx->channels * m_sample_size); +-#endif +- +- try ++ if(!format_supported) ++ { ++ int chosen_index = 0; ++ auto chosen = av_get_alt_sample_fmt(codec->sample_fmts[chosen_index], false); ++ for(int i = 1; codec->sample_fmts[i] != -1; i++) + { +- if(avio_open(&m_formatCtx->pb, filename.c_str(), AVIO_FLAG_WRITE)) +- AUD_THROW(AUD_ERROR_FILE, file_error); +- +- if(avformat_write_header(m_formatCtx, NULL) < 0) { +- throw; ++ auto fmt = av_get_alt_sample_fmt(codec->sample_fmts[i], false); ++ if((fmt > chosen && chosen < m_codecCtx->sample_fmt) || (fmt > m_codecCtx->sample_fmt && fmt < chosen)) ++ { ++ chosen = fmt; ++ chosen_index = i; + } + } +- catch(AUD_Exception&) ++ ++ m_codecCtx->sample_fmt = codec->sample_fmts[chosen_index]; ++ m_deinterleave = av_sample_fmt_is_planar(m_codecCtx->sample_fmt); ++ switch(av_get_alt_sample_fmt(m_codecCtx->sample_fmt, false)) + { +- avcodec_close(m_codecCtx); +- av_freep(&m_formatCtx->streams[0]->codec); +- throw; ++ case AV_SAMPLE_FMT_U8: ++ specs.format = AUD_FORMAT_U8; ++ m_convert = AUD_convert_float_u8; ++ break; ++ case AV_SAMPLE_FMT_S16: ++ specs.format = AUD_FORMAT_S16; ++ m_convert = AUD_convert_float_s16; ++ break; ++ case AV_SAMPLE_FMT_S32: ++ specs.format = AUD_FORMAT_S32; ++ m_convert = AUD_convert_float_s32; ++ break; ++ case AV_SAMPLE_FMT_FLT: ++ specs.format = AUD_FORMAT_FLOAT32; ++ m_convert = AUD_convert_copy<sample_t>; ++ break; ++ case AV_SAMPLE_FMT_DBL: ++ specs.format = AUD_FORMAT_FLOAT64; ++ m_convert = AUD_convert_float_double; ++ break; ++ default: ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, sample format not supported with ffmpeg."); + } + } +- catch(AUD_Exception&) ++ ++ m_codecCtx->sample_rate = 0; ++ ++ if(codec->supported_samplerates) + { +- av_freep(&m_formatCtx->streams[0]); +- throw; ++ for(int i = 0; codec->supported_samplerates[i]; i++) ++ { ++ if(codec->supported_samplerates[i] == m_specs.rate) ++ { ++ m_codecCtx->sample_rate = codec->supported_samplerates[i]; ++ break; ++ } ++ else if((codec->supported_samplerates[i] > m_codecCtx->sample_rate && m_specs.rate > m_codecCtx->sample_rate) || ++ (codec->supported_samplerates[i] < m_codecCtx->sample_rate && m_specs.rate < codec->supported_samplerates[i])) ++ { ++ m_codecCtx->sample_rate = codec->supported_samplerates[i]; ++ } ++ } + } ++ ++ if(m_codecCtx->sample_rate == 0) ++ m_codecCtx->sample_rate = m_specs.rate; ++ ++ m_specs.rate = m_codecCtx->sample_rate; ++ ++#ifdef FFMPEG_OLD_CODE ++ m_codecCtx->codec_id = audio_codec; ++#endif ++ ++ m_codecCtx->codec_type = AVMEDIA_TYPE_AUDIO; ++ m_codecCtx->bit_rate = bitrate; ++ m_codecCtx->channel_layout = channel_layout; ++ m_codecCtx->channels = m_specs.channels; ++ m_stream->time_base.num = m_codecCtx->time_base.num = 1; ++ m_stream->time_base.den = m_codecCtx->time_base.den = m_codecCtx->sample_rate; ++ ++ if(avcodec_open2(m_codecCtx, codec, nullptr) < 0) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, encoder couldn't be opened with ffmpeg."); ++ ++#ifndef FFMPEG_OLD_CODE ++ if(avcodec_parameters_from_context(m_stream->codecpar, m_codecCtx) < 0) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, codec parameters couldn't be copied to the context."); ++#endif ++ ++ int samplesize = std::max(int(AUD_SAMPLE_SIZE(m_specs)), AUD_DEVICE_SAMPLE_SIZE(m_specs)); ++ ++ if((m_input_size = m_codecCtx->frame_size)) ++ m_input_buffer.resize(m_input_size * samplesize); ++ ++ if(avio_open(&m_formatCtx->pb, filename.c_str(), AVIO_FLAG_WRITE)) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, file opening failed with ffmpeg."); ++ ++ if(avformat_write_header(m_formatCtx, nullptr) < 0) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, writing the header failed."); + } + catch(AUD_Exception&) + { +- av_free(m_formatCtx); ++#ifndef FFMPEG_OLD_CODE ++ if(m_codecCtx) ++ avcodec_free_context(&m_codecCtx); ++#endif ++ avformat_free_context(m_formatCtx); + throw; + } ++ ++#ifdef FFMPEG_OLD_CODE ++ m_packet = new AVPacket({}); ++#else ++ m_packet = av_packet_alloc(); ++#endif ++ ++ m_frame = av_frame_alloc(); + } + + AUD_FFMPEGWriter::~AUD_FFMPEGWriter() + { + // writte missing data + if(m_input_samples) +- { +- sample_t* buf = m_input_buffer.getBuffer(); +- memset(buf + m_specs.channels * m_input_samples, 0, +- (m_input_size - m_input_samples) * AUD_DEVICE_SAMPLE_SIZE(m_specs)); ++ encode(); + +- encode(buf); +- } ++ close(); + + av_write_trailer(m_formatCtx); + +- avcodec_close(m_codecCtx); ++ if(m_frame) ++ av_frame_free(&m_frame); + +- av_freep(&m_formatCtx->streams[0]->codec); +- av_freep(&m_formatCtx->streams[0]); ++ if(m_packet) ++ { ++#ifdef FFMPEG_OLD_CODE ++ delete m_packet; ++#else ++ av_packet_free(&m_packet); ++#endif ++ } + +-#ifdef FFMPEG_HAVE_ENCODE_AUDIO2 +- av_frame_free(&m_frame); ++#ifdef FFMPEG_OLD_CODE ++ avcodec_close(m_codecCtx); ++#else ++ if(m_codecCtx) ++ avcodec_free_context(&m_codecCtx); + #endif + +- avio_close(m_formatCtx->pb); +- av_free(m_formatCtx); ++ avio_closep(&m_formatCtx->pb); ++ avformat_free_context(m_formatCtx); + } + ++ ++ + int AUD_FFMPEGWriter::getPosition() const + { + return m_position; +@@ -285,72 +385,130 @@ AUD_DeviceSpecs AUD_FFMPEGWriter::getSpecs() const + return m_specs; + } + +-void AUD_FFMPEGWriter::encode(sample_t* data) ++void AUD_FFMPEGWriter::encode() + { +- // convert first +- if(m_input_size) +- m_convert(reinterpret_cast<data_t*>(data), reinterpret_cast<data_t*>(data), m_input_size * m_specs.channels); ++ sample_t* data = m_input_buffer.getBuffer(); + +- AVPacket packet = { 0 }; +- av_init_packet(&packet); +- +-#ifdef FFMPEG_HAVE_ENCODE_AUDIO2 +- int got_output, ret; +- m_frame->pts = m_frame_pts / av_q2d(m_codecCtx->time_base); +- m_frame_pts++; +-#ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT +- m_frame->channel_layout = m_codecCtx->channel_layout; +-#endif ++ if(m_deinterleave) ++ { ++ m_deinterleave_buffer.assureSize(m_input_buffer.getSize()); + +- if(m_deinterleave) { +- for(int channel = 0; channel < m_codecCtx->channels; channel++) { +- for(int i = 0; i < m_frame->nb_samples; i++) { +- memcpy(reinterpret_cast<uint8_t*>(m_deinterleave_buffer.getBuffer()) + (i + channel * m_frame->nb_samples) * m_sample_size, +- reinterpret_cast<uint8_t*>(data) + (m_codecCtx->channels * i + channel) * m_sample_size, m_sample_size); ++ sample_t* dbuf = m_deinterleave_buffer.getBuffer(); ++ // deinterleave ++ int single_size = sizeof(sample_t); ++ for(int channel = 0; channel < m_specs.channels; channel++) ++ { ++ for(int i = 0; i < m_input_buffer.getSize() / AUD_SAMPLE_SIZE(m_specs); i++) ++ { ++ std::memcpy(((data_t*)dbuf) + (m_input_samples * channel + i) * single_size, ++ ((data_t*)data) + ((m_specs.channels * i) + channel) * single_size, single_size); + } + } + +- data = m_deinterleave_buffer.getBuffer(); ++ // convert first ++ if(m_input_size) ++ m_convert(reinterpret_cast<data_t*>(data), reinterpret_cast<data_t*>(dbuf), m_input_samples * m_specs.channels); ++ else ++ std::memcpy(data, dbuf, m_input_buffer.getSize()); + } ++ else ++ // convert first ++ if(m_input_size) ++ m_convert(reinterpret_cast<data_t*>(data), reinterpret_cast<data_t*>(data), m_input_samples * m_specs.channels); + +- avcodec_fill_audio_frame(m_frame, m_codecCtx->channels, m_codecCtx->sample_fmt, reinterpret_cast<uint8_t*>(data), +- m_frame->nb_samples * av_get_bytes_per_sample(m_codecCtx->sample_fmt) * m_codecCtx->channels, 1); ++#ifdef FFMPEG_OLD_CODE ++ m_packet->data = nullptr; ++ m_packet->size = 0; + +- ret = avcodec_encode_audio2(m_codecCtx, &packet, m_frame, &got_output); +- if(ret < 0) +- AUD_THROW(AUD_ERROR_FFMPEG, codec_error); ++ av_init_packet(m_packet); + +- if(!got_output) +- return; ++ av_frame_unref(m_frame); ++ int got_packet; ++#endif ++ ++ m_frame->nb_samples = m_input_samples; ++ m_frame->format = m_codecCtx->sample_fmt; ++ m_frame->channel_layout = m_codecCtx->channel_layout; ++ ++ if(avcodec_fill_audio_frame(m_frame, m_specs.channels, m_codecCtx->sample_fmt, reinterpret_cast<data_t*>(data), m_input_buffer.getSize(), 0) < 0) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, filling the audio frame failed with ffmpeg."); ++ ++ AVRational sample_time = { 1, static_cast<int>(m_specs.rate) }; ++ m_frame->pts = av_rescale_q(m_position - m_input_samples, m_codecCtx->time_base, sample_time); ++ ++#ifdef FFMPEG_OLD_CODE ++ if(avcodec_encode_audio2(m_codecCtx, m_packet, m_frame, &got_packet)) ++ { ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, audio encoding failed with ffmpeg."); ++ } ++ ++ if(got_packet) ++ { ++ m_packet->flags |= AV_PKT_FLAG_KEY; ++ m_packet->stream_index = m_stream->index; ++ if(av_write_frame(m_formatCtx, m_packet) < 0) ++ { ++ av_free_packet(m_packet); ++ AUD_THROW(AUD_ERROR_FILE, "Frame couldn't be writen to the file with ffmpeg."); ++ } ++ av_free_packet(m_packet); ++ } + #else +- sample_t* outbuf = m_output_buffer.getBuffer(); ++ if(avcodec_send_frame(m_codecCtx, m_frame) < 0) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, audio encoding failed with ffmpeg."); + +- packet.size = avcodec_encode_audio(m_codecCtx, reinterpret_cast<uint8_t*>(outbuf), m_output_buffer.getSize(), reinterpret_cast<short*>(data)); +- if(m_codecCtx->coded_frame && m_codecCtx->coded_frame->pts != AV_NOPTS_VALUE) +- packet.pts = av_rescale_q(m_codecCtx->coded_frame->pts, m_codecCtx->time_base, m_stream->time_base); +- packet.flags |= AV_PKT_FLAG_KEY; +- packet.data = reinterpret_cast<uint8_t*>(outbuf); ++ while(avcodec_receive_packet(m_codecCtx, m_packet) == 0) ++ { ++ m_packet->stream_index = m_stream->index; ++ ++ if(av_write_frame(m_formatCtx, m_packet) < 0) ++ AUD_THROW(AUD_ERROR_FILE, "Frame couldn't be writen to the file with ffmpeg."); ++ } + #endif ++} ++ ++void AUD_FFMPEGWriter::close() ++{ ++#ifdef FFMPEG_OLD_CODE ++ int got_packet = true; + +- if(packet.pts != AV_NOPTS_VALUE) +- packet.pts = av_rescale_q(packet.pts, m_codecCtx->time_base, m_stream->time_base); +- if(packet.dts != AV_NOPTS_VALUE) +- packet.dts = av_rescale_q(packet.dts, m_codecCtx->time_base, m_stream->time_base); +- if(packet.duration > 0) +- packet.duration = av_rescale_q(packet.duration, m_codecCtx->time_base, m_stream->time_base); ++ while(got_packet) ++ { ++ m_packet->data = nullptr; ++ m_packet->size = 0; + +- packet.stream_index = m_stream->index; ++ av_init_packet(m_packet); + +- packet.flags |= AV_PKT_FLAG_KEY; ++ if(avcodec_encode_audio2(m_codecCtx, m_packet, nullptr, &got_packet)) ++ AUD_THROW(AUD_ERROR_FILE, "File end couldn't be written, audio encoding failed with ffmpeg."); + +- if(av_interleaved_write_frame(m_formatCtx, &packet)) { +- av_free_packet(&packet); +- AUD_THROW(AUD_ERROR_FFMPEG, write_error); ++ if(got_packet) ++ { ++ m_packet->flags |= AV_PKT_FLAG_KEY; ++ m_packet->stream_index = m_stream->index; ++ if(av_write_frame(m_formatCtx, m_packet)) ++ { ++ av_free_packet(m_packet); ++ AUD_THROW(AUD_ERROR_FILE, "Final frames couldn't be writen to the file with ffmpeg."); ++ } ++ av_free_packet(m_packet); ++ } + } ++#else ++ if(avcodec_send_frame(m_codecCtx, nullptr) < 0) ++ AUD_THROW(AUD_ERROR_FILE, "File couldn't be written, audio encoding failed with ffmpeg."); ++ ++ while(avcodec_receive_packet(m_codecCtx, m_packet) == 0) ++ { ++ m_packet->stream_index = m_stream->index; + +- av_free_packet(&packet); ++ if(av_write_frame(m_formatCtx, m_packet) < 0) ++ AUD_THROW(AUD_ERROR_FILE, "Frame couldn't be writen to the file with ffmpeg."); ++ } ++#endif + } + ++ + void AUD_FFMPEGWriter::write(unsigned int length, sample_t* buffer) + { + unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs); +@@ -361,9 +519,9 @@ void AUD_FFMPEGWriter::write(unsigned int length, sample_t* buffer) + + while(length) + { +- unsigned int len = AUD_MIN(m_input_size - m_input_samples, length); ++ unsigned int len = std::min(m_input_size - m_input_samples, length); + +- memcpy(inbuf + m_input_samples * m_specs.channels, buffer, len * samplesize); ++ std::memcpy(inbuf + m_input_samples * m_specs.channels, buffer, len * samplesize); + + buffer += len * m_specs.channels; + m_input_samples += len; +@@ -372,7 +530,7 @@ void AUD_FFMPEGWriter::write(unsigned int length, sample_t* buffer) + + if(m_input_samples == m_input_size) + { +- encode(inbuf); ++ encode(); + + m_input_samples = 0; + } +@@ -381,15 +539,15 @@ void AUD_FFMPEGWriter::write(unsigned int length, sample_t* buffer) + else // PCM data, can write directly! + { + int samplesize = AUD_SAMPLE_SIZE(m_specs); +- if(m_output_buffer.getSize() != length * m_specs.channels * m_codecCtx->bits_per_coded_sample / 8) +- m_output_buffer.resize(length * m_specs.channels * m_codecCtx->bits_per_coded_sample / 8); +- m_input_buffer.assureSize(length * AUD_MAX(AUD_DEVICE_SAMPLE_SIZE(m_specs), samplesize)); ++ m_input_buffer.assureSize(length * std::max(AUD_DEVICE_SAMPLE_SIZE(m_specs), samplesize)); + + sample_t* buf = m_input_buffer.getBuffer(); + m_convert(reinterpret_cast<data_t*>(buf), reinterpret_cast<data_t*>(buffer), length * m_specs.channels); + +- encode(buf); ++ m_input_samples = length; + + m_position += length; ++ ++ encode(); + } + } +diff --git a/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h b/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h +index 492aa35..a77d250 100644 +--- a/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h ++++ b/blender-2.79b/intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h +@@ -68,19 +68,19 @@ private: + AVCodecContext* m_codecCtx; + + /** +- * The AVOutputFormat structure for using ffmpeg. ++ * The AVStream structure for using ffmpeg. + */ +- AVOutputFormat* m_outputFmt; ++ AVStream* m_stream; + + /** +- * The AVStream structure for using ffmpeg. ++ * The AVPacket structure for using ffmpeg. + */ +- AVStream* m_stream; ++ AVPacket* m_packet; + + /** +- * Frame sent to the encoder. ++ * The AVFrame structure for using ffmpeg. + */ +- AVFrame *m_frame; ++ AVFrame* m_frame; + + /** + * PTS of next frame to write. +@@ -132,7 +132,13 @@ private: + * Encodes to the output buffer. + * \param data Pointer to the data to encode. + */ +- void encode(sample_t* data); ++ void encode(); ++ ++ /** ++ * Finishes writing to the file. ++ */ ++ void close(); ++ + + public: + /** +diff --git a/blender-2.79b/intern/audaspace/intern/AUD_C-API.cpp b/blender-2.79b/intern/audaspace/intern/AUD_C-API.cpp +index 52cf256..ea2faae 100644 +--- a/blender-2.79b/intern/audaspace/intern/AUD_C-API.cpp ++++ b/blender-2.79b/intern/audaspace/intern/AUD_C-API.cpp +@@ -113,9 +113,6 @@ static AUD_I3DDevice *AUD_3ddevice; + + void AUD_initOnce() + { +-#ifdef WITH_FFMPEG +- av_register_all(); +-#endif + #ifdef WITH_JACK + AUD_jack_init(); + #endif +diff --git a/blender-2.79b/intern/audaspace/intern/AUD_Space.h b/blender-2.79b/intern/audaspace/intern/AUD_Space.h +index 26bbdc5..bda500b 100644 +--- a/blender-2.79b/intern/audaspace/intern/AUD_Space.h ++++ b/blender-2.79b/intern/audaspace/intern/AUD_Space.h +@@ -195,7 +195,8 @@ typedef enum + AUD_CODEC_MP2, + AUD_CODEC_MP3, + AUD_CODEC_PCM, +- AUD_CODEC_VORBIS ++ AUD_CODEC_VORBIS, ++ AUD_CODEC_OPUS + } AUD_Codec; + + /// Sample type.(float samples) +diff --git a/blender-2.79b/intern/ffmpeg/ffmpeg_compat.h b/blender-2.79b/intern/ffmpeg/ffmpeg_compat.h +index 9c06c8a..0e4bcbb 100644 +--- a/blender-2.79b/intern/ffmpeg/ffmpeg_compat.h ++++ b/blender-2.79b/intern/ffmpeg/ffmpeg_compat.h +@@ -23,9 +23,17 @@ + + #include <libavformat/avformat.h> + +-/* check our ffmpeg is new enough, avoids user complaints */ +-#if (LIBAVFORMAT_VERSION_MAJOR < 52) || ((LIBAVFORMAT_VERSION_MAJOR == 52) && (LIBAVFORMAT_VERSION_MINOR <= 64)) +-# error "FFmpeg 0.7 or newer is needed, Upgrade your FFmpeg or disable it" ++/* Check if our ffmpeg is new enough, avoids user complaints. ++ * Minimum supported version is currently 3.2.0 which mean the following library versions: ++ * libavutil > 55.30 ++ * libavcodec > 57.60 ++ * libavformat > 57.50 ++ * ++ * We only check for one of these as they are usually updated in tandem. ++ */ ++#if (LIBAVFORMAT_VERSION_MAJOR < 57) || \ ++ ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR <= 50)) ++# error "FFmpeg 3.2.0 or newer is needed, Upgrade your FFmpeg or disable it" + #endif + /* end sanity check */ + +@@ -36,214 +44,7 @@ + # define FFMPEG_INLINE static inline + #endif + +-#include <libavcodec/avcodec.h> +-#include <libavutil/rational.h> +-#include <libavutil/opt.h> +-#include <libavutil/mathematics.h> +- +-#if (LIBAVFORMAT_VERSION_MAJOR > 52) || ((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 101)) +-# define FFMPEG_HAVE_PARSE_UTILS 1 +-# include <libavutil/parseutils.h> +-#endif +- +-#include <libswscale/swscale.h> +- +-#if (LIBAVFORMAT_VERSION_MAJOR > 52) || ((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 105)) +-# define FFMPEG_HAVE_AVIO 1 +-#endif +- +-#if (LIBAVCODEC_VERSION_MAJOR > 53) || ((LIBAVCODEC_VERSION_MAJOR == 53) && (LIBAVCODEC_VERSION_MINOR > 1)) || ((LIBAVCODEC_VERSION_MAJOR == 53) && (LIBAVCODEC_VERSION_MINOR == 1) && (LIBAVCODEC_VERSION_MICRO >= 1)) || ((LIBAVCODEC_VERSION_MAJOR == 52) && (LIBAVCODEC_VERSION_MINOR >= 121)) +-# define FFMPEG_HAVE_DEFAULT_VAL_UNION 1 +-#endif +- +-#if (LIBAVFORMAT_VERSION_MAJOR > 52) || ((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 101)) +-# define FFMPEG_HAVE_AV_DUMP_FORMAT 1 +-#endif +- +-#if (LIBAVFORMAT_VERSION_MAJOR > 52) || ((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 45)) +-# define FFMPEG_HAVE_AV_GUESS_FORMAT 1 +-#endif +- +-#if (LIBAVCODEC_VERSION_MAJOR > 52) || ((LIBAVCODEC_VERSION_MAJOR >= 52) && (LIBAVCODEC_VERSION_MINOR >= 23)) +-# define FFMPEG_HAVE_DECODE_AUDIO3 1 +-# define FFMPEG_HAVE_DECODE_VIDEO2 1 +-#endif +- +-#if (LIBAVCODEC_VERSION_MAJOR > 52) || ((LIBAVCODEC_VERSION_MAJOR >= 52) && (LIBAVCODEC_VERSION_MINOR >= 64)) +-# define FFMPEG_HAVE_AVMEDIA_TYPES 1 +-#endif +- +-#if ((LIBAVCODEC_VERSION_MAJOR > 52) || (LIBAVCODEC_VERSION_MAJOR >= 52) && (LIBAVCODEC_VERSION_MINOR >= 29)) && \ +- ((LIBSWSCALE_VERSION_MAJOR > 0) || (LIBSWSCALE_VERSION_MAJOR >= 0) && (LIBSWSCALE_VERSION_MINOR >= 10)) +-# define FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT +-#endif +- +-#if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR > 14)) +-# define FFMPEG_HAVE_CANON_H264_RESOLUTION_FIX +-#endif +- +-#if ((LIBAVCODEC_VERSION_MAJOR > 53) || (LIBAVCODEC_VERSION_MAJOR >= 53) && (LIBAVCODEC_VERSION_MINOR >= 60)) +-# define FFMPEG_HAVE_ENCODE_AUDIO2 +-#endif +- +-#if ((LIBAVCODEC_VERSION_MAJOR > 53) || (LIBAVCODEC_VERSION_MAJOR >= 53) && (LIBAVCODEC_VERSION_MINOR >= 42)) +-# define FFMPEG_HAVE_DECODE_AUDIO4 +-#endif +- +-#if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR >= 13)) +-# define FFMPEG_HAVE_AVFRAME_SAMPLE_RATE +-#endif +- +-#if ((LIBAVUTIL_VERSION_MAJOR > 51) || (LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR >= 21)) +-# define FFMPEG_FFV1_ALPHA_SUPPORTED +-# define FFMPEG_SAMPLE_FMT_S16P_SUPPORTED +-#else +- +-FFMPEG_INLINE +-int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt) +-{ +- /* no planar formats in FFmpeg < 0.9 */ +- (void) sample_fmt; +- return 0; +-} +- +-#endif +- +-/* FFmpeg upstream 1.0 is the first who added AV_ prefix. */ +-#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100) +-# define AV_CODEC_ID_NONE CODEC_ID_NONE +-# define AV_CODEC_ID_MPEG4 CODEC_ID_MPEG4 +-# define AV_CODEC_ID_MJPEG CODEC_ID_MJPEG +-# define AV_CODEC_ID_DNXHD CODEC_ID_DNXHD +-# define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO +-# define AV_CODEC_ID_MPEG1VIDEO CODEC_ID_MPEG1VIDEO +-# define AV_CODEC_ID_DVVIDEO CODEC_ID_DVVIDEO +-# define AV_CODEC_ID_THEORA CODEC_ID_THEORA +-# define AV_CODEC_ID_PNG CODEC_ID_PNG +-# define AV_CODEC_ID_QTRLE CODEC_ID_QTRLE +-# define AV_CODEC_ID_FFV1 CODEC_ID_FFV1 +-# define AV_CODEC_ID_HUFFYUV CODEC_ID_HUFFYUV +-# define AV_CODEC_ID_H264 CODEC_ID_H264 +-# define AV_CODEC_ID_FLV1 CODEC_ID_FLV1 +- +-# define AV_CODEC_ID_AAC CODEC_ID_AAC +-# define AV_CODEC_ID_AC3 CODEC_ID_AC3 +-# define AV_CODEC_ID_MP3 CODEC_ID_MP3 +-# define AV_CODEC_ID_MP2 CODEC_ID_MP2 +-# define AV_CODEC_ID_FLAC CODEC_ID_FLAC +-# define AV_CODEC_ID_PCM_U8 CODEC_ID_PCM_U8 +-# define AV_CODEC_ID_PCM_S16LE CODEC_ID_PCM_S16LE +-# define AV_CODEC_ID_PCM_S24LE CODEC_ID_PCM_S24LE +-# define AV_CODEC_ID_PCM_S32LE CODEC_ID_PCM_S32LE +-# define AV_CODEC_ID_PCM_F32LE CODEC_ID_PCM_F32LE +-# define AV_CODEC_ID_PCM_F64LE CODEC_ID_PCM_F64LE +-# define AV_CODEC_ID_VORBIS CODEC_ID_VORBIS +-#endif +- +-FFMPEG_INLINE +-int av_get_cropped_height_from_codec(AVCodecContext *pCodecCtx) +-{ +- int y = pCodecCtx->height; +- +-#ifndef FFMPEG_HAVE_CANON_H264_RESOLUTION_FIX +-/* really bad hack to remove this dreadfull black bar at the bottom +- with Canon footage and old ffmpeg versions. +- (to fix this properly in older ffmpeg versions one has to write a new +- demuxer...) +- +- see the actual fix here for reference: +- +- http://git.libav.org/?p=libav.git;a=commit;h=30f515091c323da59c0f1b533703dedca2f4b95d +- +- We do our best to apply this only to matching footage. +-*/ +- if (pCodecCtx->width == 1920 && +- pCodecCtx->height == 1088 && +- pCodecCtx->pix_fmt == PIX_FMT_YUVJ420P && +- pCodecCtx->codec_id == AV_CODEC_ID_H264 ) { +- y = 1080; +- } +-#endif +- +- return y; +-} +- +-#if ((LIBAVUTIL_VERSION_MAJOR < 51) || (LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR < 22)) +-FFMPEG_INLINE +-int av_opt_set(void *obj, const char *name, const char *val, int search_flags) +-{ +- const AVOption *rv = NULL; +- (void) search_flags; +- av_set_string3(obj, name, val, 1, &rv); +- return rv != NULL; +-} +- +-FFMPEG_INLINE +-int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags) +-{ +- const AVOption *rv = NULL; +- (void) search_flags; +- rv = av_set_int(obj, name, val); +- return rv != NULL; +-} +- +-FFMPEG_INLINE +-int av_opt_set_double(void *obj, const char *name, double val, int search_flags) +-{ +- const AVOption *rv = NULL; +- (void) search_flags; +- rv = av_set_double(obj, name, val); +- return rv != NULL; +-} +- +-# define AV_OPT_TYPE_INT FF_OPT_TYPE_INT +-# define AV_OPT_TYPE_INT64 FF_OPT_TYPE_INT64 +-# define AV_OPT_TYPE_STRING FF_OPT_TYPE_STRING +-# define AV_OPT_TYPE_CONST FF_OPT_TYPE_CONST +-# define AV_OPT_TYPE_DOUBLE FF_OPT_TYPE_DOUBLE +-# define AV_OPT_TYPE_FLOAT FF_OPT_TYPE_FLOAT +-#endif +- +-#if ((LIBAVUTIL_VERSION_MAJOR < 51) || (LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR < 54)) +-FFMPEG_INLINE +-enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt) +-{ +- if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB) +- return AV_SAMPLE_FMT_NONE; +- return sample_fmt; +-} +-#endif +- +-#if ((LIBAVCODEC_VERSION_MAJOR < 53) || (LIBAVCODEC_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR < 35)) +-FFMPEG_INLINE +-int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options) +-{ +- /* TODO: no options are taking into account */ +- (void) options; +- return avcodec_open(avctx, codec); +-} +-#endif +- +-#if ((LIBAVFORMAT_VERSION_MAJOR < 53) || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR < 21)) +-FFMPEG_INLINE +-AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c) +-{ +- /* TODO: no codec is taking into account */ +- (void) c; +- return av_new_stream(s, 0); +-} +- +-FFMPEG_INLINE +-int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) +-{ +- /* TODO: no options are taking into account */ +- (void) options; +- return av_find_stream_info(ic); +-} +-#endif +- +-#if ((LIBAVFORMAT_VERSION_MAJOR > 53) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR > 32)) || ((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR == 24) && (LIBAVFORMAT_VERSION_MICRO >= 100))) +-FFMPEG_INLINE ++/*FFMPEG_INLINE + void my_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) + { + int i; +@@ -251,9 +52,9 @@ void my_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + +- st->cur_dts = av_rescale(timestamp, +- st->time_base.den * (int64_t)ref_st->time_base.num, +- st->time_base.num * (int64_t)ref_st->time_base.den); ++ st->internal->cur_dts = av_rescale(timestamp, ++ st->time_base.den * (int64_t)ref_st->time_base.num, ++ st->time_base.num * (int64_t)ref_st->time_base.den); + } + } + +@@ -261,101 +62,13 @@ FFMPEG_INLINE + void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) + { + my_update_cur_dts(s, ref_st, timestamp); +-} +-#endif +- +-#if ((LIBAVCODEC_VERSION_MAJOR < 54) || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR < 28)) +-FFMPEG_INLINE +-void avcodec_free_frame(AVFrame **frame) +-{ +- /* don't need to do anything with old AVFrame +- * since it does not have malloced members */ +- (void)frame; +-} +-#endif +- +-#if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR >= 13)) +-# define FFMPEG_HAVE_AVFRAME_SAMPLE_RATE +-#endif +- +-#if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 13)) +-# define FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT +-#endif +- +-#ifndef FFMPEG_HAVE_AVIO +-# define AVIO_FLAG_WRITE URL_WRONLY +-# define avio_open url_fopen +-# define avio_tell url_ftell +-# define avio_close url_fclose +-# define avio_size url_fsize +-#endif +- +-/* there are some version inbetween, which have avio_... functions but no +- * AVIO_FLAG_... */ +-#ifndef AVIO_FLAG_WRITE +-# define AVIO_FLAG_WRITE URL_WRONLY +-#endif +- +-#ifndef AV_PKT_FLAG_KEY +-# define AV_PKT_FLAG_KEY PKT_FLAG_KEY +-#endif +- +-#ifndef FFMPEG_HAVE_AV_DUMP_FORMAT +-# define av_dump_format dump_format +-#endif +- +-#ifndef FFMPEG_HAVE_AV_GUESS_FORMAT +-# define av_guess_format guess_format +-#endif +- +-#ifndef FFMPEG_HAVE_PARSE_UTILS +-# define av_parse_video_rate av_parse_video_frame_rate +-#endif +- +-#ifdef FFMPEG_HAVE_DEFAULT_VAL_UNION +-# define FFMPEG_DEF_OPT_VAL_INT(OPT) OPT->default_val.i64 +-# define FFMPEG_DEF_OPT_VAL_DOUBLE(OPT) OPT->default_val.dbl +-#else +-# define FFMPEG_DEF_OPT_VAL_INT(OPT) OPT->default_val +-# define FFMPEG_DEF_OPT_VAL_DOUBLE(OPT) OPT->default_val +-#endif +- +-#ifndef FFMPEG_HAVE_AVMEDIA_TYPES +-# define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO +-# define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO +-#endif +- +-#ifndef FFMPEG_HAVE_DECODE_AUDIO3 +-FFMPEG_INLINE +-int avcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples, +- int *frame_size_ptr, AVPacket *avpkt) +-{ +- return avcodec_decode_audio2(avctx, samples, +- frame_size_ptr, avpkt->data, +- avpkt->size); +-} +-#endif +- +-#ifndef FFMPEG_HAVE_DECODE_VIDEO2 +-FFMPEG_INLINE +-int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, +- int *got_picture_ptr, +- AVPacket *avpkt) +-{ +- return avcodec_decode_video(avctx, picture, got_picture_ptr, +- avpkt->data, avpkt->size); +-} +-#endif ++}*/ + + FFMPEG_INLINE + int64_t av_get_pts_from_frame(AVFormatContext *avctx, AVFrame * picture) + { + int64_t pts; +-#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 34, 100) + pts = picture->pts; +-#else +- pts = picture->pkt_pts; +-#endif + + if (pts == AV_NOPTS_VALUE) { + pts = picture->pkt_dts; +@@ -368,101 +81,7 @@ int64_t av_get_pts_from_frame(AVFormatContext *avctx, AVFrame * picture) + return pts; + } + +-/* obsolete constant formerly defined in FFMpeg libavcodec/avcodec.h */ +-#ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE +-# define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio +-#endif +- +-#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 1, 0) +-FFMPEG_INLINE +-int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *pkt, +- const AVFrame *frame, int *got_output) +-{ +- int outsize, ret; +- +- ret = av_new_packet(pkt, avctx->width * avctx->height * 7 + 10000); +- if (ret < 0) +- return ret; +- +- outsize = avcodec_encode_video(avctx, pkt->data, pkt->size, frame); +- if (outsize <= 0) { +- *got_output = 0; +- av_free_packet(pkt); +- } +- else { +- *got_output = 1; +- av_shrink_packet(pkt, outsize); +- if (avctx->coded_frame) { +- pkt->pts = avctx->coded_frame->pts; +- if (avctx->coded_frame->key_frame) +- pkt->flags |= AV_PKT_FLAG_KEY; +- } +- } +- +- return outsize >= 0 ? 0 : outsize; +-} +- +-#endif +- +-#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 17, 0) +-FFMPEG_INLINE +-void avformat_close_input(AVFormatContext **ctx) +-{ +- av_close_input_file(*ctx); +- *ctx = NULL; +-} +-#endif +- +-#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 8, 0) +-FFMPEG_INLINE +-AVFrame *av_frame_alloc(void) +-{ +- return avcodec_alloc_frame(); +-} +- +-FFMPEG_INLINE +-void av_frame_free(AVFrame **frame) +-{ +- av_freep(frame); +-} +-#endif +- +-FFMPEG_INLINE +-AVRational av_get_r_frame_rate_compat(const AVStream *stream) +-{ +-#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 23, 1) +- /* For until r_frame_rate was deprecated use it. */ +- return stream->r_frame_rate; +-#else +- return stream->avg_frame_rate; +-#endif +-} +- +-#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 32, 0) +-# define AV_OPT_SEARCH_FAKE_OBJ 0 +-#endif +- +-#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100) +-# define FFMPEG_HAVE_DEPRECATED_FLAGS2 +-#endif +- +-/* Since FFmpeg-1.1 this constant have AV_ prefix. */ +-#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 3, 100) +-# define AV_PIX_FMT_BGR32 PIX_FMT_BGR32 +-# define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P +-# define AV_PIX_FMT_BGRA PIX_FMT_BGRA +-# define AV_PIX_FMT_ARGB PIX_FMT_ARGB +-# define AV_PIX_FMT_RGBA PIX_FMT_RGBA +-#endif +- +-/* New API from FFmpeg-2.0 which soon became recommended one. */ +-#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 38, 100) +-# define av_frame_alloc avcodec_alloc_frame +-# define av_frame_free avcodec_free_frame +-# define av_frame_unref avcodec_get_frame_defaults +-#endif +- +-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 24, 102) ++/* --- Deinterlace code block begin --- */ + + /* NOTE: The code in this block are from FFmpeg 2.6.4, which is licensed by LGPL. */ + +@@ -586,8 +205,9 @@ int deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, + uint8_t *src_m1, *src_0, *src_p1, *src_p2; + int y; + uint8_t *buf = (uint8_t *)av_malloc(width); +- if (!buf) ++ if (!buf) { + return AVERROR(ENOMEM); ++ } + + src_m1 = src1; + memcpy(buf,src_m1,width); +@@ -607,14 +227,9 @@ int deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, + return 0; + } + +-#ifdef __GNUC__ +-# pragma GCC diagnostic push +-# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +-#endif +- + FFMPEG_INLINE +-int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, +- enum AVPixelFormat pix_fmt, int width, int height) ++int av_image_deinterlace( ++ AVFrame *dst, const AVFrame *src, enum AVPixelFormat pix_fmt, int width, int height) + { + int i, ret; + +@@ -624,10 +239,12 @@ int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, + pix_fmt != AV_PIX_FMT_YUVJ422P && + pix_fmt != AV_PIX_FMT_YUV444P && + pix_fmt != AV_PIX_FMT_YUV411P && +- pix_fmt != AV_PIX_FMT_GRAY8) ++ pix_fmt != AV_PIX_FMT_GRAY8) { + return -1; +- if ((width & 3) != 0 || (height & 3) != 0) ++ } ++ if ((width & 3) != 0 || (height & 3) != 0) { + return -1; ++ } + + for(i=0;i<3;i++) { + if (i == 1) { +@@ -655,8 +272,9 @@ int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, + ret = deinterlace_bottom_field_inplace(dst->data[i], + dst->linesize[i], + width, height); +- if (ret < 0) ++ if (ret < 0) { + return ret; ++ } + } else { + deinterlace_bottom_field(dst->data[i],dst->linesize[i], + src->data[i], src->linesize[i], +@@ -666,10 +284,6 @@ int avpicture_deinterlace(AVPicture *dst, const AVPicture *src, + return 0; + } + +-#ifdef __GNUC__ +-# pragma GCC diagnostic pop +-#endif +- +-#endif ++/* --- Deinterlace code block end --- */ + + #endif +diff --git a/blender-2.79b/source/blender/blenkernel/BKE_writeffmpeg.h b/blender-2.79b/source/blender/blenkernel/BKE_writeffmpeg.h +index a40c310..9a0d9ef 100644 +--- a/blender-2.79b/source/blender/blenkernel/BKE_writeffmpeg.h ++++ b/blender-2.79b/source/blender/blenkernel/BKE_writeffmpeg.h +@@ -76,12 +76,8 @@ void BKE_ffmpeg_filepath_get(char *string, struct RenderData *rd, bool preview, + + void BKE_ffmpeg_preset_set(struct RenderData *rd, int preset); + void BKE_ffmpeg_image_type_verify(struct RenderData *rd, struct ImageFormatData *imf); +-void BKE_ffmpeg_codec_settings_verify(struct RenderData *rd); + bool BKE_ffmpeg_alpha_channel_is_supported(struct RenderData *rd); + +-int BKE_ffmpeg_property_add_string(struct RenderData *rd, const char *type, const char *str); +-void BKE_ffmpeg_property_del(struct RenderData *rd, void *type, void *prop_); +- + void *BKE_ffmpeg_context_create(void); + void BKE_ffmpeg_context_free(void *context_v); + +diff --git a/blender-2.79b/source/blender/blenkernel/intern/scene.c b/blender-2.79b/source/blender/blenkernel/intern/scene.c +index 6fd53bb..bd428b2 100644 +--- a/blender-2.79b/source/blender/blenkernel/intern/scene.c ++++ b/blender-2.79b/source/blender/blenkernel/intern/scene.c +@@ -325,10 +325,6 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) + scen->r.qtcodecdata = MEM_dupallocN(sce->r.qtcodecdata); + scen->r.qtcodecdata->cdParms = MEM_dupallocN(scen->r.qtcodecdata->cdParms); + } +- +- if (sce->r.ffcodecdata.properties) { /* intentionally check scen not sce. */ +- scen->r.ffcodecdata.properties = IDP_CopyProperty(sce->r.ffcodecdata.properties); +- } + + /* NOTE: part of SCE_COPY_LINK_DATA and SCE_COPY_FULL operations + * are done outside of blenkernel with ED_objects_single_users! */ +@@ -424,11 +420,6 @@ void BKE_scene_free(Scene *sce) + MEM_freeN(sce->r.qtcodecdata); + sce->r.qtcodecdata = NULL; + } +- if (sce->r.ffcodecdata.properties) { +- IDP_FreeProperty(sce->r.ffcodecdata.properties); +- MEM_freeN(sce->r.ffcodecdata.properties); +- sce->r.ffcodecdata.properties = NULL; +- } + + for (srl = sce->r.layers.first; srl; srl = srl->next) { + if (srl->prop != NULL) { +diff --git a/blender-2.79b/source/blender/blenkernel/intern/writeffmpeg.c b/blender-2.79b/source/blender/blenkernel/intern/writeffmpeg.c +index a19e414..a32278d 100644 +--- a/blender-2.79b/source/blender/blenkernel/intern/writeffmpeg.c ++++ b/blender-2.79b/source/blender/blenkernel/intern/writeffmpeg.c +@@ -34,6 +34,9 @@ + + #include <libavformat/avformat.h> + #include <libavcodec/avcodec.h> ++#include <libavutil/channel_layout.h> ++#include <libavutil/imgutils.h> ++#include <libavutil/opt.h> + #include <libavutil/rational.h> + #include <libavutil/samplefmt.h> + #include <libswscale/swscale.h> +@@ -50,6 +53,7 @@ + #endif + + #include "BLI_utildefines.h" ++#include "BLI_threads.h" + + #include "BKE_global.h" + #include "BKE_idprop.h" +@@ -78,18 +82,19 @@ typedef struct FFMpegContext { + int ffmpeg_preset; /* see FFMpegPreset */ + + AVFormatContext *outfile; ++ AVCodecContext *video_codec; ++ AVCodecContext *audio_codec; + AVStream *video_stream; + AVStream *audio_stream; +- AVFrame *current_frame; ++ AVFrame *current_frame; /* Image frame in output pixel format. */ ++ ++ /* Image frame in Blender's own pixel format, may need conversion to the output pixel format. */ ++ AVFrame *img_convert_frame; + struct SwsContext *img_convert_ctx; + + uint8_t *audio_input_buffer; + uint8_t *audio_deinterleave_buffer; + int audio_input_samples; +-#ifndef FFMPEG_HAVE_ENCODE_AUDIO2 +- uint8_t *audio_output_buffer; +- int audio_outbuf_size; +-#endif + double audio_time; + bool audio_deinterleave; + int audio_sample_size; +@@ -104,8 +109,6 @@ typedef struct FFMpegContext { + #define PRINT if (G.debug & G_DEBUG_FFMPEG) printf + + static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value); +-static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float value); +-static void ffmpeg_set_expert_options(RenderData *rd); + static void ffmpeg_filepath_get(FFMpegContext *context, char *string, struct RenderData *rd, bool preview, const char *suffix); + + /* Delete a picture buffer */ +@@ -125,31 +128,20 @@ static int request_float_audio_buffer(int codec_id) + } + + #ifdef WITH_AUDASPACE ++ + static int write_audio_frame(FFMpegContext *context) + { +- AVCodecContext *c = NULL; +- AVPacket pkt; + AVFrame *frame = NULL; +- int got_output = 0; +- +- c = context->audio_stream->codec; +- +- av_init_packet(&pkt); +- pkt.size = 0; +- pkt.data = NULL; ++ AVCodecContext *c = context->audio_codec; + + AUD_Device_read(context->audio_mixdown_device, context->audio_input_buffer, context->audio_input_samples); + context->audio_time += (double) context->audio_input_samples / (double) c->sample_rate; + +-#ifdef FFMPEG_HAVE_ENCODE_AUDIO2 + frame = av_frame_alloc(); +- av_frame_unref(frame); + frame->pts = context->audio_time / av_q2d(c->time_base); + frame->nb_samples = context->audio_input_samples; + frame->format = c->sample_fmt; +-#ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT + frame->channel_layout = c->channel_layout; +-#endif + + if (context->audio_deinterleave) { + int channel, i; +@@ -170,53 +162,49 @@ static int write_audio_frame(FFMpegContext *context) + avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, context->audio_input_buffer, + context->audio_input_samples * c->channels * context->audio_sample_size, 1); + +- if (avcodec_encode_audio2(c, &pkt, frame, &got_output) < 0) { +- // XXX error("Error writing audio packet"); +- return -1; +- } ++ int success = 0; + +- if (!got_output) { +- av_frame_free(&frame); +- return 0; ++ int ret = avcodec_send_frame(c, frame); ++ if (ret < 0) { ++ /* Can't send frame to encoder. This shouldn't happen. */ ++ fprintf(stderr, "Can't send audio frame: %s\n", av_err2str(ret)); ++ success = -1; + } +-#else +- pkt.size = avcodec_encode_audio(c, context->audio_output_buffer, context->audio_outbuf_size, (short *) context->audio_input_buffer); + +- if (pkt.size < 0) { +- // XXX error("Error writing audio packet"); +- return -1; +- } ++ AVPacket *pkt = av_packet_alloc(); + +- pkt.data = context->audio_output_buffer; +- got_output = 1; +-#endif ++ while (ret >= 0) { + +- if (got_output) { +- if (pkt.pts != AV_NOPTS_VALUE) +- pkt.pts = av_rescale_q(pkt.pts, c->time_base, context->audio_stream->time_base); +- if (pkt.dts != AV_NOPTS_VALUE) +- pkt.dts = av_rescale_q(pkt.dts, c->time_base, context->audio_stream->time_base); +- if (pkt.duration > 0) +- pkt.duration = av_rescale_q(pkt.duration, c->time_base, context->audio_stream->time_base); ++ ret = avcodec_receive_packet(c, pkt); ++ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { ++ break; ++ } ++ if (ret < 0) { ++ fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret)); ++ success = -1; ++ } + +- pkt.stream_index = context->audio_stream->index; ++ av_packet_rescale_ts(pkt, c->time_base, context->audio_stream->time_base); ++ if (pkt->duration > 0) { ++ pkt->duration = av_rescale_q(pkt->duration, c->time_base, context->audio_stream->time_base); ++ } + +- pkt.flags |= AV_PKT_FLAG_KEY; ++ pkt->stream_index = context->audio_stream->index; + +- if (av_interleaved_write_frame(context->outfile, &pkt) != 0) { +- fprintf(stderr, "Error writing audio packet!\n"); +- if (frame) +- av_frame_free(&frame); +- return -1; +- } ++ pkt->flags |= AV_PKT_FLAG_KEY; + +- av_free_packet(&pkt); ++ int write_ret = av_interleaved_write_frame(context->outfile, pkt); ++ if (write_ret != 0) { ++ fprintf(stderr, "Error writing audio packet: %s\n", av_err2str(write_ret)); ++ success = -1; ++ break; ++ } + } + +- if (frame) +- av_frame_free(&frame); ++ av_packet_free(&pkt); ++ av_frame_free(&frame); + +- return 0; ++ return success; + } + #endif // #ifdef WITH_AUDASPACE + +@@ -229,15 +217,22 @@ static AVFrame *alloc_picture(int pix_fmt, int width, int height) + + /* allocate space for the struct */ + f = av_frame_alloc(); +- if (!f) return NULL; +- size = avpicture_get_size(pix_fmt, width, height); ++ if (!f) { ++ return NULL; ++ } ++ size = av_image_get_buffer_size(pix_fmt, width, height, 1); + /* allocate the actual picture buffer */ + buf = MEM_mallocN(size, "AVFrame buffer"); + if (!buf) { + free(f); + return NULL; + } +- avpicture_fill((AVPicture *)f, buf, pix_fmt, width, height); ++ ++ av_image_fill_arrays(f->data, f->linesize, buf, pix_fmt, width, height, 1); ++ f->format = pix_fmt; ++ f->width = width; ++ f->height = height; ++ + return f; + } + +@@ -310,225 +305,114 @@ static const char **get_file_extensions(int format) + } + + /* Write a frame to the output file */ +-static int write_video_frame(FFMpegContext *context, RenderData *rd, int cfra, AVFrame *frame, ReportList *reports) ++static int write_video_frame(FFMpegContext *context, int cfra, AVFrame *frame, ReportList *reports) + { +- int got_output; + int ret, success = 1; +- AVCodecContext *c = context->video_stream->codec; +- AVPacket packet = { 0 }; ++ AVPacket *packet = av_packet_alloc(); + +- av_init_packet(&packet); ++ AVCodecContext *c = context->video_codec; + + frame->pts = cfra; + +- if (rd->mode & R_FIELDS) { +- frame->top_field_first = ((rd->mode & R_ODDFIELD) != 0); ++ ret = avcodec_send_frame(c, frame); ++ if (ret < 0) { ++ /* Can't send frame to encoder. This shouldn't happen. */ ++ fprintf(stderr, "Can't send video frame: %s\n", av_err2str(ret)); ++ success = -1; + } + +- ret = avcodec_encode_video2(c, &packet, frame, &got_output); ++ while (ret >= 0) { ++ ret = avcodec_receive_packet(c, packet); + +- if (ret >= 0 && got_output) { +- if (packet.pts != AV_NOPTS_VALUE) { +- packet.pts = av_rescale_q(packet.pts, c->time_base, context->video_stream->time_base); +- PRINT("Video Frame PTS: %d\n", (int)packet.pts); +- } +- else { +- PRINT("Video Frame PTS: not set\n"); +- } +- if (packet.dts != AV_NOPTS_VALUE) { +- packet.dts = av_rescale_q(packet.dts, c->time_base, context->video_stream->time_base); +- PRINT("Video Frame DTS: %d\n", (int)packet.dts); ++ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { ++ /* No more packets available. */ ++ break; + } +- else { +- PRINT("Video Frame DTS: not set\n"); ++ if (ret < 0) { ++ fprintf(stderr, "Error encoding frame: %s\n", av_err2str(ret)); ++ break; + } + +- packet.stream_index = context->video_stream->index; +- ret = av_interleaved_write_frame(context->outfile, &packet); +- success = (ret == 0); ++ packet->stream_index = context->video_stream->index; ++ av_packet_rescale_ts(packet, c->time_base, context->video_stream->time_base); ++ if (av_interleaved_write_frame(context->outfile, packet) != 0) { ++ success = -1; ++ break; ++ } + } +- else if (ret < 0) { +- success = 0; ++ ++ if (!success) { ++ PRINT("Error writing frame: %s\n", av_err2str(ret)); + } + +- if (!success) +- BKE_report(reports, RPT_ERROR, "Error writing frame"); ++ av_packet_free(&packet); + + return success; + } + + /* read and encode a frame of audio from the buffer */ +-static AVFrame *generate_video_frame(FFMpegContext *context, uint8_t *pixels, ReportList *reports) ++static AVFrame *generate_video_frame(FFMpegContext *context, const uint8_t *pixels) + { +- uint8_t *rendered_frame; +- +- AVCodecContext *c = context->video_stream->codec; +- int width = c->width; +- int height = c->height; ++ AVCodecParameters *codec = context->video_stream->codecpar; ++ int height = codec->height; + AVFrame *rgb_frame; + +- if (c->pix_fmt != AV_PIX_FMT_BGR32) { +- rgb_frame = alloc_picture(AV_PIX_FMT_BGR32, width, height); +- if (!rgb_frame) { +- BKE_report(reports, RPT_ERROR, "Could not allocate temporary frame"); +- return NULL; +- } ++ if (context->img_convert_frame != NULL) { ++ /* Pixel format conversion is needed. */ ++ rgb_frame = context->img_convert_frame; + } + else { ++ /* The output pixel format is Blender's internal pixel format. */ + rgb_frame = context->current_frame; + } + +- rendered_frame = pixels; ++ /* Copy the Blender pixels into the FFmpeg datastructure, taking care of endianness and flipping ++ * the image vertically. */ ++ int linesize = rgb_frame->linesize[0]; ++ for (int y = 0; y < height; y++) { ++ uint8_t *target = rgb_frame->data[0] + linesize * (height - y - 1); ++ const uint8_t *src = pixels + linesize * y; + +- /* Do RGBA-conversion and flipping in one step depending +- * on CPU-Endianess */ ++# if ENDIAN_ORDER == L_ENDIAN ++ memcpy(target, src, linesize); + +- if (ENDIAN_ORDER == L_ENDIAN) { +- int y; +- for (y = 0; y < height; y++) { +- uint8_t *target = rgb_frame->data[0] + width * 4 * (height - y - 1); +- uint8_t *src = rendered_frame + width * 4 * y; +- uint8_t *end = src + width * 4; +- while (src != end) { +- target[3] = src[3]; +- target[2] = src[2]; +- target[1] = src[1]; +- target[0] = src[0]; ++# elif ENDIAN_ORDER == B_ENDIAN ++ const uint8_t *end = src + linesize; ++ while (src != end) { ++ target[3] = src[0]; ++ target[2] = src[1]; ++ target[1] = src[2]; ++ target[0] = src[3]; + +- target += 4; +- src += 4; +- } +- } +- } +- else { +- int y; +- for (y = 0; y < height; y++) { +- uint8_t *target = rgb_frame->data[0] + width * 4 * (height - y - 1); +- uint8_t *src = rendered_frame + width * 4 * y; +- uint8_t *end = src + width * 4; +- while (src != end) { +- target[3] = src[0]; +- target[2] = src[1]; +- target[1] = src[2]; +- target[0] = src[3]; +- +- target += 4; +- src += 4; +- } ++ target += 4; ++ src += 4; + } ++# else ++# error ENDIAN_ORDER should either be L_ENDIAN or B_ENDIAN. ++# endif + } + +- if (c->pix_fmt != AV_PIX_FMT_BGR32) { +- sws_scale(context->img_convert_ctx, (const uint8_t *const *) rgb_frame->data, +- rgb_frame->linesize, 0, c->height, +- context->current_frame->data, context->current_frame->linesize); +- delete_picture(rgb_frame); ++ /* Convert to the output pixel format, if it's different that Blender's internal one. */ ++ if (context->img_convert_frame != NULL) { ++ BLI_assert(context->img_convert_ctx != NULL); ++ sws_scale(context->img_convert_ctx, ++ (const uint8_t *const *)rgb_frame->data, ++ rgb_frame->linesize, ++ 0, ++ codec->height, ++ context->current_frame->data, ++ context->current_frame->linesize); + } + +- context->current_frame->format = AV_PIX_FMT_BGR32; +- context->current_frame->width = width; +- context->current_frame->height = height; +- + return context->current_frame; + } + +-static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop, AVDictionary **dictionary) +-{ +- char name[128]; +- char *param; +- +- PRINT("FFMPEG expert option: %s: ", prop->name); +- +- BLI_strncpy(name, prop->name, sizeof(name)); +- +- param = strchr(name, ':'); +- +- if (param) { +- *param++ = '\0'; +- } +- +- switch (prop->type) { +- case IDP_STRING: +- PRINT("%s.\n", IDP_String(prop)); +- av_dict_set(dictionary, name, IDP_String(prop), 0); +- break; +- case IDP_FLOAT: +- PRINT("%g.\n", IDP_Float(prop)); +- ffmpeg_dict_set_float(dictionary, prop->name, IDP_Float(prop)); +- break; +- case IDP_INT: +- PRINT("%d.\n", IDP_Int(prop)); +- +- if (param) { +- if (IDP_Int(prop)) { +- av_dict_set(dictionary, name, param, 0); +- } +- else { +- return; +- } +- } +- else { +- ffmpeg_dict_set_int(dictionary, prop->name, IDP_Int(prop)); +- } +- break; +- } +-} +- +-static int ffmpeg_proprty_valid(AVCodecContext *c, const char *prop_name, IDProperty *curr) +-{ +- int valid = 1; +- +- if (STREQ(prop_name, "video")) { +- if (STREQ(curr->name, "bf")) { +- /* flash codec doesn't support b frames */ +- valid &= c->codec_id != AV_CODEC_ID_FLV1; +- } +- } +- +- return valid; +-} +- +-static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char *prop_name, +- AVDictionary **dictionary) +-{ +- IDProperty *prop; +- IDProperty *curr; +- +- /* TODO(sergey): This is actually rather stupid, because changing +- * codec settings in render panel would also set expert options. +- * +- * But we need ti here in order to get rid of deprecated settings +- * when opening old files in new blender. +- * +- * For as long we don't allow editing properties in the interface +- * it's all good. bug if we allow editing them, we'll need to +- * replace it with some smarter code which would port settings +- * from deprecated to new one. +- */ +- ffmpeg_set_expert_options(rd); +- +- if (!rd->ffcodecdata.properties) { +- return; +- } +- +- prop = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, prop_name); +- if (!prop) { +- return; +- } +- +- for (curr = prop->data.group.first; curr; curr = curr->next) { +- if (ffmpeg_proprty_valid(c, prop_name, curr)) +- set_ffmpeg_property_option(c, curr, dictionary); +- } +-} +- + /* prepare a video stream for the output file */ + + static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int codec_id, AVFormatContext *of, + int rectx, int recty, char *error, int error_size) + { + AVStream *st; +- AVCodecContext *c; + AVCodec *codec; + AVDictionary *opts = NULL; + +@@ -539,13 +423,14 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int + st->id = 0; + + /* Set up the codec context */ +- +- c = st->codec; ++ ++ context->video_codec = avcodec_alloc_context3(NULL); ++ AVCodecContext *c = context->video_codec; + c->codec_id = codec_id; + c->codec_type = AVMEDIA_TYPE_VIDEO; + + /* Get some values from the current render settings */ +- ++ + c->width = rectx; + c->height = recty; + +@@ -605,12 +490,12 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int + c->rc_buffer_aggressivity = 1.0; + #endif + +- c->me_method = ME_EPZS; +- + codec = avcodec_find_encoder(c->codec_id); +- if (!codec) ++ if (!codec) { ++ avcodec_free_context(&c); + return NULL; +- ++ } ++ + /* Be sure to use the correct pixel format(e.g. RGB, YUV) */ + + if (codec->pix_fmts) { +@@ -643,6 +528,13 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int + } + } + ++ if (codec_id == AV_CODEC_ID_DNXHD) { ++ if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) { ++ /* Set the block decision algorithm to be of the highest quality ("rd" == 2). */ ++ c->mb_decision = 2; ++ } ++ } ++ + if (codec_id == AV_CODEC_ID_FFV1) { + c->pix_fmt = AV_PIX_FMT_RGB32; + } +@@ -668,14 +560,14 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int + ) + { + PRINT("Using global header\n"); +- c->flags |= CODEC_FLAG_GLOBAL_HEADER; ++ c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } + + /* Determine whether we are encoding interlaced material or not */ + if (rd->mode & R_FIELDS) { + PRINT("Encoding interlaced video\n"); +- c->flags |= CODEC_FLAG_INTERLACED_DCT; +- c->flags |= CODEC_FLAG_INTERLACED_ME; ++ c->flags |= AV_CODEC_FLAG_INTERLACED_DCT; ++ c->flags |= AV_CODEC_FLAG_INTERLACED_ME; + } + + /* xasp & yasp got float lately... */ +@@ -683,28 +575,46 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int + st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(((double) rd->xasp / (double) rd->yasp), 255); + st->avg_frame_rate = av_inv_q(c->time_base); + +- set_ffmpeg_properties(rd, c, "video", &opts); +- + if (avcodec_open2(c, codec, &opts) < 0) { + BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); + av_dict_free(&opts); ++ avcodec_free_context(&c); + return NULL; + } + av_dict_free(&opts); + ++ /* FFmpeg expects its data in the output pixel format. */ + context->current_frame = alloc_picture(c->pix_fmt, c->width, c->height); + +- context->img_convert_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_BGR32, c->width, c->height, c->pix_fmt, SWS_BICUBIC, +- NULL, NULL, NULL); ++ if (c->pix_fmt == AV_PIX_FMT_RGBA) { ++ /* Output pixel format is the same we use internally, no conversion necessary. */ ++ context->img_convert_frame = NULL; ++ context->img_convert_ctx = NULL; ++ } ++ else { ++ /* Output pixel format is different, allocate frame for conversion. */ ++ context->img_convert_frame = alloc_picture(AV_PIX_FMT_RGBA, c->width, c->height); ++ context->img_convert_ctx = sws_getContext(c->width, ++ c->height, ++ AV_PIX_FMT_RGBA, ++ c->width, ++ c->height, ++ c->pix_fmt, ++ SWS_BICUBIC, ++ NULL, ++ NULL, ++ NULL); ++ } ++ ++ avcodec_parameters_from_context(st->codecpar, c); ++ + return st; + } + + static AVStream *alloc_audio_stream(FFMpegContext *context, RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size) + { + AVStream *st; +- AVCodecContext *c; +- AVCodec *codec; +- AVDictionary *opts = NULL; ++ const AVCodec *codec; + + error[0] = '\0'; + +@@ -712,27 +622,47 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, RenderData *rd, int + if (!st) return NULL; + st->id = 1; + +- c = st->codec; +- c->codec_id = codec_id; +- c->codec_type = AVMEDIA_TYPE_AUDIO; ++ codec = avcodec_find_encoder(codec_id); ++ if (!codec) { ++ fprintf(stderr, "Couldn't find valid audio codec\n"); ++ context->audio_codec = NULL; ++ return NULL; ++ } ++ ++ context->audio_codec = avcodec_alloc_context3(codec); ++ AVCodecContext *c = context->audio_codec; ++ c->thread_count = BLI_system_thread_count(); ++ c->thread_type = FF_THREAD_SLICE; + + c->sample_rate = rd->ffcodecdata.audio_mixrate; + c->bit_rate = context->ffmpeg_audio_bitrate * 1000; + c->sample_fmt = AV_SAMPLE_FMT_S16; + c->channels = rd->ffcodecdata.audio_channels; + ++ switch (rd->ffcodecdata.audio_channels) { ++ case AUD_CHANNELS_MONO: ++ c->channel_layout = AV_CH_LAYOUT_MONO; ++ break; ++ case AUD_CHANNELS_STEREO: ++ c->channel_layout = AV_CH_LAYOUT_STEREO; ++ break; ++ case AUD_CHANNELS_SURROUND4: ++ c->channel_layout = AV_CH_LAYOUT_QUAD; ++ break; ++ case AUD_CHANNELS_SURROUND51: ++ c->channel_layout = AV_CH_LAYOUT_5POINT1_BACK; ++ break; ++ case AUD_CHANNELS_SURROUND71: ++ c->channel_layout = AV_CH_LAYOUT_7POINT1; ++ break; ++ } ++ + if (request_float_audio_buffer(codec_id)) { + /* mainly for AAC codec which is experimental */ + c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + c->sample_fmt = AV_SAMPLE_FMT_FLT; + } + +- codec = avcodec_find_encoder(c->codec_id); +- if (!codec) { +- //XXX error("Couldn't find a valid audio codec"); +- return NULL; +- } +- + if (codec->sample_fmts) { + /* check if the preferred sample format for this codec is supported. + * this is because, depending on the version of libav, and with the whole ffmpeg/libav fork situation, +@@ -740,12 +670,13 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, RenderData *rd, int + */ + const enum AVSampleFormat *p = codec->sample_fmts; + for (; *p != -1; p++) { +- if (*p == st->codec->sample_fmt) ++ if (*p == c->sample_fmt) { + break; ++ } + } + if (*p == -1) { + /* sample format incompatible with codec. Defaulting to a format known to work */ +- st->codec->sample_fmt = codec->sample_fmts[0]; ++ c->sample_fmt = codec->sample_fmts[0]; + } + } + +@@ -754,50 +685,40 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, RenderData *rd, int + int best = 0; + int best_dist = INT_MAX; + for (; *p; p++) { +- int dist = abs(st->codec->sample_rate - *p); ++ int dist = abs(c->sample_rate - *p); + if (dist < best_dist) { + best_dist = dist; + best = *p; + } + } + /* best is the closest supported sample rate (same as selected if best_dist == 0) */ +- st->codec->sample_rate = best; ++ c->sample_rate = best; + } + + if (of->oformat->flags & AVFMT_GLOBALHEADER) { +- c->flags |= CODEC_FLAG_GLOBAL_HEADER; ++ c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } + +- set_ffmpeg_properties(rd, c, "audio", &opts); +- +- if (avcodec_open2(c, codec, &opts) < 0) { ++ if (avcodec_open2(c, codec, NULL) < 0) { + //XXX error("Couldn't initialize audio codec"); + BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); +- av_dict_free(&opts); ++ avcodec_free_context(&c); ++ context->audio_codec = NULL; + return NULL; + } +- av_dict_free(&opts); + + /* need to prevent floating point exception when using vorbis audio codec, + * initialize this value in the same way as it's done in FFmpeg itself (sergey) */ +- st->codec->time_base.num = 1; +- st->codec->time_base.den = st->codec->sample_rate; +- +-#ifndef FFMPEG_HAVE_ENCODE_AUDIO2 +- context->audio_outbuf_size = FF_MIN_BUFFER_SIZE; +-#endif ++ c->time_base.num = 1; ++ c->time_base.den = c->sample_rate; + + if (c->frame_size == 0) + // used to be if ((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD)) + // not sure if that is needed anymore, so let's try out if there are any + // complaints regarding some ffmpeg versions users might have +- context->audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels; ++ context->audio_input_samples = AV_INPUT_BUFFER_MIN_SIZE * 8 / c->bits_per_coded_sample / c->channels; + else { + context->audio_input_samples = c->frame_size; +-#ifndef FFMPEG_HAVE_ENCODE_AUDIO2 +- if (c->frame_size * c->channels * sizeof(int16_t) * 4 > context->audio_outbuf_size) +- context->audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4; +-#endif + } + + context->audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt); +@@ -805,15 +726,14 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, RenderData *rd, int + context->audio_sample_size = av_get_bytes_per_sample(c->sample_fmt); + + context->audio_input_buffer = (uint8_t *) av_malloc(context->audio_input_samples * c->channels * context->audio_sample_size); +-#ifndef FFMPEG_HAVE_ENCODE_AUDIO2 +- context->audio_output_buffer = (uint8_t *) av_malloc(context->audio_outbuf_size); +-#endif + + if (context->audio_deinterleave) + context->audio_deinterleave_buffer = (uint8_t *) av_malloc(context->audio_input_samples * c->channels * context->audio_sample_size); + + context->audio_time = 0.0f; + ++ avcodec_parameters_from_context(st->codecpar, c); ++ + return st; + } + /* essential functions -- start, append, end */ +@@ -827,21 +747,11 @@ static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value) + av_dict_set(dict, key, buffer, 0); + } + +-static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float value) +-{ +- char buffer[32]; +- +- BLI_snprintf(buffer, sizeof(buffer), "%.8f", value); +- +- av_dict_set(dict, key, buffer, 0); +-} +- + static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int rectx, int recty, const char *suffix, ReportList *reports) + { + /* Handle to the output file */ + AVFormatContext *of; +- AVOutputFormat *fmt; +- AVDictionary *opts = NULL; ++ const AVOutputFormat *fmt; + char name[FILE_MAX], error[1024]; + const char **exts; + +@@ -869,12 +779,14 @@ static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int + name, context->ffmpeg_type, context->ffmpeg_codec, context->ffmpeg_audio_codec, + context->ffmpeg_video_bitrate, context->ffmpeg_audio_bitrate, + context->ffmpeg_gop_size, context->ffmpeg_autosplit, rectx, recty); +- ++ ++ /* Sanity checks for the output file extensions. */ + exts = get_file_extensions(context->ffmpeg_type); + if (!exts) { + BKE_report(reports, RPT_ERROR, "No valid formats found"); + return 0; + } ++ + fmt = av_guess_format(NULL, exts[0], NULL); + if (!fmt) { + BKE_report(reports, RPT_ERROR, "No valid formats found"); +@@ -883,67 +795,50 @@ static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int + + of = avformat_alloc_context(); + if (!of) { +- BKE_report(reports, RPT_ERROR, "Error opening output file"); ++ BKE_report(reports, RPT_ERROR, "Can't allocate ffmpeg format context"); + return 0; + } + ++ enum AVCodecID audio_codec = context->ffmpeg_audio_codec; ++ enum AVCodecID video_codec = context->ffmpeg_codec; + +- /* Returns after this must 'goto fail;' */ +- +- of->oformat = fmt; +- +- /* Only bother with setting packet size & mux rate when CRF is not used. */ +- if (context->ffmpeg_crf == 0) { +- of->packet_size = rd->ffcodecdata.mux_packet_size; +- if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) { +- ffmpeg_dict_set_int(&opts, "muxrate", rd->ffcodecdata.mux_rate); +- } +- else { +- av_dict_set(&opts, "muxrate", "0", 0); +- } +- } +- +- ffmpeg_dict_set_int(&opts, "preload", (int)(0.5 * AV_TIME_BASE)); +- +- of->max_delay = (int)(0.7 * AV_TIME_BASE); +- +- fmt->audio_codec = context->ffmpeg_audio_codec; +- +- BLI_strncpy(of->filename, name, sizeof(of->filename)); +- /* set the codec to the user's selection */ ++ of->url = av_strdup(name); ++ /* Check if we need to force change the codec because of file type codec restrictions */ + switch (context->ffmpeg_type) { +- case FFMPEG_AVI: +- case FFMPEG_MOV: +- case FFMPEG_MKV: +- fmt->video_codec = context->ffmpeg_codec; +- break; + case FFMPEG_OGG: +- fmt->video_codec = AV_CODEC_ID_THEORA; ++ video_codec = AV_CODEC_ID_THEORA; + break; + case FFMPEG_DV: +- fmt->video_codec = AV_CODEC_ID_DVVIDEO; ++ video_codec = AV_CODEC_ID_DVVIDEO; + break; + case FFMPEG_MPEG1: +- fmt->video_codec = AV_CODEC_ID_MPEG1VIDEO; ++ video_codec = AV_CODEC_ID_MPEG1VIDEO; + break; + case FFMPEG_MPEG2: +- fmt->video_codec = AV_CODEC_ID_MPEG2VIDEO; ++ video_codec = AV_CODEC_ID_MPEG2VIDEO; + break; + case FFMPEG_H264: +- fmt->video_codec = AV_CODEC_ID_H264; ++ video_codec = AV_CODEC_ID_H264; + break; + case FFMPEG_XVID: +- fmt->video_codec = AV_CODEC_ID_MPEG4; ++ video_codec = AV_CODEC_ID_MPEG4; + break; + case FFMPEG_FLV: +- fmt->video_codec = AV_CODEC_ID_FLV1; ++ video_codec = AV_CODEC_ID_FLV1; + break; +- case FFMPEG_MPEG4: + default: +- fmt->video_codec = context->ffmpeg_codec; ++ /* These containers are not restricted to any specific codec types. ++ * Currently we expect these to be .avi, .mov, .mkv, and .mp4. ++ */ ++ video_codec = context->ffmpeg_codec; + break; + } +- if (fmt->video_codec == AV_CODEC_ID_DVVIDEO) { ++ ++ /* Returns after this must 'goto fail;' */ ++ ++ of->oformat = fmt; ++ ++ if (video_codec == AV_CODEC_ID_DVVIDEO) { + if (rectx != 720) { + BKE_report(reports, RPT_ERROR, "Render width has to be 720 pixels for DV!"); + goto fail; +@@ -957,51 +852,62 @@ static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int + goto fail; + } + } +- ++ + if (context->ffmpeg_type == FFMPEG_DV) { +- fmt->audio_codec = AV_CODEC_ID_PCM_S16LE; ++ audio_codec = AV_CODEC_ID_PCM_S16LE; + if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) { + BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!"); + goto fail; + } + } + +- if (fmt->video_codec != AV_CODEC_ID_NONE) { +- context->video_stream = alloc_video_stream(context, rd, fmt->video_codec, of, rectx, recty, error, sizeof(error)); ++ if (video_codec != AV_CODEC_ID_NONE) { ++ context->video_stream = alloc_video_stream(context, rd, video_codec, of, rectx, recty, error, sizeof(error)); + PRINT("alloc video stream %p\n", context->video_stream); + if (!context->video_stream) { +- if (error[0]) ++ if (error[0]) { + BKE_report(reports, RPT_ERROR, error); +- else ++ PRINT("Video stream error: %s\n", error); ++ } ++ else { + BKE_report(reports, RPT_ERROR, "Error initializing video stream"); ++ PRINT("Error initializing video stream"); ++ } + goto fail; + } + } + + if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) { +- context->audio_stream = alloc_audio_stream(context, rd, fmt->audio_codec, of, error, sizeof(error)); ++ context->audio_stream = alloc_audio_stream(context, rd, audio_codec, of, error, sizeof(error)); + if (!context->audio_stream) { +- if (error[0]) ++ if (error[0]) { + BKE_report(reports, RPT_ERROR, error); +- else ++ PRINT("Audio stream error: %s\n", error); ++ } ++ else { + BKE_report(reports, RPT_ERROR, "Error initializing audio stream"); ++ PRINT("Error initializing audio stream"); ++ } + goto fail; + } + } + if (!(fmt->flags & AVFMT_NOFILE)) { + if (avio_open(&of->pb, name, AVIO_FLAG_WRITE) < 0) { + BKE_report(reports, RPT_ERROR, "Could not open file for writing"); ++ PRINT("Could not open file for writing\n"); + goto fail; + } + } +- if (avformat_write_header(of, NULL) < 0) { ++ ++ int ret = avformat_write_header(of, NULL); ++ if (ret < 0) { + BKE_report(reports, RPT_ERROR, "Could not initialize streams, probably unsupported codec combination"); ++ PRINT("Could not write media header: %s\n", av_err2str(ret)); + goto fail; + } + + context->outfile = of; + av_dump_format(of, 0, name, 1); +- av_dict_free(&opts); + + return 1; + +@@ -1011,17 +917,14 @@ fail: + avio_close(of->pb); + } + +- if (context->video_stream && context->video_stream->codec) { +- avcodec_close(context->video_stream->codec); ++ if (context->video_stream) { + context->video_stream = NULL; + } + +- if (context->audio_stream && context->audio_stream->codec) { +- avcodec_close(context->audio_stream->codec); ++ if (context->audio_stream) { + context->audio_stream = NULL; + } + +- av_dict_free(&opts); + avformat_free_context(of); + return 0; + } +@@ -1045,46 +948,35 @@ fail: + */ + static void flush_ffmpeg(FFMpegContext *context) + { +- int ret = 0; +- +- AVCodecContext *c = context->video_stream->codec; +- /* get the delayed frames */ +- while (1) { +- int got_output; +- AVPacket packet = { 0 }; +- av_init_packet(&packet); +- +- ret = avcodec_encode_video2(c, &packet, NULL, &got_output); +- if (ret < 0) { +- fprintf(stderr, "Error encoding delayed frame %d\n", ret); ++ AVCodecContext *c = context->video_codec; ++ AVPacket *packet = av_packet_alloc(); ++ ++ avcodec_send_frame(c, NULL); ++ /* Get the packets frames. */ ++ int ret = 1; ++ while (ret >= 0) { ++ ret = avcodec_receive_packet(c, packet); ++ ++ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { ++ /* No more packets to flush. */ + break; + } +- if (!got_output) { ++ if (ret < 0) { ++ fprintf(stderr, "Error encoding delayed frame: %s\n", av_err2str(ret)); + break; + } +- if (packet.pts != AV_NOPTS_VALUE) { +- packet.pts = av_rescale_q(packet.pts, c->time_base, context->video_stream->time_base); +- PRINT("Video Frame PTS: %d\n", (int) packet.pts); +- } +- else { +- PRINT("Video Frame PTS: not set\n"); +- } +- if (packet.dts != AV_NOPTS_VALUE) { +- packet.dts = av_rescale_q(packet.dts, c->time_base, context->video_stream->time_base); +- PRINT("Video Frame DTS: %d\n", (int) packet.dts); +- } +- else { +- PRINT("Video Frame DTS: not set\n"); +- } + +- packet.stream_index = context->video_stream->index; +- ret = av_interleaved_write_frame(context->outfile, &packet); +- if (ret != 0) { +- fprintf(stderr, "Error writing delayed frame %d\n", ret); ++ packet->stream_index = context->video_stream->index; ++ av_packet_rescale_ts(packet, c->time_base, context->video_stream->time_base); ++ ++ int write_ret = av_interleaved_write_frame(context->outfile, packet); ++ if (write_ret != 0) { ++ fprintf(stderr, "Error writing delayed frame: %s\n", av_err2str(write_ret)); + break; + } + } +- avcodec_flush_buffers(context->video_stream->codec); ++ ++ av_packet_free(&packet); + } + + /* ********************************************************************** +@@ -1172,7 +1064,8 @@ int BKE_ffmpeg_start(void *context_v, struct Scene *scene, RenderData *rd, int r + success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports); + #ifdef WITH_AUDASPACE + if (context->audio_stream) { +- AVCodecContext *c = context->audio_stream->codec; ++ AVCodecContext *c = context->audio_codec; ++ + AUD_DeviceSpecs specs; + specs.channels = c->channels; + +@@ -1198,10 +1091,6 @@ int BKE_ffmpeg_start(void *context_v, struct Scene *scene, RenderData *rd, int r + + specs.rate = rd->ffcodecdata.audio_mixrate; + context->audio_mixdown_device = BKE_sound_mixdown(scene, specs, preview ? rd->psfra : rd->sfra, rd->ffcodecdata.audio_volume); +-#ifdef FFMPEG_CODEC_TIME_BASE +- c->time_base.den = specs.rate; +- c->time_base.num = 1; +-#endif + } + #endif + return success; +@@ -1237,8 +1126,8 @@ int BKE_ffmpeg_append(void *context_v, RenderData *rd, int start_frame, int fram + // write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base)); + + if (context->video_stream) { +- avframe = generate_video_frame(context, (unsigned char *) pixels, reports); +- success = (avframe && write_video_frame(context, rd, frame - start_frame, avframe, reports)); ++ avframe = generate_video_frame(context, (unsigned char *)pixels); ++ success = (avframe && write_video_frame(context, frame - start_frame, avframe, reports)); + + if (context->ffmpeg_autosplit) { + if (avio_tell(context->outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) { +@@ -1274,7 +1163,7 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit) + } + #endif + +- if (context->video_stream && context->video_stream->codec) { ++ if (context->video_stream) { + PRINT("Flushing delayed frames...\n"); + flush_ffmpeg(context); + } +@@ -1285,14 +1174,12 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit) + + /* Close the video codec */ + +- if (context->video_stream != NULL && context->video_stream->codec != NULL) { +- avcodec_close(context->video_stream->codec); ++ if (context->video_stream != NULL) { + PRINT("zero video stream %p\n", context->video_stream); + context->video_stream = NULL; + } + +- if (context->audio_stream != NULL && context->audio_stream->codec != NULL) { +- avcodec_close(context->audio_stream->codec); ++ if (context->audio_stream != NULL) { + context->audio_stream = NULL; + } + +@@ -1306,20 +1193,30 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit) + avio_close(context->outfile->pb); + } + } ++ ++ if (context->video_codec != NULL) { ++ avcodec_free_context(&context->video_codec); ++ context->video_codec = NULL; ++ } ++ if (context->audio_codec != NULL) { ++ avcodec_free_context(&context->audio_codec); ++ context->audio_codec = NULL; ++ } ++ ++ if (context->img_convert_frame != NULL) { ++ delete_picture(context->img_convert_frame); ++ context->img_convert_frame = NULL; ++ } ++ + if (context->outfile != NULL) { + avformat_free_context(context->outfile); + context->outfile = NULL; + } ++ + if (context->audio_input_buffer != NULL) { + av_free(context->audio_input_buffer); + context->audio_input_buffer = NULL; + } +-#ifndef FFMPEG_HAVE_ENCODE_AUDIO2 +- if (context->audio_output_buffer != NULL) { +- av_free(context->audio_output_buffer); +- context->audio_output_buffer = NULL; +- } +-#endif + + if (context->audio_deinterleave_buffer != NULL) { + av_free(context->audio_deinterleave_buffer); +@@ -1338,235 +1235,17 @@ void BKE_ffmpeg_end(void *context_v) + end_ffmpeg_impl(context, false); + } + +-/* properties */ +- +-void BKE_ffmpeg_property_del(RenderData *rd, void *type, void *prop_) +-{ +- struct IDProperty *prop = (struct IDProperty *) prop_; +- IDProperty *group; +- +- if (!rd->ffcodecdata.properties) { +- return; +- } +- +- group = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, type); +- if (group && prop) { +- IDP_FreeFromGroup(group, prop); +- } +-} +- +-static IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, const AVOption *o, const AVOption *parent) +-{ +- AVCodecContext c; +- IDProperty *group; +- IDProperty *prop; +- IDPropertyTemplate val; +- int idp_type; +- char name[256]; +- +- val.i = 0; +- +- avcodec_get_context_defaults3(&c, NULL); +- +- if (!rd->ffcodecdata.properties) { +- rd->ffcodecdata.properties = IDP_New(IDP_GROUP, &val, "ffmpeg"); +- } +- +- group = IDP_GetPropertyFromGroup(rd->ffcodecdata.properties, type); +- +- if (!group) { +- group = IDP_New(IDP_GROUP, &val, type); +- IDP_AddToGroup(rd->ffcodecdata.properties, group); +- } +- +- if (parent) { +- BLI_snprintf(name, sizeof(name), "%s:%s", parent->name, o->name); +- } +- else { +- BLI_strncpy(name, o->name, sizeof(name)); +- } +- +- PRINT("ffmpeg_property_add: %s %s\n", type, name); +- +- prop = IDP_GetPropertyFromGroup(group, name); +- if (prop) { +- return prop; +- } +- +- switch (o->type) { +- case AV_OPT_TYPE_INT: +- case AV_OPT_TYPE_INT64: +- val.i = FFMPEG_DEF_OPT_VAL_INT(o); +- idp_type = IDP_INT; +- break; +- case AV_OPT_TYPE_DOUBLE: +- case AV_OPT_TYPE_FLOAT: +- val.f = FFMPEG_DEF_OPT_VAL_DOUBLE(o); +- idp_type = IDP_FLOAT; +- break; +- case AV_OPT_TYPE_STRING: +- val.string.str = (char *)" "; +- val.string.len = 80; +-/* val.str = (char *)" ";*/ +- idp_type = IDP_STRING; +- break; +- case AV_OPT_TYPE_CONST: +- val.i = 1; +- idp_type = IDP_INT; +- break; +- default: +- return NULL; +- } +- prop = IDP_New(idp_type, &val, name); +- IDP_AddToGroup(group, prop); +- return prop; +-} +- +-/* not all versions of ffmpeg include that, so here we go ... */ +- +-int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char *str) +-{ +- AVCodecContext c; +- const AVOption *o = NULL; +- const AVOption *p = NULL; +- char name_[128]; +- char *name; +- char *param; +- IDProperty *prop = NULL; +- +- avcodec_get_context_defaults3(&c, NULL); +- +- BLI_strncpy(name_, str, sizeof(name_)); +- +- name = name_; +- while (*name == ' ') name++; +- +- param = strchr(name, ':'); +- +- if (!param) { +- param = strchr(name, ' '); +- } +- if (param) { +- *param++ = '\0'; +- while (*param == ' ') param++; +- } +- +- o = av_opt_find(&c, name, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ); +- if (!o) { +- PRINT("Ignoring unknown expert option %s\n", str); +- return 0; +- } +- if (param && o->type == AV_OPT_TYPE_CONST) { +- return 0; +- } +- if (param && o->type != AV_OPT_TYPE_CONST && o->unit) { +- p = av_opt_find(&c, param, o->unit, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ); +- if (p) { +- prop = BKE_ffmpeg_property_add(rd, (char *) type, p, o); +- } +- else { +- PRINT("Ignoring unknown expert option %s\n", str); +- } +- } +- else { +- prop = BKE_ffmpeg_property_add(rd, (char *) type, o, NULL); +- } +- +- +- if (!prop) { +- return 0; +- } +- +- if (param && !p) { +- switch (prop->type) { +- case IDP_INT: +- IDP_Int(prop) = atoi(param); +- break; +- case IDP_FLOAT: +- IDP_Float(prop) = atof(param); +- break; +- case IDP_STRING: +- strncpy(IDP_String(prop), param, prop->len); +- break; +- } +- } +- return 1; +-} +- +-static void ffmpeg_set_expert_options(RenderData *rd) +-{ +- int codec_id = rd->ffcodecdata.codec; +- +- if (rd->ffcodecdata.properties) +- IDP_FreeProperty(rd->ffcodecdata.properties); +- +- if (codec_id == AV_CODEC_ID_H264) { +- /* +- * All options here are for x264, but must be set via ffmpeg. +- * The names are therefore different - Search for "x264 to FFmpeg option mapping" +- * to get a list. +- */ +- +- /* +- * Use CABAC coder. Using "coder:1", which should be equivalent, +- * crashes Blender for some reason. Either way - this is no big deal. +- */ +- BKE_ffmpeg_property_add_string(rd, "video", "coder:vlc"); +- +- /* +- * The other options were taken from the libx264-default.preset +- * included in the ffmpeg distribution. +- */ +-// ffmpeg_property_add_string(rd, "video", "flags:loop"); // this breaks compatibility for QT +- BKE_ffmpeg_property_add_string(rd, "video", "cmp:chroma"); +- BKE_ffmpeg_property_add_string(rd, "video", "partitions:parti4x4"); // Deprecated. +- BKE_ffmpeg_property_add_string(rd, "video", "partitions:partp8x8"); // Deprecated. +- BKE_ffmpeg_property_add_string(rd, "video", "partitions:partb8x8"); // Deprecated. +- BKE_ffmpeg_property_add_string(rd, "video", "me:hex"); +- BKE_ffmpeg_property_add_string(rd, "video", "subq:6"); +- BKE_ffmpeg_property_add_string(rd, "video", "me_range:16"); +- BKE_ffmpeg_property_add_string(rd, "video", "qdiff:4"); +- BKE_ffmpeg_property_add_string(rd, "video", "keyint_min:25"); +- BKE_ffmpeg_property_add_string(rd, "video", "sc_threshold:40"); +- BKE_ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71"); +- BKE_ffmpeg_property_add_string(rd, "video", "b_strategy:1"); +- BKE_ffmpeg_property_add_string(rd, "video", "bf:3"); +- BKE_ffmpeg_property_add_string(rd, "video", "refs:2"); +- BKE_ffmpeg_property_add_string(rd, "video", "qcomp:0.6"); +- +- BKE_ffmpeg_property_add_string(rd, "video", "trellis:0"); +- BKE_ffmpeg_property_add_string(rd, "video", "weightb:1"); +-#ifdef FFMPEG_HAVE_DEPRECATED_FLAGS2 +- BKE_ffmpeg_property_add_string(rd, "video", "flags2:dct8x8"); +- BKE_ffmpeg_property_add_string(rd, "video", "directpred:3"); +- BKE_ffmpeg_property_add_string(rd, "video", "flags2:fastpskip"); +- BKE_ffmpeg_property_add_string(rd, "video", "flags2:wpred"); +-#else +- BKE_ffmpeg_property_add_string(rd, "video", "8x8dct:1"); +- BKE_ffmpeg_property_add_string(rd, "video", "fast-pskip:1"); +- BKE_ffmpeg_property_add_string(rd, "video", "wpredp:2"); +-#endif +- } +- else if (codec_id == AV_CODEC_ID_DNXHD) { +- if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) +- BKE_ffmpeg_property_add_string(rd, "video", "mbd:rd"); +- } +-} +- + void BKE_ffmpeg_preset_set(RenderData *rd, int preset) + { +- int isntsc = (rd->frs_sec != 25); +- +- if (rd->ffcodecdata.properties) +- IDP_FreeProperty(rd->ffcodecdata.properties); ++ bool is_ntsc = (rd->frs_sec != 25); + + switch (preset) { + case FFMPEG_PRESET_VCD: + rd->ffcodecdata.type = FFMPEG_MPEG1; + rd->ffcodecdata.video_bitrate = 1150; + rd->xsch = 352; +- rd->ysch = isntsc ? 240 : 288; +- rd->ffcodecdata.gop_size = isntsc ? 18 : 15; ++ rd->ysch = is_ntsc ? 240 : 288; ++ rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 1150; + rd->ffcodecdata.rc_min_rate = 1150; + rd->ffcodecdata.rc_buffer_size = 40 * 8; +@@ -1578,8 +1257,8 @@ void BKE_ffmpeg_preset_set(RenderData *rd, int preset) + rd->ffcodecdata.type = FFMPEG_MPEG2; + rd->ffcodecdata.video_bitrate = 2040; + rd->xsch = 480; +- rd->ysch = isntsc ? 480 : 576; +- rd->ffcodecdata.gop_size = isntsc ? 18 : 15; ++ rd->ysch = is_ntsc ? 480 : 576; ++ rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 2516; + rd->ffcodecdata.rc_min_rate = 0; + rd->ffcodecdata.rc_buffer_size = 224 * 8; +@@ -1593,9 +1272,9 @@ void BKE_ffmpeg_preset_set(RenderData *rd, int preset) + + /* Don't set resolution, see [#21351] + * rd->xsch = 720; +- * rd->ysch = isntsc ? 480 : 576; */ ++ * rd->ysch = is_ntsc ? 480 : 576; */ + +- rd->ffcodecdata.gop_size = isntsc ? 18 : 15; ++ rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 9000; + rd->ffcodecdata.rc_min_rate = 0; + rd->ffcodecdata.rc_buffer_size = 224 * 8; +@@ -1606,14 +1285,14 @@ void BKE_ffmpeg_preset_set(RenderData *rd, int preset) + case FFMPEG_PRESET_DV: + rd->ffcodecdata.type = FFMPEG_DV; + rd->xsch = 720; +- rd->ysch = isntsc ? 480 : 576; ++ rd->ysch = is_ntsc ? 480 : 576; + break; + + case FFMPEG_PRESET_H264: + rd->ffcodecdata.type = FFMPEG_AVI; + rd->ffcodecdata.codec = AV_CODEC_ID_H264; + rd->ffcodecdata.video_bitrate = 6000; +- rd->ffcodecdata.gop_size = isntsc ? 18 : 15; ++ rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 9000; + rd->ffcodecdata.rc_min_rate = 0; + rd->ffcodecdata.rc_buffer_size = 224 * 8; +@@ -1634,17 +1313,14 @@ void BKE_ffmpeg_preset_set(RenderData *rd, int preset) + } + + rd->ffcodecdata.video_bitrate = 6000; +- rd->ffcodecdata.gop_size = isntsc ? 18 : 15; ++ rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15; + rd->ffcodecdata.rc_max_rate = 9000; + rd->ffcodecdata.rc_min_rate = 0; + rd->ffcodecdata.rc_buffer_size = 224 * 8; + rd->ffcodecdata.mux_packet_size = 2048; + rd->ffcodecdata.mux_rate = 10080000; + break; +- + } +- +- ffmpeg_set_expert_options(rd); + } + + void BKE_ffmpeg_image_type_verify(RenderData *rd, ImageFormatData *imf) +@@ -1693,30 +1369,17 @@ void BKE_ffmpeg_image_type_verify(RenderData *rd, ImageFormatData *imf) + } + } + +-void BKE_ffmpeg_codec_settings_verify(RenderData *rd) +-{ +- ffmpeg_set_expert_options(rd); +-} +- + bool BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd) + { + int codec = rd->ffcodecdata.codec; + +- if (codec == AV_CODEC_ID_QTRLE) +- return true; +- +- if (codec == AV_CODEC_ID_PNG) +- return true; +- +- if (codec == AV_CODEC_ID_HUFFYUV) +- return true; +- +-#ifdef FFMPEG_FFV1_ALPHA_SUPPORTED +- if (codec == AV_CODEC_ID_FFV1) +- return true; +-#endif ++ return ELEM(codec, ++ AV_CODEC_ID_FFV1, ++ AV_CODEC_ID_QTRLE, ++ AV_CODEC_ID_PNG, ++ AV_CODEC_ID_VP9, ++ AV_CODEC_ID_HUFFYUV); + +- return false; + } + + void *BKE_ffmpeg_context_create(void) +diff --git a/blender-2.79b/source/blender/blenlib/BLI_math_base.h b/blender-2.79b/source/blender/blenlib/BLI_math_base.h +index e7e89a6..0872000 100644 +--- a/blender-2.79b/source/blender/blenlib/BLI_math_base.h ++++ b/blender-2.79b/source/blender/blenlib/BLI_math_base.h +@@ -153,6 +153,8 @@ MINLINE int iroundf(float a); + MINLINE int divide_round_i(int a, int b); + MINLINE int mod_i(int i, int n); + ++MINLINE int round_fl_to_int(float a); ++ + MINLINE signed char round_fl_to_char_clamp(float a); + MINLINE unsigned char round_fl_to_uchar_clamp(float a); + MINLINE short round_fl_to_short_clamp(float a); +diff --git a/blender-2.79b/source/blender/blenlib/intern/math_base_inline.c b/blender-2.79b/source/blender/blenlib/intern/math_base_inline.c +index 37efe95..95ff62b 100644 +--- a/blender-2.79b/source/blender/blenlib/intern/math_base_inline.c ++++ b/blender-2.79b/source/blender/blenlib/intern/math_base_inline.c +@@ -189,6 +189,15 @@ MINLINE int iroundf(float a) + return (int)floorf(a + 0.5f); + } + ++#define _round_fl_impl(arg, ty) \ ++ { \ ++ return (ty)floorf(arg + 0.5f); \ ++ } ++ ++MINLINE int round_fl_to_int(float a){_round_fl_impl(a, int)} ++ ++#undef _round_fl_impl ++ + #define _round_clamp_fl_impl(arg, ty, min, max) { \ + float r = floorf(arg + 0.5f); \ + if (UNLIKELY(r <= (float)min)) return (ty)min; \ +diff --git a/blender-2.79b/source/blender/blenloader/intern/readfile.c b/blender-2.79b/source/blender/blenloader/intern/readfile.c +index f440cca..bd6168c 100644 +--- a/blender-2.79b/source/blender/blenloader/intern/readfile.c ++++ b/blender-2.79b/source/blender/blenloader/intern/readfile.c +@@ -6169,7 +6169,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) + } + } + } +- ++ + sce->r.avicodecdata = newdataadr(fd, sce->r.avicodecdata); + if (sce->r.avicodecdata) { + sce->r.avicodecdata->lpFormat = newdataadr(fd, sce->r.avicodecdata->lpFormat); +@@ -6180,11 +6180,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) + if (sce->r.qtcodecdata) { + sce->r.qtcodecdata->cdParms = newdataadr(fd, sce->r.qtcodecdata->cdParms); + } +- if (sce->r.ffcodecdata.properties) { +- sce->r.ffcodecdata.properties = newdataadr(fd, sce->r.ffcodecdata.properties); +- IDP_DirectLinkGroup_OrFree(&sce->r.ffcodecdata.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); +- } +- ++ + link_list(fd, &(sce->markers)); + link_list(fd, &(sce->transform_spaces)); + link_list(fd, &(sce->r.layers)); +@@ -6209,7 +6205,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) + } + + direct_link_view_settings(fd, &sce->view_settings); +- ++ + sce->rigidbody_world = newdataadr(fd, sce->rigidbody_world); + rbw = sce->rigidbody_world; + if (rbw) { +diff --git a/blender-2.79b/source/blender/blenloader/intern/writefile.c b/blender-2.79b/source/blender/blenloader/intern/writefile.c +index a50afc4..0c54b11 100644 +--- a/blender-2.79b/source/blender/blenloader/intern/writefile.c ++++ b/blender-2.79b/source/blender/blenloader/intern/writefile.c +@@ -2697,9 +2697,6 @@ static void write_scene(WriteData *wd, Scene *sce) + writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms); + } + } +- if (sce->r.ffcodecdata.properties) { +- IDP_WriteProperty(sce->r.ffcodecdata.properties, wd); +- } + + /* writing dynamic list of TimeMarkers to the blend file */ + for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) { +diff --git a/blender-2.79b/source/blender/imbuf/intern/IMB_anim.h b/blender-2.79b/source/blender/imbuf/intern/IMB_anim.h +index 5f47769..8d380fb 100644 +--- a/blender-2.79b/source/blender/imbuf/intern/IMB_anim.h ++++ b/blender-2.79b/source/blender/imbuf/intern/IMB_anim.h +@@ -145,7 +145,7 @@ struct anim { + #ifdef WITH_FFMPEG + AVFormatContext *pFormatCtx; + AVCodecContext *pCodecCtx; +- AVCodec *pCodec; ++ const AVCodec *pCodec; + AVFrame *pFrame; + int pFrameComplete; + AVFrame *pFrameRGB; +@@ -156,7 +156,7 @@ struct anim { + struct ImBuf *last_frame; + int64_t last_pts; + int64_t next_pts; +- AVPacket next_packet; ++ AVPacket *next_packet; + #endif + + char index_dir[768]; +diff --git a/blender-2.79b/source/blender/imbuf/intern/anim_movie.c b/blender-2.79b/source/blender/imbuf/intern/anim_movie.c +index 8bd808f..9eb40d3 100644 +--- a/blender-2.79b/source/blender/imbuf/intern/anim_movie.c ++++ b/blender-2.79b/source/blender/imbuf/intern/anim_movie.c +@@ -92,6 +92,7 @@ + #ifdef WITH_FFMPEG + # include <libavformat/avformat.h> + # include <libavcodec/avcodec.h> ++# include <libavutil/imgutils.h> + # include <libavutil/rational.h> + # include <libswscale/swscale.h> + +@@ -448,24 +449,25 @@ BLI_INLINE bool need_aligned_ffmpeg_buffer(struct anim *anim) + + static int startffmpeg(struct anim *anim) + { +- int i, videoStream; ++ int i, video_stream_index; + +- AVCodec *pCodec; ++ const AVCodec *pCodec; + AVFormatContext *pFormatCtx = NULL; + AVCodecContext *pCodecCtx; + AVRational frame_rate; ++ AVStream *video_stream; + int frs_num; + double frs_den; + int streamcount; + +-#ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT + /* The following for color space determination */ + int srcRange, dstRange, brightness, contrast, saturation; + int *table; + const int *inv_table; +-#endif + +- if (anim == NULL) return(-1); ++ if (anim == NULL) { ++ return(-1); ++ } + + streamcount = anim->streamindex; + +@@ -482,47 +484,50 @@ static int startffmpeg(struct anim *anim) + + + /* Find the video stream */ +- videoStream = -1; ++ video_stream_index = -1; + +- for (i = 0; i < pFormatCtx->nb_streams; i++) +- if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { ++ for (i = 0; i < pFormatCtx->nb_streams; i++) { ++ if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (streamcount > 0) { + streamcount--; + continue; + } +- videoStream = i; ++ video_stream_index = i; + break; + } ++ } + +- if (videoStream == -1) { ++ if (video_stream_index == -1) { + avformat_close_input(&pFormatCtx); + return -1; + } + +- pCodecCtx = pFormatCtx->streams[videoStream]->codec; ++ video_stream = pFormatCtx->streams[video_stream_index]; + + /* Find the decoder for the video stream */ +- pCodec = avcodec_find_decoder(pCodecCtx->codec_id); ++ pCodec = avcodec_find_decoder(video_stream->codecpar->codec_id); + if (pCodec == NULL) { + avformat_close_input(&pFormatCtx); + return -1; + } + +- pCodecCtx->workaround_bugs = 1; ++ pCodecCtx = avcodec_alloc_context3(NULL); ++ avcodec_parameters_to_context(pCodecCtx, video_stream->codecpar); ++ pCodecCtx->workaround_bugs = FF_BUG_AUTODETECT; + + if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { + avformat_close_input(&pFormatCtx); + return -1; + } + if (pCodecCtx->pix_fmt == AV_PIX_FMT_NONE) { +- avcodec_close(anim->pCodecCtx); ++ avcodec_free_context(&anim->pCodecCtx); + avformat_close_input(&pFormatCtx); + return -1; + } + +- frame_rate = av_get_r_frame_rate_compat(pFormatCtx->streams[videoStream]); +- if (pFormatCtx->streams[videoStream]->nb_frames != 0) { +- anim->duration = pFormatCtx->streams[videoStream]->nb_frames; ++ frame_rate = av_guess_frame_rate(pFormatCtx, video_stream, NULL); ++ if (video_stream->nb_frames != 0) { ++ anim->duration = video_stream->nb_frames; + } + else { + anim->duration = (int)(pFormatCtx->duration * +@@ -546,12 +551,12 @@ static int startffmpeg(struct anim *anim) + anim->params = 0; + + anim->x = pCodecCtx->width; +- anim->y = av_get_cropped_height_from_codec(pCodecCtx); ++ anim->y = pCodecCtx->height; + + anim->pFormatCtx = pFormatCtx; + anim->pCodecCtx = pCodecCtx; + anim->pCodec = pCodec; +- anim->videoStream = videoStream; ++ anim->videoStream = video_stream_index; + + anim->interlacing = 0; + anim->orientation = 0; +@@ -561,7 +566,8 @@ static int startffmpeg(struct anim *anim) + anim->last_frame = 0; + anim->last_pts = -1; + anim->next_pts = -1; +- anim->next_packet.stream_index = -1; ++ anim->next_packet = av_packet_alloc(); ++ anim->next_packet->stream_index = -1; + + anim->pFrame = av_frame_alloc(); + anim->pFrameComplete = false; +@@ -575,8 +581,9 @@ static int startffmpeg(struct anim *anim) + + if (av_frame_get_buffer(anim->pFrameRGB, 32) < 0) { + fprintf(stderr, "Could not allocate frame data.\n"); +- avcodec_close(anim->pCodecCtx); ++ avcodec_free_context(&anim->pCodecCtx); + avformat_close_input(&anim->pFormatCtx); ++ av_packet_free(&anim->next_packet); + av_frame_free(&anim->pFrameRGB); + av_frame_free(&anim->pFrameDeinterlaced); + av_frame_free(&anim->pFrame); +@@ -585,13 +592,13 @@ static int startffmpeg(struct anim *anim) + } + } + +- if (avpicture_get_size(AV_PIX_FMT_RGBA, anim->x, anim->y) != +- anim->x * anim->y * 4) ++ if (av_image_get_buffer_size(AV_PIX_FMT_RGBA, anim->x, anim->y, 1) != anim->x * anim->y * 4) + { + fprintf(stderr, + "ffmpeg has changed alloc scheme ... ARGHHH!\n"); +- avcodec_close(anim->pCodecCtx); ++ avcodec_free_context(&anim->pCodecCtx); + avformat_close_input(&anim->pFormatCtx); ++ av_packet_free(&anim->next_packet); + av_frame_free(&anim->pFrameRGB); + av_frame_free(&anim->pFrameDeinterlaced); + av_frame_free(&anim->pFrame); +@@ -600,15 +607,17 @@ static int startffmpeg(struct anim *anim) + } + + if (anim->ib_flags & IB_animdeinterlace) { +- avpicture_fill((AVPicture *) anim->pFrameDeinterlaced, +- MEM_callocN(avpicture_get_size( +- anim->pCodecCtx->pix_fmt, +- anim->pCodecCtx->width, +- anim->pCodecCtx->height), +- "ffmpeg deinterlace"), +- anim->pCodecCtx->pix_fmt, +- anim->pCodecCtx->width, +- anim->pCodecCtx->height); ++ av_image_fill_arrays(anim->pFrameDeinterlaced->data, ++ anim->pFrameDeinterlaced->linesize, ++ MEM_callocN(av_image_get_buffer_size(anim->pCodecCtx->pix_fmt, ++ anim->pCodecCtx->width, ++ anim->pCodecCtx->height, ++ 1), ++ "ffmpeg deinterlace"), ++ anim->pCodecCtx->pix_fmt, ++ anim->pCodecCtx->width, ++ anim->pCodecCtx->height, ++ 1); + } + + if (pCodecCtx->has_b_frames) { +@@ -617,7 +626,7 @@ static int startffmpeg(struct anim *anim) + else { + anim->preseek = 0; + } +- ++ + anim->img_convert_ctx = sws_getContext( + anim->x, + anim->y, +@@ -627,12 +636,13 @@ static int startffmpeg(struct anim *anim) + AV_PIX_FMT_RGBA, + SWS_FAST_BILINEAR | SWS_PRINT_INFO | SWS_FULL_CHR_H_INT, + NULL, NULL, NULL); +- ++ + if (!anim->img_convert_ctx) { + fprintf(stderr, + "Can't transform color space??? Bailing out...\n"); +- avcodec_close(anim->pCodecCtx); ++ avcodec_free_context(&anim->pCodecCtx); + avformat_close_input(&anim->pFormatCtx); ++ av_packet_free(&anim->next_packet); + av_frame_free(&anim->pFrameRGB); + av_frame_free(&anim->pFrameDeinterlaced); + av_frame_free(&anim->pFrame); +@@ -640,7 +650,6 @@ static int startffmpeg(struct anim *anim) + return -1; + } + +-#ifdef FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT + /* Try do detect if input has 0-255 YCbCR range (JFIF Jpeg MotionJpeg) */ + if (!sws_getColorspaceDetails(anim->img_convert_ctx, (int **)&inv_table, &srcRange, + &table, &dstRange, &brightness, &contrast, &saturation)) +@@ -657,8 +666,7 @@ static int startffmpeg(struct anim *anim) + else { + fprintf(stderr, "Warning: Could not set libswscale colorspace details.\n"); + } +-#endif +- ++ + return (0); + } + +@@ -695,14 +703,11 @@ static void ffmpeg_postprocess(struct anim *anim) + + + if (anim->ib_flags & IB_animdeinterlace) { +- if (avpicture_deinterlace( +- (AVPicture *) +- anim->pFrameDeinterlaced, +- (const AVPicture *) +- anim->pFrame, +- anim->pCodecCtx->pix_fmt, +- anim->pCodecCtx->width, +- anim->pCodecCtx->height) < 0) ++ if (av_image_deinterlace(anim->pFrameDeinterlaced, ++ anim->pFrame, ++ anim->pCodecCtx->pix_fmt, ++ anim->pCodecCtx->width, ++ anim->pCodecCtx->height) < 0) + { + filter_y = true; + } +@@ -712,9 +717,13 @@ static void ffmpeg_postprocess(struct anim *anim) + } + + if (!need_aligned_ffmpeg_buffer(anim)) { +- avpicture_fill((AVPicture *) anim->pFrameRGB, +- (unsigned char *) ibuf->rect, +- AV_PIX_FMT_RGBA, anim->x, anim->y); ++ av_image_fill_arrays(anim->pFrameRGB->data, ++ anim->pFrameRGB->linesize, ++ (unsigned char *)ibuf->rect, ++ AV_PIX_FMT_RGBA, ++ anim->x, ++ anim->y, ++ 1); + } + + if (ENDIAN_ORDER == B_ENDIAN) { +@@ -803,33 +812,27 @@ static int ffmpeg_decode_video_frame(struct anim *anim) + + av_log(anim->pFormatCtx, AV_LOG_DEBUG, " DECODE VIDEO FRAME\n"); + +- if (anim->next_packet.stream_index == anim->videoStream) { +- av_free_packet(&anim->next_packet); +- anim->next_packet.stream_index = -1; ++ if (anim->next_packet->stream_index == anim->videoStream) { ++ av_packet_unref(anim->next_packet); ++ anim->next_packet->stream_index = -1; + } +- +- while ((rval = av_read_frame(anim->pFormatCtx, &anim->next_packet)) >= 0) { ++ ++ while ((rval = av_read_frame(anim->pFormatCtx, anim->next_packet)) >= 0) { + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, + "%sREAD: strID=%d (VID: %d) dts=%lld pts=%lld " + "%s\n", +- (anim->next_packet.stream_index == anim->videoStream) +- ? "->" : " ", +- anim->next_packet.stream_index, ++ (anim->next_packet->stream_index == anim->videoStream) ? "->" : " ", ++ anim->next_packet->stream_index, + anim->videoStream, +- (anim->next_packet.dts == AV_NOPTS_VALUE) ? -1 : +- (long long int)anim->next_packet.dts, +- (anim->next_packet.pts == AV_NOPTS_VALUE) ? -1 : +- (long long int)anim->next_packet.pts, +- (anim->next_packet.flags & AV_PKT_FLAG_KEY) ? +- " KEY" : ""); +- if (anim->next_packet.stream_index == anim->videoStream) { ++ (anim->next_packet->dts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->next_packet->dts, ++ (anim->next_packet->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->next_packet->pts, ++ (anim->next_packet->flags & AV_PKT_FLAG_KEY) ? " KEY" : ""); ++ if (anim->next_packet->stream_index == anim->videoStream) { + anim->pFrameComplete = 0; + +- avcodec_decode_video2( +- anim->pCodecCtx, +- anim->pFrame, &anim->pFrameComplete, +- &anim->next_packet); ++ avcodec_send_packet(anim->pCodecCtx, anim->next_packet); ++ anim->pFrameComplete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0; + + if (anim->pFrameComplete) { + anim->next_pts = av_get_pts_from_frame( +@@ -837,38 +840,23 @@ static int ffmpeg_decode_video_frame(struct anim *anim) + + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, +- " FRAME DONE: next_pts=%lld " +- "pkt_pts=%lld, guessed_pts=%lld\n", ++ " FRAME DONE: next_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n", + (anim->pFrame->pts == AV_NOPTS_VALUE) ? +- -1 : (long long int)anim->pFrame->pts, +- (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? +- -1 : (long long int)anim->pFrame->pkt_pts, +- (long long int)anim->next_pts); ++ -1 : (int64_t)anim->pFrame->pts, ++ (int64_t)anim->next_pts); + break; + } + } +- av_free_packet(&anim->next_packet); +- anim->next_packet.stream_index = -1; ++ av_packet_unref(anim->next_packet); ++ anim->next_packet->stream_index = -1; + } + + if (rval == AVERROR_EOF) { +- /* this sets size and data fields to zero, +- * which is necessary to decode the remaining data +- * in the decoder engine after EOF. It also prevents a memory +- * leak, since av_read_frame spills out a full size packet even +- * on EOF... (and: it's safe to call on NULL packets) */ +- +- av_free_packet(&anim->next_packet); +- +- anim->next_packet.size = 0; +- anim->next_packet.data = 0; +- ++ /* Flush any remaining frames out of the decoder. */ + anim->pFrameComplete = 0; + +- avcodec_decode_video2( +- anim->pCodecCtx, +- anim->pFrame, &anim->pFrameComplete, +- &anim->next_packet); ++ avcodec_send_packet(anim->pCodecCtx, NULL); ++ anim->pFrameComplete = avcodec_receive_frame(anim->pCodecCtx, anim->pFrame) == 0; + + if (anim->pFrameComplete) { + anim->next_pts = av_get_pts_from_frame( +@@ -876,23 +864,21 @@ static int ffmpeg_decode_video_frame(struct anim *anim) + + av_log(anim->pFormatCtx, + AV_LOG_DEBUG, +- " FRAME DONE (after EOF): next_pts=%lld " +- "pkt_pts=%lld, guessed_pts=%lld\n", ++ " FRAME DONE (after EOF): next_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n", + (anim->pFrame->pts == AV_NOPTS_VALUE) ? + -1 : (long long int)anim->pFrame->pts, +- (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? +- -1 : (long long int)anim->pFrame->pkt_pts, + (long long int)anim->next_pts); + rval = 0; + } + } + + if (rval < 0) { +- anim->next_packet.stream_index = -1; ++ av_packet_unref(anim->next_packet); ++ anim->next_packet->stream_index = -1; + + av_log(anim->pFormatCtx, + AV_LOG_ERROR, " DECODE READ FAILED: av_read_frame() " +- "returned error: %d\n", rval); ++ "returned error: %s\n", av_err2str(rval)); + } + + return (rval >= 0); +@@ -998,7 +984,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, + + v_st = anim->pFormatCtx->streams[anim->videoStream]; + +- frame_rate = av_q2d(av_get_r_frame_rate_compat(v_st)); ++ frame_rate = av_q2d(av_guess_frame_rate(anim->pFormatCtx, v_st, NULL)); + + st_time = anim->pFormatCtx->start_time; + pts_time_base = av_q2d(v_st->time_base); +@@ -1082,7 +1068,6 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, + ret = av_seek_frame(anim->pFormatCtx, + -1, + pos, AVSEEK_FLAG_BYTE); +- av_update_cur_dts(anim->pFormatCtx, v_st, dts); + } + else { + av_log(anim->pFormatCtx, AV_LOG_DEBUG, +@@ -1127,9 +1112,9 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, + + anim->next_pts = -1; + +- if (anim->next_packet.stream_index == anim->videoStream) { +- av_free_packet(&anim->next_packet); +- anim->next_packet.stream_index = -1; ++ if (anim->next_packet->stream_index == anim->videoStream) { ++ av_packet_unref(&anim->next_packet); ++ anim->next_packet->stream_index = -1; + } + + /* memset(anim->pFrame, ...) ?? */ +@@ -1154,11 +1139,11 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, + ffmpeg_postprocess(anim); + + anim->last_pts = anim->next_pts; +- ++ + ffmpeg_decode_video_frame(anim); +- ++ + anim->curposition = position; +- ++ + IMB_refImBuf(anim->last_frame); + + return anim->last_frame; +@@ -1169,35 +1154,30 @@ static void free_anim_ffmpeg(struct anim *anim) + if (anim == NULL) return; + + if (anim->pCodecCtx) { +- avcodec_close(anim->pCodecCtx); ++ avcodec_free_context(&anim->pCodecCtx); + avformat_close_input(&anim->pFormatCtx); ++ av_packet_free(&anim->next_packet); + +- /* Special case here: pFrame could share pointers with codec, +- * so in order to avoid double-free we don't use av_frame_free() +- * to free the frame. +- * +- * Could it be a bug in FFmpeg? +- */ +- av_free(anim->pFrame); ++ av_frame_free(&anim->pFrame); + + if (!need_aligned_ffmpeg_buffer(anim)) { + /* If there's no need for own aligned buffer it means that FFmpeg's + * frame shares the same buffer as temporary ImBuf. In this case we + * should not free the buffer when freeing the FFmpeg buffer. + */ +- avpicture_fill((AVPicture *)anim->pFrameRGB, +- NULL, +- AV_PIX_FMT_RGBA, +- anim->x, anim->y); ++ av_image_fill_arrays(anim->pFrameRGB->data, ++ anim->pFrameRGB->linesize, ++ NULL, ++ AV_PIX_FMT_RGBA, ++ anim->x, ++ anim->y, ++ 1); + } + av_frame_free(&anim->pFrameRGB); + av_frame_free(&anim->pFrameDeinterlaced); + + sws_freeContext(anim->img_convert_ctx); + IMB_freeImBuf(anim->last_frame); +- if (anim->next_packet.stream_index != -1) { +- av_free_packet(&anim->next_packet); +- } + } + anim->duration = 0; + } +diff --git a/blender-2.79b/source/blender/imbuf/intern/indexer.c b/blender-2.79b/source/blender/imbuf/intern/indexer.c +index e1b3abc..df8d5c4 100644 +--- a/blender-2.79b/source/blender/imbuf/intern/indexer.c ++++ b/blender-2.79b/source/blender/imbuf/intern/indexer.c +@@ -32,6 +32,7 @@ + + #include "BLI_utildefines.h" + #include "BLI_endian_switch.h" ++#include "BLI_math_base.h" + #include "BLI_path_util.h" + #include "BLI_string.h" + #include "BLI_fileops.h" +@@ -49,6 +50,7 @@ + + #ifdef WITH_FFMPEG + # include "ffmpeg_compat.h" ++# include <libavutil/imgutils.h> + #endif + + +@@ -452,7 +454,7 @@ struct proxy_output_ctx { + AVFormatContext *of; + AVStream *st; + AVCodecContext *c; +- AVCodec *codec; ++ const AVCodec *codec; + struct SwsContext *sws_ctx; + AVFrame *frame; + int cfra; +@@ -477,7 +479,6 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( + sizeof(struct proxy_output_ctx), "alloc_proxy_output"); + + char fname[FILE_MAX]; +- int ffmpeg_quality; + + /* JPEG requires this */ + width = round_up(width, 8); +@@ -491,30 +492,30 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( + + rv->of = avformat_alloc_context(); + rv->of->oformat = av_guess_format("avi", NULL, NULL); +- +- BLI_strncpy(rv->of->filename, fname, sizeof(rv->of->filename)); + +- fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename); ++ rv->of->url = av_strdup(fname); ++ ++ fprintf(stderr, "Starting work on proxy: %s\n", rv->of->url); + + rv->st = avformat_new_stream(rv->of, NULL); + rv->st->id = 0; + +- rv->c = rv->st->codec; +- rv->c->codec_type = AVMEDIA_TYPE_VIDEO; +- rv->c->codec_id = AV_CODEC_ID_MJPEG; +- rv->c->width = width; +- rv->c->height = height; ++ rv->codec = avcodec_find_encoder(AV_CODEC_ID_H264); + +- rv->of->oformat->video_codec = rv->c->codec_id; +- rv->codec = avcodec_find_encoder(rv->c->codec_id); ++ rv->c = avcodec_alloc_context3(rv->codec); + + if (!rv->codec) { + fprintf(stderr, "No ffmpeg MJPEG encoder available? " + "Proxy not built!\n"); +- av_free(rv->of); ++ avcodec_free_context(&rv->c); ++ avformat_free_context(rv->of); ++ MEM_freeN(rv); + return NULL; + } + ++ rv->c->width = width; ++ rv->c->height = height; ++ + if (rv->codec->pix_fmts) { + rv->c->pix_fmt = rv->codec->pix_fmts[0]; + } +@@ -522,76 +523,105 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( + rv->c->pix_fmt = AV_PIX_FMT_YUVJ420P; + } + +- rv->c->sample_aspect_ratio = +- rv->st->sample_aspect_ratio = +- st->codec->sample_aspect_ratio; ++ rv->c->sample_aspect_ratio = rv->st->sample_aspect_ratio = st->sample_aspect_ratio; + + rv->c->time_base.den = 25; + rv->c->time_base.num = 1; + rv->st->time_base = rv->c->time_base; + +- /* there's no way to set JPEG quality in the same way as in AVI JPEG and image sequence, +- * but this seems to be giving expected quality result */ +- ffmpeg_quality = (int)(1.0f + 30.0f * (1.0f - (float)quality / 100.0f) + 0.5f); +- av_opt_set_int(rv->c, "qmin", ffmpeg_quality, 0); +- av_opt_set_int(rv->c, "qmax", ffmpeg_quality, 0); ++ /* This range matches #eFFMpegCrf. `crf_range_min` corresponds to lowest quality, ++ * `crf_range_max` to highest quality. */ ++ const int crf_range_min = 32; ++ const int crf_range_max = 17; ++ int crf = round_fl_to_int((quality / 100.0f) * (crf_range_max - crf_range_min) + crf_range_min); ++ ++ AVDictionary *codec_opts = NULL; ++ /* High quality preset value. */ ++ av_dict_set_int(&codec_opts, "crf", crf, 0); ++ /* Prefer smaller file-size. Presets from `veryslow` to `veryfast` produce output with very ++ * similar file-size, but there is big difference in performance. ++ * In some cases `veryfast` preset will produce smallest file-size. */ ++ av_dict_set(&codec_opts, "preset", "veryfast", 0); ++ av_dict_set(&codec_opts, "tune", "fastdecode", 0); + + if (rv->of->flags & AVFMT_GLOBALHEADER) { +- rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER; ++ rv->c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + } + +- if (avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE) < 0) { +- fprintf(stderr, "Couldn't open outputfile! " +- "Proxy not built!\n"); +- av_free(rv->of); +- return 0; ++ avcodec_parameters_from_context(rv->st->codecpar, rv->c); ++ ++ int ret = avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE); ++ ++ if (ret < 0) { ++ fprintf(stderr, "Couldn't open IO: %s\n" ++ "Proxy not built!\n", ++ av_err2str(ret)); ++ avcodec_free_context(&rv->c); ++ avformat_free_context(rv->of); ++ MEM_freeN(rv); ++ return NULL; + } + +- avcodec_open2(rv->c, rv->codec, NULL); ++ ret = avcodec_open2(rv->c, rv->codec, &codec_opts); ++ if (ret < 0) { ++ fprintf(stderr, ++ "Couldn't open codec: %s\n" ++ "Proxy not built!\n", ++ av_err2str(ret)); ++ avcodec_free_context(&rv->c); ++ avformat_free_context(rv->of); ++ MEM_freeN(rv); ++ return NULL; ++ } + +- rv->orig_height = av_get_cropped_height_from_codec(st->codec); ++ rv->orig_height = st->codecpar->height; + +- if (st->codec->width != width || st->codec->height != height || +- st->codec->pix_fmt != rv->c->pix_fmt) ++ if (st->codecpar->width != width || st->codecpar->height != height || ++ st->codecpar->format != rv->c->pix_fmt) + { + rv->frame = av_frame_alloc(); +- avpicture_fill((AVPicture *) rv->frame, +- MEM_mallocN(avpicture_get_size( +- rv->c->pix_fmt, +- round_up(width, 16), height), +- "alloc proxy output frame"), +- rv->c->pix_fmt, round_up(width, 16), height); ++ av_image_fill_arrays(rv->frame->data, ++ rv->frame->linesize, ++ MEM_mallocN(av_image_get_buffer_size(rv->c->pix_fmt, round_up(width, 16), height, 1), "alloc proxy output frame"), ++ rv->c->pix_fmt, ++ round_up(width, 16), ++ height, ++ 1); + + rv->sws_ctx = sws_getContext( +- st->codec->width, ++ st->codecpar->width, + rv->orig_height, +- st->codec->pix_fmt, ++ st->codecpar->format, + width, height, + rv->c->pix_fmt, + SWS_FAST_BILINEAR | SWS_PRINT_INFO, + NULL, NULL, NULL); + } + +- if (avformat_write_header(rv->of, NULL) < 0) { +- fprintf(stderr, "Couldn't set output parameters? " +- "Proxy not built!\n"); +- av_free(rv->of); +- return 0; ++ ret = avformat_write_header(rv->of, NULL); ++ if (ret < 0) { ++ fprintf(stderr, "Couldn't write header: %s\n" ++ "Proxy not built!\n", ++ av_err2str(ret)); ++ ++ if (rv->frame) { ++ av_frame_free(&rv->frame); ++ } ++ ++ avcodec_free_context(&rv->c); ++ avformat_free_context(rv->of); ++ MEM_freeN(rv); ++ return NULL; + } + + return rv; + } + +-static int add_to_proxy_output_ffmpeg( ++static void add_to_proxy_output_ffmpeg( + struct proxy_output_ctx *ctx, AVFrame *frame) + { +- AVPacket packet = { 0 }; +- int ret, got_output; +- +- av_init_packet(&packet); +- + if (!ctx) { +- return 0; ++ return; + } + + if (ctx->sws_ctx && frame && +@@ -609,39 +639,42 @@ static int add_to_proxy_output_ffmpeg( + frame->pts = ctx->cfra++; + } + +- ret = avcodec_encode_video2(ctx->c, &packet, frame, &got_output); ++ int ret = avcodec_send_frame(ctx->c, frame); + if (ret < 0) { +- fprintf(stderr, "Error encoding proxy frame %d for '%s'\n", +- ctx->cfra - 1, ctx->of->filename); +- return 0; ++ /* Can't send frame to encoder. This shouldn't happen. */ ++ fprintf(stderr, "Can't send video frame: %s\n", av_err2str(ret)); ++ return; + } ++ AVPacket *packet = av_packet_alloc(); ++ ++ while (ret >= 0) { ++ ret = avcodec_receive_packet(ctx->c, packet); + +- if (got_output) { +- if (packet.pts != AV_NOPTS_VALUE) { +- packet.pts = av_rescale_q(packet.pts, +- ctx->c->time_base, +- ctx->st->time_base); ++ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { ++ /* No more packets to flush. */ ++ break; + } +- if (packet.dts != AV_NOPTS_VALUE) { +- packet.dts = av_rescale_q(packet.dts, +- ctx->c->time_base, +- ctx->st->time_base); ++ if (ret < 0) { ++ fprintf(stderr, ++ "Error encoding proxy frame %d for '%s': %s\n", ++ ctx->cfra - 1, ++ ctx->of->url, ++ av_err2str(ret)); ++ break; + } + +- packet.stream_index = ctx->st->index; ++ packet->stream_index = ctx->st->index; ++ av_packet_rescale_ts(packet, ctx->c->time_base, ctx->st->time_base); + +- if (av_interleaved_write_frame(ctx->of, &packet) != 0) { ++ int write_ret = av_interleaved_write_frame(ctx->of, packet); ++ if (write_ret != 0) { + fprintf(stderr, "Error writing proxy frame %d " +- "into '%s'\n", ctx->cfra - 1, +- ctx->of->filename); +- return 0; ++ "into '%s': %s\n", ctx->cfra - 1, ++ ctx->of->url, av_err2str(write_ret)); ++ break; + } +- +- return 1; +- } +- else { +- return 0; + } ++ av_packet_free(&packet); + } + + static void free_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, +@@ -655,15 +688,16 @@ static void free_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, + } + + if (!rollback) { +- while (add_to_proxy_output_ffmpeg(ctx, NULL)) {} ++ /* Flush the remaining packets. */ ++ add_to_proxy_output_ffmpeg(ctx, NULL); + } + + avcodec_flush_buffers(ctx->c); + + av_write_trailer(ctx->of); +- +- avcodec_close(ctx->c); +- ++ ++ avcodec_free_context(&ctx->c); ++ + if (ctx->of->oformat) { + if (!(ctx->of->oformat->flags & AVFMT_NOFILE)) { + avio_close(ctx->of->pb); +@@ -699,7 +733,7 @@ typedef struct FFmpegIndexBuilderContext { + + AVFormatContext *iFormatCtx; + AVCodecContext *iCodecCtx; +- AVCodec *iCodec; ++ const AVCodec *iCodec; + AVStream *iStream; + int videoStream; + +@@ -756,7 +790,7 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Tim + /* Find the video stream */ + context->videoStream = -1; + for (i = 0; i < context->iFormatCtx->nb_streams; i++) +- if (context->iFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { ++ if (context->iFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (streamcount > 0) { + streamcount--; + continue; +@@ -772,9 +806,8 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Tim + } + + context->iStream = context->iFormatCtx->streams[context->videoStream]; +- context->iCodecCtx = context->iStream->codec; + +- context->iCodec = avcodec_find_decoder(context->iCodecCtx->codec_id); ++ context->iCodec = avcodec_find_decoder(context->iStream->codecpar->codec_id); + + if (context->iCodec == NULL) { + avformat_close_input(&context->iFormatCtx); +@@ -782,22 +815,25 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Tim + return NULL; + } + +- context->iCodecCtx->workaround_bugs = 1; ++ context->iCodecCtx = avcodec_alloc_context3(NULL); ++ avcodec_parameters_to_context(context->iCodecCtx, context->iStream->codecpar); ++ context->iCodecCtx->workaround_bugs = FF_BUG_AUTODETECT; + + if (avcodec_open2(context->iCodecCtx, context->iCodec, NULL) < 0) { + avformat_close_input(&context->iFormatCtx); ++ avcodec_free_context(&context->iCodecCtx); + MEM_freeN(context); + return NULL; + } + + for (i = 0; i < num_proxy_sizes; i++) { + if (proxy_sizes_in_use & proxy_sizes[i]) { +- context->proxy_ctx[i] = alloc_proxy_output_ffmpeg( +- anim, context->iStream, proxy_sizes[i], +- context->iCodecCtx->width * proxy_fac[i], +- av_get_cropped_height_from_codec( +- context->iCodecCtx) * proxy_fac[i], +- quality); ++ context->proxy_ctx[i] = alloc_proxy_output_ffmpeg(anim, ++ context->iStream, ++ proxy_sizes[i], ++ context->iCodecCtx->width * proxy_fac[i], ++ context->iCodecCtx->height * proxy_fac[i], ++ quality); + if (!context->proxy_ctx[i]) { + proxy_sizes_in_use &= ~proxy_sizes[i]; + } +@@ -836,7 +872,7 @@ static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, int + } + } + +- avcodec_close(context->iCodecCtx); ++ avcodec_free_context(&context->iCodecCtx); + avformat_close_input(&context->iFormatCtx); + + MEM_freeN(context); +@@ -899,23 +935,18 @@ static void index_rebuild_ffmpeg_proc_decoded_frame( + static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, + short *stop, short *do_update, float *progress) + { +- AVFrame *in_frame = 0; +- AVPacket next_packet; ++ AVFrame *in_frame = av_frame_alloc(); ++ AVPacket *next_packet = av_packet_alloc(); + uint64_t stream_size; + +- memset(&next_packet, 0, sizeof(AVPacket)); +- +- in_frame = av_frame_alloc(); +- + stream_size = avio_size(context->iFormatCtx->pb); + +- context->frame_rate = av_q2d(av_get_r_frame_rate_compat(context->iStream)); ++ context->frame_rate = av_q2d(av_guess_frame_rate(context->iFormatCtx, context->iStream, NULL)); + context->pts_time_base = av_q2d(context->iStream->time_base); + +- while (av_read_frame(context->iFormatCtx, &next_packet) >= 0) { ++ while (av_read_frame(context->iFormatCtx, next_packet) >= 0) { + int frame_finished = 0; +- float next_progress = (float)((int)floor(((double) next_packet.pos) * 100 / +- ((double) stream_size) + 0.5)) / 100; ++ float next_progress = (float)((int)floor(((double)next_packet->pos) * 100 / ((double)stream_size) + 0.5)) / 100; + + if (*progress != next_progress) { + *progress = next_progress; +@@ -923,56 +954,59 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context, + } + + if (*stop) { +- av_free_packet(&next_packet); + break; + } + +- if (next_packet.stream_index == context->videoStream) { +- if (next_packet.flags & AV_PKT_FLAG_KEY) { ++ if (next_packet->stream_index == context->videoStream) { ++ if (next_packet->flags & AV_PKT_FLAG_KEY) { + context->last_seek_pos = context->seek_pos; + context->last_seek_pos_dts = context->seek_pos_dts; +- context->seek_pos = next_packet.pos; +- context->seek_pos_dts = next_packet.dts; +- context->seek_pos_pts = next_packet.pts; ++ context->seek_pos = next_packet->pos; ++ context->seek_pos_dts = next_packet->dts; ++ context->seek_pos_pts = next_packet->pts; + } + +- avcodec_decode_video2( +- context->iCodecCtx, in_frame, &frame_finished, +- &next_packet); +- } +- +- if (frame_finished) { +- index_rebuild_ffmpeg_proc_decoded_frame( +- context, &next_packet, in_frame); ++ int ret = avcodec_send_packet(context->iCodecCtx, next_packet); ++ while (ret >= 0) { ++ ret = avcodec_receive_frame(context->iCodecCtx, in_frame); ++ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { ++ /* No more frames to flush. */ ++ break; ++ } ++ if (ret < 0) { ++ fprintf(stderr, "Error decoding proxy frame: %s\n", av_err2str(ret)); ++ break; ++ } ++ index_rebuild_ffmpeg_proc_decoded_frame(context, next_packet, in_frame); ++ } + } +- av_free_packet(&next_packet); + } + + /* process pictures still stuck in decoder engine after EOF +- * according to ffmpeg docs using 0-size packets. ++ * according to ffmpeg docs using NULL packets. + * + * At least, if we haven't already stopped... */ + +- /* this creates the 0-size packet and prevents a memory leak. */ +- av_free_packet(&next_packet); +- + if (!*stop) { +- int frame_finished; ++ int ret = avcodec_send_packet(context->iCodecCtx, NULL); + +- do { +- frame_finished = 0; ++ while (ret >= 0) { ++ ret = avcodec_receive_frame(context->iCodecCtx, in_frame); + +- avcodec_decode_video2( +- context->iCodecCtx, in_frame, &frame_finished, +- &next_packet); ++ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { ++ /* No more frames to flush. */ ++ break; ++ } + +- if (frame_finished) { +- index_rebuild_ffmpeg_proc_decoded_frame( +- context, &next_packet, in_frame); ++ if (ret < 0) { ++ fprintf(stderr, "Error flushing proxy frame: %s\n", av_err2str(ret)); ++ break; + } +- } while (frame_finished); ++ index_rebuild_ffmpeg_proc_decoded_frame(context, next_packet, in_frame); ++ } + } + ++ av_packet_free(&next_packet); + av_free(in_frame); + + return 1; +diff --git a/blender-2.79b/source/blender/imbuf/intern/util.c b/blender-2.79b/source/blender/imbuf/intern/util.c +index ba8480b..24e360c 100644 +--- a/blender-2.79b/source/blender/imbuf/intern/util.c ++++ b/blender-2.79b/source/blender/imbuf/intern/util.c +@@ -290,7 +290,6 @@ static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_lis + + void IMB_ffmpeg_init(void) + { +- av_register_all(); + avdevice_register_all(); + + ffmpeg_last_error[0] = '\0'; +@@ -312,8 +311,7 @@ static int isffmpeg(const char *filename) + AVFormatContext *pFormatCtx = NULL; + unsigned int i; + int videoStream; +- AVCodec *pCodec; +- AVCodecContext *pCodecCtx; ++ const AVCodec *pCodec; + + if (BLI_testextensie_n( + filename, +@@ -339,9 +337,8 @@ static int isffmpeg(const char *filename) + /* Find the first video stream */ + videoStream = -1; + for (i = 0; i < pFormatCtx->nb_streams; i++) +- if (pFormatCtx->streams[i] && +- pFormatCtx->streams[i]->codec && +- (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)) ++ if (pFormatCtx->streams[i] && pFormatCtx->streams[i]->codecpar && ++ (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)) + { + videoStream = i; + break; +@@ -352,21 +349,15 @@ static int isffmpeg(const char *filename) + return 0; + } + +- pCodecCtx = pFormatCtx->streams[videoStream]->codec; ++ AVCodecParameters *codec_par = pFormatCtx->streams[videoStream]->codecpar; + + /* Find the decoder for the video stream */ +- pCodec = avcodec_find_decoder(pCodecCtx->codec_id); ++ pCodec = avcodec_find_decoder(codec_par->codec_id); + if (pCodec == NULL) { + avformat_close_input(&pFormatCtx); + return 0; + } + +- if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { +- avformat_close_input(&pFormatCtx); +- return 0; +- } +- +- avcodec_close(pCodecCtx); + avformat_close_input(&pFormatCtx); + + return 1; +diff --git a/blender-2.79b/source/blender/makesdna/DNA_scene_types.h b/blender-2.79b/source/blender/makesdna/DNA_scene_types.h +index 79ee91b..d7e377a 100644 +--- a/blender-2.79b/source/blender/makesdna/DNA_scene_types.h ++++ b/blender-2.79b/source/blender/makesdna/DNA_scene_types.h +@@ -174,7 +174,6 @@ typedef struct FFMpegCodecData { + int audio_bitrate; + int audio_mixrate; + int audio_channels; +- int audio_pad; + float audio_volume; + int gop_size; + int max_b_frames; /* only used if FFMPEG_USE_MAX_B_FRAMES flag is set. */ +@@ -187,9 +186,7 @@ typedef struct FFMpegCodecData { + int rc_buffer_size; + int mux_packet_size; + int mux_rate; +- int pad1; +- +- IDProperty *properties; ++ void *_pad1; + } FFMpegCodecData; + + /* ************************************************************* */ +diff --git a/blender-2.79b/source/blender/makesrna/intern/rna_scene.c b/blender-2.79b/source/blender/makesrna/intern/rna_scene.c +index db3ff9b..fa02539 100644 +--- a/blender-2.79b/source/blender/makesrna/intern/rna_scene.c ++++ b/blender-2.79b/source/blender/makesrna/intern/rna_scene.c +@@ -1406,20 +1406,12 @@ static void rna_FFmpegSettings_lossless_output_set(PointerRNA *ptr, int value) + Scene *scene = (Scene *) ptr->id.data; + RenderData *rd = &scene->r; + +- if (value) ++ if (value) { + rd->ffcodecdata.flags |= FFMPEG_LOSSLESS_OUTPUT; +- else ++ } ++ else { + rd->ffcodecdata.flags &= ~FFMPEG_LOSSLESS_OUTPUT; +- +- BKE_ffmpeg_codec_settings_verify(rd); +-} +- +-static void rna_FFmpegSettings_codec_settings_update(Main *UNUSED(bmain), Scene *UNUSED(scene_unused), PointerRNA *ptr) +-{ +- Scene *scene = (Scene *) ptr->id.data; +- RenderData *rd = &scene->r; +- +- BKE_ffmpeg_codec_settings_verify(rd); ++ } + } + #endif + +@@ -5594,7 +5586,6 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) + RNA_def_property_enum_items(prop, ffmpeg_format_items); + RNA_def_property_enum_default(prop, FFMPEG_MKV); + RNA_def_property_ui_text(prop, "Container", "Output file container"); +- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_FFmpegSettings_codec_settings_update"); + + prop = RNA_def_property(srna, "codec", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "codec"); +@@ -5602,7 +5593,6 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) + RNA_def_property_enum_items(prop, ffmpeg_codec_items); + RNA_def_property_enum_default(prop, AV_CODEC_ID_H264); + RNA_def_property_ui_text(prop, "Codec", "FFmpeg codec to use"); +- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_FFmpegSettings_codec_settings_update"); + + prop = RNA_def_property(srna, "video_bitrate", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "video_bitrate"); +diff --git a/blender-2.79b/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/blender-2.79b/source/gameengine/VideoTexture/VideoFFmpeg.cpp +index 083e9e2..7246278 100644 +--- a/blender-2.79b/source/gameengine/VideoTexture/VideoFFmpeg.cpp ++++ b/blender-2.79b/source/gameengine/VideoTexture/VideoFFmpeg.cpp +@@ -36,6 +36,10 @@ + #define __STDC_CONSTANT_MACROS + #ifdef __STDC_CONSTANT_MACROS /* quiet warning */ + #endif ++extern "C" { ++#include <libavutil/imgutils.h> ++#include <libswscale/swscale.h> ++} + #endif + + #include <stdint.h> +@@ -63,7 +67,7 @@ const double defFrameRate = 25.0; + VideoFFmpeg::VideoFFmpeg (HRESULT * hRslt) : VideoBase(), + m_codec(NULL), m_formatCtx(NULL), m_codecCtx(NULL), + m_frame(NULL), m_frameDeinterlaced(NULL), m_frameRGB(NULL), m_imgConvertCtx(NULL), +-m_deinterlace(false), m_preseek(0), m_videoStream(-1), m_baseFrameRate(25.0), ++m_deinterlace(false), m_preseek(0), m_videoStreamIndex(-1), m_baseFrameRate(25.0), + m_lastFrame(-1), m_eof(false), m_externTime(false), m_curPosition(-1), m_startTime(0), + m_captWidth(0), m_captHeight(0), m_captRate(0.f), m_isImage(false), + m_isThreaded(false), m_isStreaming(false), m_stopThread(false), m_cacheStarted(false) +@@ -144,20 +148,22 @@ AVFrame *VideoFFmpeg::allocFrameRGB() + frame = av_frame_alloc(); + if (m_format == RGBA32) + { +- avpicture_fill((AVPicture*)frame, +- (uint8_t*)MEM_callocN(avpicture_get_size( +- AV_PIX_FMT_RGBA, +- m_codecCtx->width, m_codecCtx->height), +- "ffmpeg rgba"), +- AV_PIX_FMT_RGBA, m_codecCtx->width, m_codecCtx->height); ++ av_image_fill_arrays(frame->data, ++ frame->linesize, ++ (uint8_t*)MEM_mallocN(av_image_get_buffer_size(AV_PIX_FMT_RGBA, m_codecCtx->width, m_codecCtx->height, 1), "ffmpeg rgba"), ++ AV_PIX_FMT_RGBA, ++ m_codecCtx->width, ++ m_codecCtx->height, ++ 1); + } else + { +- avpicture_fill((AVPicture*)frame, +- (uint8_t*)MEM_callocN(avpicture_get_size( +- AV_PIX_FMT_RGB24, +- m_codecCtx->width, m_codecCtx->height), +- "ffmpeg rgb"), +- AV_PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height); ++ av_image_fill_arrays(frame->data, ++ frame->linesize, ++ (uint8_t*)MEM_mallocN(av_image_get_buffer_size(AV_PIX_FMT_RGB24, m_codecCtx->width, m_codecCtx->height, 1), "ffmpeg rgba"), ++ AV_PIX_FMT_RGBA, ++ m_codecCtx->width, ++ m_codecCtx->height, ++ 1); + } + return frame; + } +@@ -172,12 +178,13 @@ void VideoFFmpeg::initParams (short width, short height, float rate, bool image) + } + + +-int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AVDictionary **formatParams) ++int VideoFFmpeg::openStream(const char *filename, const AVInputFormat *inputFormat, AVDictionary **formatParams) + { + AVFormatContext *formatCtx = NULL; +- int i, videoStream; +- AVCodec *codec; ++ int i, video_stream_index; ++ const AVCodec *codec; + AVCodecContext *codecCtx; ++ AVStream *video_stream; + + if (avformat_open_input(&formatCtx, filename, inputFormat, formatParams)!=0) + return -1; +@@ -188,65 +195,63 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV + return -1; + } + +- /* Find the first video stream */ +- videoStream=-1; +- for (i=0; i<formatCtx->nb_streams; i++) +- { ++ /* Find the video stream */ ++ video_stream_index = -1; ++ ++ for (i = 0; i < formatCtx->nb_streams; i++) { + if (formatCtx->streams[i] && +- get_codec_from_stream(formatCtx->streams[i]) && +- (get_codec_from_stream(formatCtx->streams[i])->codec_type==AVMEDIA_TYPE_VIDEO)) ++ formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) + { +- videoStream=i; ++ video_stream_index = i; + break; + } + } + +- if (videoStream==-1) ++ if (video_stream_index == -1) + { + avformat_close_input(&formatCtx); + return -1; + } + +- codecCtx = get_codec_from_stream(formatCtx->streams[videoStream]); ++ video_stream = formatCtx->streams[video_stream_index]; + + /* Find the decoder for the video stream */ +- codec=avcodec_find_decoder(codecCtx->codec_id); +- if (codec==NULL) +- { ++ codec = avcodec_find_decoder(video_stream->codecpar->codec_id); ++ if (codec == nullptr) { + avformat_close_input(&formatCtx); + return -1; + } +- codecCtx->workaround_bugs = 1; +- if (avcodec_open2(codecCtx, codec, NULL) < 0) ++ ++ codecCtx = avcodec_alloc_context3(NULL); ++ avcodec_parameters_to_context(codecCtx, video_stream->codecpar); ++ codecCtx->workaround_bugs = FF_BUG_AUTODETECT; ++ ++ if (avcodec_open2(codecCtx, codec, nullptr) < 0) + { + avformat_close_input(&formatCtx); + return -1; + } + +-#ifdef FFMPEG_OLD_FRAME_RATE +- if (codecCtx->frame_rate>1000 && codecCtx->frame_rate_base==1) +- codecCtx->frame_rate_base=1000; +- m_baseFrameRate = (double)codecCtx->frame_rate / (double)codecCtx->frame_rate_base; +-#else +- m_baseFrameRate = av_q2d(av_get_r_frame_rate_compat(formatCtx->streams[videoStream])); +-#endif +- if (m_baseFrameRate <= 0.0) ++ m_baseFrameRate = av_q2d(av_guess_frame_rate(formatCtx, video_stream, nullptr)); ++ if (m_baseFrameRate <= 0.0) { + m_baseFrameRate = defFrameRate; ++ } + + m_codec = codec; + m_codecCtx = codecCtx; + m_formatCtx = formatCtx; +- m_videoStream = videoStream; ++ m_videoStreamIndex = video_stream_index; + m_frame = av_frame_alloc(); + m_frameDeinterlaced = av_frame_alloc(); + + // allocate buffer if deinterlacing is required +- avpicture_fill((AVPicture*)m_frameDeinterlaced, +- (uint8_t*)MEM_callocN(avpicture_get_size( +- m_codecCtx->pix_fmt, +- m_codecCtx->width, m_codecCtx->height), +- "ffmpeg deinterlace"), +- m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height); ++ av_image_fill_arrays(m_frameDeinterlaced->data, ++ m_frameDeinterlaced->linesize, ++ (uint8_t*)MEM_mallocN(av_image_get_buffer_size(m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height, 1), "ffmpeg deinterlace"), ++ m_codecCtx->pix_fmt, ++ m_codecCtx->width, ++ m_codecCtx->height, ++ 1); + + // check if the pixel format supports Alpha + if (m_codecCtx->pix_fmt == AV_PIX_FMT_RGB32 || +@@ -321,8 +326,8 @@ void *VideoFFmpeg::cacheThread(void *data) + CachePacket *cachePacket; + bool endOfFile = false; + int frameFinished = 0; +- double timeBase = av_q2d(video->m_formatCtx->streams[video->m_videoStream]->time_base); +- int64_t startTs = video->m_formatCtx->streams[video->m_videoStream]->start_time; ++ double timeBase = av_q2d(video->m_formatCtx->streams[video->m_videoStreamIndex]->time_base); ++ int64_t startTs = video->m_formatCtx->streams[video->m_videoStreamIndex]->start_time; + + if (startTs == AV_NOPTS_VALUE) + startTs = 0; +@@ -340,17 +345,17 @@ void *VideoFFmpeg::cacheThread(void *data) + // free packet => packet cache is not full yet, just read more + if (av_read_frame(video->m_formatCtx, &cachePacket->packet)>=0) + { +- if (cachePacket->packet.stream_index == video->m_videoStream) ++ if (cachePacket->packet.stream_index == video->m_videoStreamIndex) + { + // make sure fresh memory is allocated for the packet and move it to queue +- av_dup_packet(&cachePacket->packet); ++ av_packet_ref(&cachePacket->packet, nullptr); + BLI_remlink(&video->m_packetCacheFree, cachePacket); + BLI_addtail(&video->m_packetCacheBase, cachePacket); + break; + } else { + // this is not a good packet for us, just leave it on free queue + // Note: here we could handle sound packet +- av_free_packet(&cachePacket->packet); ++ av_packet_unref(&cachePacket->packet); + frameFinished++; + } + +@@ -380,9 +385,8 @@ void *VideoFFmpeg::cacheThread(void *data) + BLI_remlink(&video->m_packetCacheBase, cachePacket); + // use m_frame because when caching, it is not used in main thread + // we can't use currentFrame directly because we need to convert to RGB first +- avcodec_decode_video2(video->m_codecCtx, +- video->m_frame, &frameFinished, +- &cachePacket->packet); ++ avcodec_send_packet(video->m_codecCtx, &cachePacket->packet); ++ frameFinished = avcodec_receive_frame(video->m_codecCtx, video->m_frame) == 0; + if (frameFinished) + { + AVFrame * input = video->m_frame; +@@ -393,9 +397,9 @@ void *VideoFFmpeg::cacheThread(void *data) + { + if (video->m_deinterlace) + { +- if (avpicture_deinterlace( +- (AVPicture*) video->m_frameDeinterlaced, +- (const AVPicture*) video->m_frame, ++ if (av_image_deinterlace( ++ video->m_frameDeinterlaced, ++ video->m_frame, + video->m_codecCtx->pix_fmt, + video->m_codecCtx->width, + video->m_codecCtx->height) >= 0) +@@ -420,7 +424,7 @@ void *VideoFFmpeg::cacheThread(void *data) + currentFrame = NULL; + } + } +- av_free_packet(&cachePacket->packet); ++ av_packet_unref(&cachePacket->packet); + BLI_addtail(&video->m_packetCacheFree, cachePacket); + } + if (currentFrame && endOfFile) +@@ -500,7 +504,7 @@ void VideoFFmpeg::stopCache() + while ((packet = (CachePacket *)m_packetCacheBase.first) != NULL) + { + BLI_remlink(&m_packetCacheBase, packet); +- av_free_packet(&packet->packet); ++ av_packet_unref(&packet->packet); + delete packet; + } + while ((packet = (CachePacket *)m_packetCacheFree.first) != NULL) +@@ -590,7 +594,7 @@ void VideoFFmpeg::openFile (char *filename) + void VideoFFmpeg::openCam (char *file, short camIdx) + { + // open camera source +- AVInputFormat *inputFormat; ++ const AVInputFormat *inputFormat; + AVDictionary *formatParams = NULL; + char filename[28], rateStr[20]; + +@@ -930,8 +934,8 @@ AVFrame *VideoFFmpeg::grabFrame(long position) + pthread_mutex_unlock(&m_cacheMutex); + } while (true); + } +- double timeBase = av_q2d(m_formatCtx->streams[m_videoStream]->time_base); +- int64_t startTs = m_formatCtx->streams[m_videoStream]->start_time; ++ double timeBase = av_q2d(m_formatCtx->streams[m_videoStreamIndex]->time_base); ++ int64_t startTs = m_formatCtx->streams[m_videoStreamIndex]->start_time; + if (startTs == AV_NOPTS_VALUE) + startTs = 0; + +@@ -947,18 +951,16 @@ AVFrame *VideoFFmpeg::grabFrame(long position) + { + while (av_read_frame(m_formatCtx, &packet)>=0) + { +- if (packet.stream_index == m_videoStream) ++ if (packet.stream_index == m_videoStreamIndex) + { +- avcodec_decode_video2( +- m_codecCtx, +- m_frame, &frameFinished, +- &packet); ++ avcodec_send_packet(m_codecCtx, &packet); ++ frameFinished = avcodec_receive_frame(m_codecCtx, m_frame) == 0; + if (frameFinished) + { + m_curPosition = (long)((packet.dts-startTs) * (m_baseFrameRate*timeBase) + 0.5); + } + } +- av_free_packet(&packet); ++ av_packet_unref(&packet); + if (position == m_curPosition+1) + break; + } +@@ -983,10 +985,10 @@ AVFrame *VideoFFmpeg::grabFrame(long position) + if (position <= m_preseek) + { + // we can safely go the beginning of the file +- if (av_seek_frame(m_formatCtx, m_videoStream, 0, AVSEEK_FLAG_BYTE) >= 0) ++ if (av_seek_frame(m_formatCtx, m_videoStreamIndex, 0, AVSEEK_FLAG_BYTE) >= 0) + { + // binary seek does not reset the timestamp, must do it now +- av_update_cur_dts(m_formatCtx, m_formatCtx->streams[m_videoStream], startTs); ++ av_update_cur_dts(m_formatCtx, m_formatCtx->streams[m_videoStreamIndex], startTs); + m_curPosition = 0; + } + } +@@ -994,7 +996,7 @@ AVFrame *VideoFFmpeg::grabFrame(long position) + #endif + { + // current position is now lost, guess a value. +- if (av_seek_frame(m_formatCtx, m_videoStream, pos, AVSEEK_FLAG_BACKWARD) >= 0) ++ if (av_seek_frame(m_formatCtx, m_videoStreamIndex, pos, AVSEEK_FLAG_BACKWARD) >= 0) + { + // current position is now lost, guess a value. + // It's not important because it will be set at this end of this function +@@ -1022,14 +1024,15 @@ AVFrame *VideoFFmpeg::grabFrame(long position) + // return the next frame. This is not quite correct, may need more work + while (av_read_frame(m_formatCtx, &packet) >= 0) + { +- if (packet.stream_index == m_videoStream) ++ if (packet.stream_index == m_videoStreamIndex) + { + AVFrame *input = m_frame; + short counter = 0; + + /* If m_isImage, while the data is not read properly (png, tiffs, etc formats may need several pass), else don't need while loop*/ + do { +- avcodec_decode_video2(m_codecCtx, m_frame, &frameFinished, &packet); ++ avcodec_send_packet(m_codecCtx, &packet); ++ frameFinished = avcodec_receive_frame(m_codecCtx, m_frame) == 0; + counter++; + } while ((input->data[0] == 0 && input->data[1] == 0 && input->data[2] == 0 && input->data[3] == 0) && counter < 10 && m_isImage); + +@@ -1052,15 +1055,15 @@ AVFrame *VideoFFmpeg::grabFrame(long position) + if ( input->data[0]==0 && input->data[1]==0 + && input->data[2]==0 && input->data[3]==0) + { +- av_free_packet(&packet); ++ av_packet_unref(&packet); + break; + } + + if (m_deinterlace) + { +- if (avpicture_deinterlace( +- (AVPicture*) m_frameDeinterlaced, +- (const AVPicture*) m_frame, ++ if (av_image_deinterlace( ++ m_frameDeinterlaced, ++ m_frame, + m_codecCtx->pix_fmt, + m_codecCtx->width, + m_codecCtx->height) >= 0) +@@ -1076,12 +1079,12 @@ AVFrame *VideoFFmpeg::grabFrame(long position) + m_codecCtx->height, + m_frameRGB->data, + m_frameRGB->linesize); +- av_free_packet(&packet); ++ av_packet_unref(&packet); + frameLoaded = true; + break; + } + } +- av_free_packet(&packet); ++ av_packet_unref(&packet); + } + m_eof = m_isFile && !frameLoaded; + if (frameLoaded) +diff --git a/blender-2.79b/source/gameengine/VideoTexture/VideoFFmpeg.h b/blender-2.79b/source/gameengine/VideoTexture/VideoFFmpeg.h +index 0a49a0b..b25d569 100644 +--- a/blender-2.79b/source/gameengine/VideoTexture/VideoFFmpeg.h ++++ b/blender-2.79b/source/gameengine/VideoTexture/VideoFFmpeg.h +@@ -36,32 +36,17 @@ + #if defined(__FreeBSD__) + # include <inttypes.h> + #endif ++ ++struct AVCodecContext; + extern "C" { + #include <pthread.h> + #include "ffmpeg_compat.h" + #include "DNA_listBase.h" + #include "BLI_threads.h" + #include "BLI_blenlib.h" ++#include <libavcodec/avcodec.h> + } + +-#if LIBAVFORMAT_VERSION_INT < (49 << 16) +-# define FFMPEG_OLD_FRAME_RATE 1 +-#else +-# define FFMPEG_CODEC_IS_POINTER 1 +-#endif +- +-#ifdef FFMPEG_CODEC_IS_POINTER +-static inline AVCodecContext *get_codec_from_stream(AVStream* stream) +-{ +- return stream->codec; +-} +-#else +-static inline AVCodecContext *get_codec_from_stream(AVStream* stream) +-{ +- return &stream->codec; +-} +-#endif +- + #include "VideoBase.h" + + #define CACHE_FRAME_SIZE 10 +@@ -106,7 +91,7 @@ public: + + protected: + // format and codec information +- AVCodec *m_codec; ++ const AVCodec *m_codec; + AVFormatContext *m_formatCtx; + AVCodecContext *m_codecCtx; + // raw frame extracted from video file +@@ -122,7 +107,7 @@ protected: + // number of frame of preseek + int m_preseek; + // order number of stream holding the video in format context +- int m_videoStream; ++ int m_videoStreamIndex; + + // the actual frame rate + double m_baseFrameRate; +@@ -173,7 +158,7 @@ protected: + double actFrameRate (void) { return m_frameRate * m_baseFrameRate; } + + /// common function to video file and capture +- int openStream(const char *filename, AVInputFormat *inputFormat, AVDictionary **formatParams); ++ int openStream(const char *filename, const AVInputFormat *inputFormat, AVDictionary **formatParams); + + /// check if a frame is available and load it in pFrame, return true if a frame could be retrieved + AVFrame* grabFrame(long frame); @@ -4,10 +4,7 @@ # shellcheck disable=SC2191 # preserve current _CMAKE_FLAGS initialization. # Configuration. -_branch="blender2.7" -_fragment=${FRAGMENT:-#branch=${_branch}} [[ -v CUDA_ARCH ]] && _cuda_capability=${CUDA_ARCH} -_commit_url="https://git.blender.org/gitweb/gitweb.cgi/blender.git/patch" #some extra, unofficially supported stuff goes here: ((TRAVIS)) && _cuda_capability+=(sm_50 sm_52 sm_60 sm_61 sm_70 sm_75) # Travis memory limit is not enough to build for arch 3.x. @@ -16,69 +13,71 @@ _commit_url="https://git.blender.org/gitweb/gitweb.cgi/blender.git/patch" ((DISABLE_CUDA)) && optdepends+=('cuda: CUDA support in Cycles') || makedepends+=('cuda') pkgname=blender-2.7 -pkgver=2.79b.r71421.e045fe53f1b -pkgrel=3 -pkgdesc="Maintnance version of Blenders ${_branch} branch" +pkgver=2.79b +pkgrel=4 +pkgdesc="Keeping Blender 2.79b up-to-date with modern compiler and libs" arch=('i686' 'x86_64') url="https://blender.org/" -depends+=('alembic' 'libgl' 'python' 'python-numpy' 'openjpeg2' - 'ffmpeg' 'fftw' 'openal' 'freetype2' 'libxi' 'openimageio' 'opencolorio1' - 'openvdb' 'opencollada' 'opensubdiv' 'openshadinglanguage' 'libtiff' 'libpng') -makedepends+=('git' 'cmake' 'boost' 'mesa' 'llvm') +depends+=('alembic' 'libgl' 'python' 'python-numpy' 'openjpeg2' 'ffmpeg' + 'fftw' 'openal' 'freetype2' 'libxi' 'openimageio' 'opencolorio1' + 'openvdb' 'opencollada' 'opensubdiv' 'openshadinglanguage' 'libtiff' + 'libpng') +makedepends+=('cmake' 'boost' 'mesa' 'llvm') provides=('blender-2.7') license=('GPL') -# NOTE: the source array has to be kept in sync with .gitmodules -# the submodules has to be stored in path ending with git to match -# the path in .gitmodules. -# More info: -# http://wiki.blender.org/index.php/Dev:Doc/Tools/Git -source=("git://git.blender.org/blender.git${_fragment}" - 'blender-addons.git::git://git.blender.org/blender-addons.git' - 'blender-addons-contrib.git::git://git.blender.org/blender-addons-contrib.git' - 'blender-translations.git::git://git.blender.org/blender-translations.git' - 'blender-dev-tools.git::git://git.blender.org/blender-dev-tools.git' +source=('https://download.blender.org/source/blender-2.79b.tar.gz' SelectCudaComputeArch.patch - stl_export_iter.patch - python3.7.patch - python3.8.patch - 'python3.9.patch' # ::https://git.blender.org/gitweb/gitweb.cgi/blender.git/patch/56d0df51a36fdce7ec2d1fbb7b47b1d95b591b5f - 'python3.9_2.patch' # ::https://git.blender.org/gitweb/gitweb.cgi/blender.git/patch/5edba9b42f684bf8b99894bb6988e7f46180e12c - openvdb7.patch - openvdb8.patch # ::${_commit_url}/37889011070ff2ec52159690f652238d2b325185 - cycles.patch - openexr3.patch opencolorio1.patch - ) -sha256sums=('SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - 'SKIP' - '28e407e3aefdd9bd76805b6033ada0b5b41dd6183bcf4f58a642c109f10c1876' - '649c21a12a1bfc0207078e1e58b4813a3e898c6dbbbb35d21e1de7c9e8f1985a' - '47811284f080e38bcfbfb1f7346279245815a064df092989336b0bf3fe4530e9' - '229853b98bb62e1dec835aea6b2eab4c3dabbc8be591206573a3c1b85f10be59' - 'd106248d55045f5ef913bf6243ad74a76f6282264d9ee4c9b87ec4a3d2e2064b' - 'b2a2bc5de8d3b730e49d1f50cb025c1dfdbcb66c58ead573322585b6a887d3a7' - 'c4079c4c142516d9cd476f5a3cafddf4068f0950c3c11ea4da9cf999c5ccc1f9' - 'edfd784f8497417660c0b9fdc97893fd0d77764d0bc10f4cb92a9082f41bae75' - 'd245f02d73bd5b767ffa49d369383d7cd6ae5e57b89c2975a78c1015e1884864' - 'e7d75a5ef5cb6452b45f6e1e80b6fe69e2630878b1f4f6d53bf0e36ced237712' - 'b3fa6ef21383287d0f8e7c3b848f3cf02186f9e3a0e8f194f3ca1323935e5e0e') - -pkgver() { -# shellcheck disable=SC2164 - cd "$srcdir/blender" - printf "2.79b.r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)" -} + 0000_misc.patch + 0001_openexr3.patch + 0002_opencollada1_6_68.patch + 0003_openvdb.patch + 0004_openimageio.patch + 0005_cycles.patch + 0006_python3_7.patch + 0007_python3_8.patch + 0008_python3_9.patch + 0009_python3_10.patch + 0010_python3_11.patch + 0011_ffmpeg.patch) +sha512sums=('2db21ace446168dd683cdb5aad9dec001f8888ae4e9603a04ddb44fb78489ded827deb07e83712b0f1118a0e7bf66f2a5d935dc4ebb3a6703d72672ff414367f' + '15b10bf91c759a8ab6519f3c02f54e7d3ad105eb915663e0de2a65b38d1e42b55cc383bae96a1507f1eb55200eb14ebe904b6a7b772b4073aa6a53ac5d4dd194' + '4126ddaaab2dc8c45cd850353a2e4a0e6ff2ef4476f9a533916e59fc57e426ca3110f7b3d38685fffd97b969208f941359122b693584c2a70a3f8420a832214b' + 'd7b6f1707ad902743a3f08c6423aabd7abd0841eb78404419884d7c0b02affc1b6c3eafea55f9db04bce5e27d22cfd0ec63153c61a5fa2c3227de54a09f0895d' + '0a8bd2ad7e199f95145bd0a66471686e0c545b071c73e6a659b570c001a860504f0970818fd686f52be9f5c18bd294c0efbede5c058ac96a4682e54b6235aac0' + '435e33926766a143cb6445a0c3219c9126b5d77e8114601a1f07848120b823ef2d1789bccb10079436b89eb9f894df54571ed50cde0713af857a8148be8f18ae' + 'fc86d7a9a46e521ec22b2d87dfb023a71bfde624c4a6ddcf137038c7f46b97d614f8cb99951489a251cb2ea28460690cc0e5eb9ac6f2ccacc27c0052d137dcc9' + 'c8bd5ee00f062760ae3a2493750b2eb66d0368955ebb443aad5313f91c1fd0680df239eb1ca957e79cda482c084a023efc60e4341c198d55f897415cf79de35d' + '3e3bef5e27279fc9c4f66398cd04a51a1ed268b7b99df2cf0151ed63994b742e39917e525ddac666d12a3df02a3ecef7dbe03da52c6be1aa143a3be960acbc5f' + '7c98cf29fa22e7e816789254e43ed0f5595529f8ed37c88abac8667a80bf2bee9f020fa204a45800586e4d0c2de977df9ceda6d8bc0b77c806743f761b6ffa9f' + '7effbd675b2167cc4c25a36d58f08824b2770e7b57fee93fd909a715003ee076ffcfc7e91cf965b9836da2fa54246fb68bbe613e44d312702298a5386b124dfa' + 'a556445f27eaaba839d0efcfa70c530c269c7189e194c93b929044a54697f3606401dfdf5dbec05b181c26ba82d2b16560f2db7cd579104e0a0a322525cecaff' + 'ecae55f642bf7f08edc56f8740a9fec650a3617f0ce7c7ba5b3211994ad8c46dc8fbbe897405699d46cb01c15129c0d4d9184657daeaf41172533195cdbbb104' + 'de254cb5e43fe05c3b5e70df881c1ab847b58c383d8df28be6d044c058d4776a5a3d57f710eb3cf0a83b43c95fac29f772c446a23e0f9c2bf73d1dcc8b23b67c' + 'a0ff4f4dbc3624692c16d45f632cda1362173a5685c85e62d54af1d63d5a421867a5eb89b5b1c5b72bbceef98664d96b54901790470cbe67f701c582858af0ed') prepare() { - # update the submodules - git -C "$srcdir/blender" -c protocol.file.allow=always submodule update --init --recursive --remote + # Apply CUDA patch if [ ! -v _cuda_capability ] && grep -q nvidia <(lsmod); then - git -C "$srcdir/blender" apply -v "${srcdir}"/SelectCudaComputeArch.patch + patch -p1 < SelectCudaComputeArch.patch fi - git -C "$srcdir/blender" apply -v "${srcdir}"/{python3.7,stl_export_iter,python3.{8,9,9_2},openvdb{7,8},cycles,open{exr3,colorio1}}.patch + + # Build with OpenColorIO 1 for now + patch -p1 < opencolorio1.patch + + # Apply patches to build with modern libs and compiler + patch -p1 < 0000_misc.patch + patch -p1 < 0001_openexr3.patch + patch -p1 < 0002_opencollada1_6_68.patch + patch -p1 < 0003_openvdb.patch + patch -p1 < 0004_openimageio.patch + patch -p1 < 0005_cycles.patch + patch -p1 < 0006_python3_7.patch + patch -p1 < 0007_python3_8.patch + patch -p1 < 0008_python3_9.patch + patch -p1 < 0009_python3_10.patch + patch -p1 < 0010_python3_11.patch + patch -p1 < 0011_ffmpeg.patch } build() { @@ -100,8 +99,8 @@ build() { fi ((DISABLE_NINJA)) && generator="Unix Makefiles" || generator="Ninja" - cmake -G "$generator" -S "$srcdir/blender" -B "$srcdir/build" \ - -C "${srcdir}/blender/build_files/cmake/config/blender_release.cmake" \ + cmake -G "$generator" -S "$srcdir/blender-2.79b" -B "$srcdir/build" \ + -C "${srcdir}/blender-2.79b/build_files/cmake/config/blender_release.cmake" \ -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_BUILD_TYPE=Release \ -DWITH_INSTALL_PORTABLE=OFF \ @@ -111,6 +110,16 @@ build() { -DWITH_PYTHON_INSTALL=OFF \ -DPYTHON_VERSION="${_pyver}" \ -DWITH_LLVM=ON \ + -DWITH_CODEC_FFMPEG=ON \ + -DWITH_CYCLES=ON \ + -DWITH_OPENCOLLADA=ON \ + -DWITH_OPENCOLORIO=ON \ + -DWITH_OPENVDB=ON \ + -DWITH_OPENIMAGEIO=ON \ + -DWITH_GAMEENGINE=ON \ + -DWITH_PLAYER=ON \ + -DWITH_PYTHON_MODULE=OFF \ + -DWITH_CYCLES_OSL=NO "${_CMAKE_FLAGS[@]}" export NINJA_STATUS="[%p | %f<%r<%u | %cbps ] " # shellcheck disable=SC2086 # allow MAKEFLAGS to split when multiple flags provided. diff --git a/SelectCudaComputeArch.patch b/SelectCudaComputeArch.patch index ab63fd128490..385f532ac91c 100644 --- a/SelectCudaComputeArch.patch +++ b/SelectCudaComputeArch.patch @@ -1,7 +1,7 @@ diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index d0f473a2939..90fcb40107a 100644 ---- a/intern/cycles/cmake/external_libs.cmake -+++ b/intern/cycles/cmake/external_libs.cmake +--- a/blender-2.79b/intern/cycles/cmake/external_libs.cmake ++++ b/blender-2.79b/intern/cycles/cmake/external_libs.cmake @@ -41,6 +41,11 @@ if(WITH_CYCLES_CUDA_BINARIES OR NOT WITH_CUDA_DYNLOAD) find_package(CUDA) # Try to auto locate CUDA toolkit if(CUDA_FOUND) diff --git a/cycles.patch b/cycles.patch deleted file mode 100644 index 9d949f95058b..000000000000 --- a/cycles.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h -index 3990a22aefd..8b2faf3afe4 100644 ---- a/intern/cycles/kernel/osl/osl_services.h -+++ b/intern/cycles/kernel/osl/osl_services.h -@@ -92,7 +92,7 @@ public: - bool getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name, - TypeDesc type, void *val, bool derivatives) override; - -- TextureSystem::TextureHandle *get_texture_handle(ustring filename) override; -+ TextureSystem::TextureHandle *get_texture_handle(ustring filename); - - bool good(TextureSystem::TextureHandle *texture_handle) override; - -@@ -145,7 +145,7 @@ public: - int subimage, - ustring dataname, - TypeDesc datatype, -- void *data) override; -+ void *data); - - static bool get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, - TypeDesc type, bool derivatives, void *val); diff --git a/opencolorio1.patch b/opencolorio1.patch index 89fbbd65455d..7e52cd057d3b 100644 --- a/opencolorio1.patch +++ b/opencolorio1.patch @@ -1,7 +1,7 @@ diff --git a/build_files/cmake/Modules/FindOpenColorIO.cmake b/build_files/cmake/Modules/FindOpenColorIO.cmake index 090032e06ec..f5db181d73d 100644 ---- a/build_files/cmake/Modules/FindOpenColorIO.cmake -+++ b/build_files/cmake/Modules/FindOpenColorIO.cmake +--- a/blender-2.79b/build_files/cmake/Modules/FindOpenColorIO.cmake ++++ b/blender-2.79b/build_files/cmake/Modules/FindOpenColorIO.cmake @@ -28,7 +28,7 @@ IF(NOT OPENCOLORIO_ROOT_DIR AND NOT $ENV{OPENCOLORIO_ROOT_DIR} STREQUAL "") ENDIF() @@ -11,7 +11,7 @@ index 090032e06ec..f5db181d73d 100644 yaml-cpp tinyxml ) -@@ -40,7 +40,7 @@ SET(_opencolorio_SEARCH_DIRS +@@ -44,7 +44,7 @@ SET(_opencolorio_SEARCH_DIRS FIND_PATH(OPENCOLORIO_INCLUDE_DIR NAMES @@ -22,9 +22,9 @@ index 090032e06ec..f5db181d73d 100644 PATH_SUFFIXES diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc index 0e25c89f5d7..f1f99de4bd8 100644 ---- a/intern/opencolorio/ocio_impl.cc -+++ b/intern/opencolorio/ocio_impl.cc -@@ -26,7 +26,7 @@ +--- a/blender-2.79b/intern/opencolorio/ocio_impl.cc ++++ b/blender-2.79b/intern/opencolorio/ocio_impl.cc +@@ -33,7 +33,7 @@ # pragma warning(push) # pragma warning(disable : 4251 4275) #endif @@ -35,9 +35,9 @@ index 0e25c89f5d7..f1f99de4bd8 100644 #endif diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index df6adc8f34b..24d1ec8a871 100644 ---- a/intern/opencolorio/ocio_impl_glsl.cc -+++ b/intern/opencolorio/ocio_impl_glsl.cc -@@ -40,7 +40,7 @@ +--- a/blender-2.79b/intern/opencolorio/ocio_impl_glsl.cc ++++ b/blender-2.79b/intern/opencolorio/ocio_impl_glsl.cc +@@ -43,7 +43,7 @@ # pragma warning(push) # pragma warning(disable : 4251 4275) #endif @@ -46,16 +46,4 @@ index df6adc8f34b..24d1ec8a871 100644 #ifdef _MSC_VER # pragma warning(pop) #endif -diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp -index 8403a636e1c..54abe4cfa3c 100644 ---- a/intern/cycles/render/shader.cpp -+++ b/intern/cycles/render/shader.cpp -@@ -35,7 +35,7 @@ - #include "util/util_murmurhash.h" - - #ifdef WITH_OCIO --# include <OpenColorIO/OpenColorIO.h> -+# include <OpenColorIO1/OpenColorIO.h> - namespace OCIO = OCIO_NAMESPACE; - #endif - + diff --git a/openexr3.patch b/openexr3.patch deleted file mode 100644 index a60f5f99bab6..000000000000 --- a/openexr3.patch +++ /dev/null @@ -1,57 +0,0 @@ -diff --git a/build_files/cmake/Modules/FindOpenEXR.cmake b/build_files/cmake/Modules/FindOpenEXR.cmake -index 090f80b8df7..a2f7b4c622b 100644 ---- a/build_files/cmake/Modules/FindOpenEXR.cmake -+++ b/build_files/cmake/Modules/FindOpenEXR.cmake -@@ -34,11 +34,10 @@ ENDIF() - SET(_openexr_libs_ver_init "2.0") - - SET(_openexr_FIND_COMPONENTS -- Half - Iex -- IlmImf -- IlmThread - Imath -+ OpenEXR -+ IlmThread - ) - - SET(_openexr_SEARCH_DIRS -@@ -120,7 +119,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenEXR DEFAULT_MSG - IF(OPENEXR_FOUND) - SET(OPENEXR_LIBRARIES ${_openexr_LIBRARIES}) - # Both include paths are needed because of dummy OSL headers mixing #include <OpenEXR/foo.h> and #include <foo.h> :( -- SET(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR}/OpenEXR) -+ SET(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR_INCLUDE_DIR}/OpenEXR ${OPENEXR_INCLUDE_DIR}/Imath) - ENDIF() - - MARK_AS_ADVANCED( -diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp -index a254111e489..50aa6d784f6 100644 ---- a/source/blender/imbuf/intern/openexr/openexr_api.cpp -+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp -@@ -37,10 +37,12 @@ - #include <ImfVersion.h> - #include <ImathBox.h> - #include <ImfArray.h> -+#include <ImfFrameBuffer.h> - #include <ImfIO.h> - #include <ImfChannelList.h> - #include <ImfPixelType.h> - #include <ImfInputFile.h> -+#include <ImfInt64.h> - #include <ImfOutputFile.h> - #include <ImfCompression.h> - #include <ImfCompressionAttribute.h> -diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc -index 68eb1652210..679f3deaf8c 100644 ---- a/source/blender/alembic/intern/abc_transform.cc -+++ b/source/blender/alembic/intern/abc_transform.cc -@@ -16,7 +16,7 @@ - - #include "abc_transform.h" - --#include <OpenEXR/ImathBoxAlgo.h> -+#include <Imath/ImathBoxAlgo.h> - - #include "abc_util.h" - diff --git a/openvdb7.patch b/openvdb7.patch deleted file mode 100644 index 630605a6c353..000000000000 --- a/openvdb7.patch +++ /dev/null @@ -1,29 +0,0 @@ -diff --git a/intern/openvdb/CMakeLists.txt b/intern/openvdb/CMakeLists.txt -index 9ac0817903b..e60d45b7f64 100644 ---- a/intern/openvdb/CMakeLists.txt -+++ b/intern/openvdb/CMakeLists.txt -@@ -23,6 +23,8 @@ - # - # ***** END GPL LICENSE BLOCK ***** - -+set (CMAKE_CXX_STANDARD 14) -+ - set(INC - . - intern -diff --git a/intern/openvdb/intern/openvdb_writer.cc b/intern/openvdb/intern/openvdb_writer.cc -index 900c5371682..f209ec758b6 100644 ---- a/intern/openvdb/intern/openvdb_writer.cc -+++ b/intern/openvdb/intern/openvdb_writer.cc -@@ -39,11 +39,7 @@ void OpenVDBWriter::insert(const openvdb::GridBase::Ptr &grid) - - void OpenVDBWriter::insert(const openvdb::GridBase &grid) - { --#if (OPENVDB_LIBRARY_MAJOR_VERSION_NUMBER <= 3) || defined(OPENVDB_3_ABI_COMPATIBLE) -- m_grids->push_back(grid.copyGrid()); --#else - m_grids->push_back(grid.copyGridWithNewTree()); --#endif - } - - void OpenVDBWriter::insertFloatMeta(const openvdb::Name &name, const float value) diff --git a/openvdb8.patch b/openvdb8.patch deleted file mode 100644 index bb44c7946cdf..000000000000 --- a/openvdb8.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/intern/openvdb/openvdb_util.cc b/intern/openvdb/openvdb_util.cc -index a221a537851..899b41ff09b 100644 ---- a/intern/openvdb/openvdb_util.cc -+++ b/intern/openvdb/openvdb_util.cc -@@ -27,5 +27,10 @@ ScopeTimer::ScopeTimer(const std::string &message) : m_message(message), m_timer - - ScopeTimer::~ScopeTimer() - { -- std::printf("%s: %fms\n", m_message.c_str(), m_timer.delta()); -+#if OPENVDB_LIBRARY_MAJOR_VERSION_NUMBER >= 7 -+ double delta = m_timer.milliseconds(); -+#else -+ double delta = m_timer.delta(); /* Deprecated in OpenVDB 7. */ -+#endif -+ std::printf("%s: %fms\n", m_message.c_str(), delta); - } diff --git a/python3.7.patch b/python3.7.patch deleted file mode 100644 index 1b93964aecaf..000000000000 --- a/python3.7.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/object_facemap_auto/auto_fmap_widgets.py b/object_facemap_auto/auto_fmap_widgets.py -index 5b26f75..646e844 100644 ---- a/release/scripts/addons_contrib/object_facemap_auto/auto_fmap_widgets.py -+++ b/release/scripts/addons_contrib/object_facemap_auto/auto_fmap_widgets.py -@@ -324,7 +324,7 @@ class AutoFaceMapWidgetGroup(ManipulatorGroup): - - # foo;bar=baz;bonzo=bingo --> {"bar": baz", "bonzo": bingo} - mpr.fmap_target_rules = dict( -- item.partition("=")[::2] for item in fmap_rules, -+ item.partition("=")[::2] for item in fmap_rules - ) - - # XXX, we might want to have some way to extract a 'center' from a face-map diff --git a/python3.8.patch b/python3.8.patch deleted file mode 100644 index ffaa3e2a914b..000000000000 --- a/python3.8.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 4b663ecf264020b1d7003a137ce84b06d7ec4ce6 Mon Sep 17 00:00:00 2001 -From: bartus <szczepaniak.bartek+github@gmail.com> -Date: Sat, 16 Nov 2019 20:29:30 +0100 -Subject: [PATCH] Add python 3.8 support. - ---- - source/blender/python/generic/py_capi_utils.c | 27 +++++++++++++++---- - 1 file changed, 22 insertions(+), 5 deletions(-) - -diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c -index 545e0506f84..a7eab70600b 100644 ---- a/source/blender/python/generic/py_capi_utils.c -+++ b/source/blender/python/generic/py_capi_utils.c -@@ -696,9 +696,16 @@ PyObject *PyC_UnicodeFromByte(const char *str) - ****************************************************************************/ - PyObject *PyC_DefaultNameSpace(const char *filename) - { -+ #if PY_VERSION_HEX >= 0x03080000 -+ PyObject *modules = PyImport_GetModuleDict(); -+ PyObject *builtins = PyEval_GetBuiltins(); -+ #else - PyInterpreterState *interp = PyThreadState_GET()->interp; -+ PyObject *modules = interp->modules; -+ PyObject *builtins = interp->builtins; -+ #endif - PyObject *mod_main = PyModule_New("__main__"); -- PyDict_SetItemString(interp->modules, "__main__", mod_main); -+ PyDict_SetItemString(modules, "__main__", mod_main); - Py_DECREF(mod_main); /* sys.modules owns now */ - PyModule_AddStringConstant(mod_main, "__name__", "__main__"); - if (filename) { -@@ -706,8 +713,8 @@ PyObject *PyC_DefaultNameSpace(const char *filename) - * note: this wont map to a real file when executing text-blocks and buttons. */ - PyModule_AddObject(mod_main, "__file__", PyC_UnicodeFromByte(filename)); - } -- PyModule_AddObject(mod_main, "__builtins__", interp->builtins); -- Py_INCREF(interp->builtins); /* AddObject steals a reference */ -+ PyModule_AddObject(mod_main, "__builtins__", builtins); -+ Py_INCREF(builtins); /* AddObject steals a reference */ - return PyModule_GetDict(mod_main); - } - -@@ -734,15 +741,25 @@ bool PyC_NameSpace_ImportArray(PyObject *py_dict, const char *imports[]) - /* restore MUST be called after this */ - void PyC_MainModule_Backup(PyObject **main_mod) - { -+ #if PY_VERSION_HEX >= 0x03080000 -+ PyObject *modules = PyImport_GetModuleDict(); -+ #else - PyInterpreterState *interp = PyThreadState_GET()->interp; -- *main_mod = PyDict_GetItemString(interp->modules, "__main__"); -+ PyObject *modules = interp->modules; -+ #endif -+ *main_mod = PyDict_GetItemString(modules, "__main__"); - Py_XINCREF(*main_mod); /* don't free */ - } - - void PyC_MainModule_Restore(PyObject *main_mod) - { -+ #if PY_VERSION_HEX >= 0x03080000 -+ PyObject *modules = PyImport_GetModuleDict(); -+ #else - PyInterpreterState *interp = PyThreadState_GET()->interp; -- PyDict_SetItemString(interp->modules, "__main__", main_mod); -+ PyObject *modules = interp->modules; -+ #endif -+ PyDict_SetItemString(modules, "__main__", main_mod); - Py_XDECREF(main_mod); - } - --- -2.24.0 - diff --git a/python3.9.patch b/python3.9.patch deleted file mode 100644 index f4d7869d09f3..000000000000 --- a/python3.9.patch +++ /dev/null @@ -1,141 +0,0 @@ -diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c -index 19fc05e66ea..5e10baa43ac 100644 ---- a/source/blender/python/mathutils/mathutils_Matrix.c -+++ b/source/blender/python/mathutils/mathutils_Matrix.c -@@ -43,7 +43,8 @@ static PyObject *Matrix_copy_notest(MatrixObject *self, const float *matrix); - static PyObject *Matrix_copy(MatrixObject *self); - static PyObject *Matrix_deepcopy(MatrixObject *self, PyObject *args); - static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value); --static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self); -+static PyObject *matrix__apply_to_copy(PyObject *(*matrix_func)(MatrixObject *), -+ MatrixObject *self); - static PyObject *MatrixAccess_CreatePyObject(MatrixObject *matrix, const eMatrixAccess_t type); - - static int matrix_row_vector_check(MatrixObject *mat, VectorObject *vec, int row) -@@ -380,14 +381,15 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) - return NULL; - } - --static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self) -+static PyObject *matrix__apply_to_copy(PyObject *(*matrix_func)(MatrixObject *), -+ MatrixObject *self) - { - PyObject *ret = Matrix_copy(self); - if (ret) { -- PyObject *ret_dummy = matrix_func(ret); -+ PyObject *ret_dummy = matrix_func((MatrixObject *)ret); - if (ret_dummy) { - Py_DECREF(ret_dummy); -- return (PyObject *)ret; -+ return ret; - } - else { /* error */ - Py_DECREF(ret); -@@ -1593,7 +1595,7 @@ PyDoc_STRVAR(Matrix_adjugated_doc, - ); - static PyObject *Matrix_adjugated(MatrixObject *self) - { -- return matrix__apply_to_copy((PyNoArgsFunction)Matrix_adjugate, self); -+ return matrix__apply_to_copy(Matrix_adjugate, self); - } - - PyDoc_STRVAR(Matrix_rotate_doc, -@@ -1799,7 +1801,7 @@ PyDoc_STRVAR(Matrix_transposed_doc, - ); - static PyObject *Matrix_transposed(MatrixObject *self) - { -- return matrix__apply_to_copy((PyNoArgsFunction)Matrix_transpose, self); -+ return matrix__apply_to_copy(Matrix_transpose, self); - } - - /*---------------------------matrix.normalize() ------------------*/ -@@ -1846,7 +1848,7 @@ PyDoc_STRVAR(Matrix_normalized_doc, - ); - static PyObject *Matrix_normalized(MatrixObject *self) - { -- return matrix__apply_to_copy((PyNoArgsFunction)Matrix_normalize, self); -+ return matrix__apply_to_copy(Matrix_normalize, self); - } - - /*---------------------------matrix.zero() -----------------------*/ -diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c -index 7255c0028d7..89c448d6413 100644 ---- a/source/blender/python/mathutils/mathutils_Quaternion.c -+++ b/source/blender/python/mathutils/mathutils_Quaternion.c -@@ -35,7 +35,8 @@ - - #define QUAT_SIZE 4 - --static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self); -+static PyObject *quat__apply_to_copy(PyObject *(*quat_func)(QuaternionObject *), -+ QuaternionObject *self); - static void quat__axis_angle_sanitize(float axis[3], float *angle); - static PyObject *Quaternion_copy(QuaternionObject *self); - static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args); -@@ -376,7 +377,7 @@ PyDoc_STRVAR(Quaternion_normalized_doc, - ); - static PyObject *Quaternion_normalized(QuaternionObject *self) - { -- return quat__apply_to_copy((PyNoArgsFunction)Quaternion_normalize, self); -+ return quat__apply_to_copy(Quaternion_normalize, self); - } - - PyDoc_STRVAR(Quaternion_invert_doc, -@@ -404,7 +405,7 @@ PyDoc_STRVAR(Quaternion_inverted_doc, - ); - static PyObject *Quaternion_inverted(QuaternionObject *self) - { -- return quat__apply_to_copy((PyNoArgsFunction)Quaternion_invert, self); -+ return quat__apply_to_copy(Quaternion_invert, self); - } - - PyDoc_STRVAR(Quaternion_identity_doc, -@@ -468,7 +469,7 @@ PyDoc_STRVAR(Quaternion_conjugated_doc, - ); - static PyObject *Quaternion_conjugated(QuaternionObject *self) - { -- return quat__apply_to_copy((PyNoArgsFunction)Quaternion_conjugate, self); -+ return quat__apply_to_copy(Quaternion_conjugate, self); - } - - PyDoc_STRVAR(Quaternion_copy_doc, -@@ -1143,10 +1144,11 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw - return Quaternion_CreatePyObject(quat, type); - } - --static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self) -+static PyObject *quat__apply_to_copy(PyObject *(*quat_func)(QuaternionObject *), -+ QuaternionObject *self) - { - PyObject *ret = Quaternion_copy(self); -- PyObject *ret_dummy = quat_func(ret); -+ PyObject *ret_dummy = quat_func((QuaternionObject *)ret); - if (ret_dummy) { - Py_DECREF(ret_dummy); - return ret; -diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c -index b3bba79280d..626eaa6505f 100644 ---- a/source/blender/python/mathutils/mathutils_Vector.c -+++ b/source/blender/python/mathutils/mathutils_Vector.c -@@ -94,10 +94,10 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) - return Vector_CreatePyObject_alloc(vec, size, type); - } - --static PyObject *vec__apply_to_copy(PyNoArgsFunction vec_func, VectorObject *self) -+static PyObject *vec__apply_to_copy(PyObject *(*vec_func)(VectorObject *), VectorObject *self) - { - PyObject *ret = Vector_copy(self); -- PyObject *ret_dummy = vec_func(ret); -+ PyObject *ret_dummy = vec_func((VectorObject *)ret); - if (ret_dummy) { - Py_DECREF(ret_dummy); - return (PyObject *)ret; -@@ -380,7 +380,7 @@ PyDoc_STRVAR(Vector_normalized_doc, - ); - static PyObject *Vector_normalized(VectorObject *self) - { -- return vec__apply_to_copy((PyNoArgsFunction)Vector_normalize, self); -+ return vec__apply_to_copy(Vector_normalize, self); - } - - PyDoc_STRVAR(Vector_resize_doc, diff --git a/python3.9_2.patch b/python3.9_2.patch deleted file mode 100644 index a1de7b401485..000000000000 --- a/python3.9_2.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/source/blender/python/generic/bpy_threads.c b/source/blender/python/generic/bpy_threads.c -index 5507aa73183..4807c1f5071 100644 ---- a/source/blender/python/generic/bpy_threads.c -+++ b/source/blender/python/generic/bpy_threads.c -@@ -29,14 +29,11 @@ - /* analogue of PyEval_SaveThread() */ - BPy_ThreadStatePtr BPY_thread_save(void) - { -- PyThreadState *tstate = PyThreadState_Swap(NULL); -- /* note: tstate can be NULL when quitting Blender */ -- -- if (tstate && PyEval_ThreadsInitialized()) { -- PyEval_ReleaseLock(); -+ /* The thread-state can be NULL when quitting Blender. */ -+ if (_PyThreadState_UncheckedGet()) { -+ return (BPy_ThreadStatePtr)PyEval_SaveThread(); - } -- -- return (BPy_ThreadStatePtr)tstate; -+ return NULL; - } - - /* analogue of PyEval_RestoreThread() */ diff --git a/stl_export_iter.patch b/stl_export_iter.patch deleted file mode 100644 index edf985e88ca1..000000000000 --- a/stl_export_iter.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/release/scripts/addons/io_mesh_stl/blender_utils.py b/release/scripts/addons/io_mesh_stl/blender_utils.py -index 864335ab..c74853db 100644 ---- a/release/scripts/addons/io_mesh_stl/blender_utils.py -+++ b/release/scripts/addons/io_mesh_stl/blender_utils.py -@@ -86,7 +86,7 @@ def faces_from_mesh(ob, global_matrix, use_mesh_modifiers=False, triangulate=Tru - try: - mesh = ob.to_mesh(bpy.context.scene, use_mesh_modifiers, "PREVIEW") - except RuntimeError: -- raise StopIteration -+ return - - mat = global_matrix * ob.matrix_world - mesh.transform(mat) |