[
  {
    "path": ".ci/apple_arm64_x265.patch",
    "content": "diff -Naur ./source/CMakeLists.txt ../x265_apple_patch/source/CMakeLists.txt\n--- ./source/CMakeLists.txt\t2021-05-08 13:06:22.000000000 +0100\n+++ ../x265_apple_patch/source/CMakeLists.txt\t2021-05-08 13:08:01.000000000 +0100\n@@ -40,9 +40,11 @@\n # System architecture detection\n string(TOLOWER \"${CMAKE_SYSTEM_PROCESSOR}\" SYSPROC)\n set(X86_ALIASES x86 i386 i686 x86_64 amd64)\n-set(ARM_ALIASES armv6l armv7l aarch64)\n+set(ARM_ALIASES armv6l armv7l)\n+set(ARM64_ALIASES arm64 arm64e aarch64)\n list(FIND X86_ALIASES \"${SYSPROC}\" X86MATCH)\n list(FIND ARM_ALIASES \"${SYSPROC}\" ARMMATCH)\n+list(FIND ARM64_ALIASES \"${SYSPROC}\" ARM64MATCH)\n set(POWER_ALIASES ppc64 ppc64le)\n list(FIND POWER_ALIASES \"${SYSPROC}\" POWERMATCH)\n if(\"${SYSPROC}\" STREQUAL \"\" OR X86MATCH GREATER \"-1\")\n@@ -79,6 +81,15 @@\n         message(STATUS \"Detected ARM target processor\")\n         add_definitions(-DX265_ARCH_ARM=1 -DX265_ARCH_ARM64=0 -DHAVE_ARMV6=1)\n     endif()\n+elseif(ARM64MATCH GREATER \"-1\")\n+    if(CROSS_COMPILE_ARM64)\n+        message(STATUS \"Cross compiling for ARM64 arch\")\n+    else()\n+        set(CROSS_COMPILE_ARM64 0)\n+    endif()\n+    message(STATUS \"Detected ARM64 target processor\")\n+    set(ARM64 1)\n+    add_definitions(-DX265_ARCH_ARM64=1 -DHAVE_NEON)\n else()\n     message(STATUS \"CMAKE_SYSTEM_PROCESSOR value `${CMAKE_SYSTEM_PROCESSOR}` is unknown\")\n     message(STATUS \"Please add this value near ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE}\")\n@@ -259,6 +270,9 @@\n             endif()\n         endif()\n     endif()\n+    if(ARM64 OR CROSS_COMPILE_ARM64)\n+        add_definitions(-DHAVE_NEON)\n+    endif()\n     add_definitions(${ARM_ARGS})\n     if(FPROFILE_GENERATE)\n         if(INTEL_CXX)\n@@ -350,7 +364,7 @@\n endif(GCC)\n \n find_package(Nasm)\n-if(ARM OR CROSS_COMPILE_ARM)\n+if(ARM OR CROSS_COMPILE_ARM OR ARM64 OR CROSS_COMPILE_ARM64)\n     option(ENABLE_ASSEMBLY \"Enable use of assembly coded primitives\" ON)\n elseif(NASM_FOUND AND X86)\n     if (NASM_VERSION_STRING VERSION_LESS \"2.13.0\")\n@@ -549,6 +563,32 @@\n                 ARGS ${ARM_ARGS} -c ${ASM_SRC} -o ${ASM}.${SUFFIX}\n                 DEPENDS ${ASM_SRC})\n         endforeach()\n+    elseif(ARM64 OR CROSS_COMPILE_ARM64)\n+    # compile ARM arch asm files here\n+        enable_language(ASM)\n+        foreach(ASM ${ARM_ASMS})\n+            set(ASM_SRC ${CMAKE_CURRENT_SOURCE_DIR}/common/arm64/${ASM})\n+            list(APPEND ASM_SRCS ${ASM_SRC})\n+            list(APPEND ASM_OBJS ${ASM}.${SUFFIX})\n+            add_custom_command(\n+                OUTPUT ${ASM}.${SUFFIX}\n+                COMMAND ${CMAKE_CXX_COMPILER}\n+                ARGS ${ARM_ARGS} -c ${ASM_SRC} -o ${ASM}.${SUFFIX}\n+                DEPENDS ${ASM_SRC})\n+        endforeach()\n+    elseif(ARM64 OR CROSS_COMPILE_ARM64)\n+    # compile ARM arch asm files here\n+        enable_language(ASM)\n+        foreach(ASM ${ARM_ASMS})\n+            set(ASM_SRC ${CMAKE_CURRENT_SOURCE_DIR}/common/arm64/${ASM})\n+            list(APPEND ASM_SRCS ${ASM_SRC})\n+            list(APPEND ASM_OBJS ${ASM}.${SUFFIX})\n+            add_custom_command(\n+                OUTPUT ${ASM}.${SUFFIX}\n+                COMMAND ${CMAKE_CXX_COMPILER}\n+                ARGS ${ARM_ARGS} -c ${ASM_SRC} -o ${ASM}.${SUFFIX}\n+                DEPENDS ${ASM_SRC})\n+        endforeach()\n     elseif(X86)\n     # compile X86 arch asm files here\n         foreach(ASM ${MSVC_ASMS})\ndiff -Naur ./source/common/CMakeLists.txt ../x265_apple_patch/source/common/CMakeLists.txt\n--- ./source/common/CMakeLists.txt\t2021-05-08 13:06:22.000000000 +0100\n+++ ../x265_apple_patch/source/common/CMakeLists.txt\t2021-05-08 13:08:01.000000000 +0100\n@@ -114,6 +114,22 @@\n     source_group(Assembly FILES ${ASM_PRIMITIVES})\n endif(ENABLE_ASSEMBLY AND (ARM OR CROSS_COMPILE_ARM))\n \n+\n+if(ENABLE_ASSEMBLY AND (ARM64 OR CROSS_COMPILE_ARM64))\n+    set(C_SRCS asm-primitives.cpp pixel-prim.h pixel-prim.cpp  filter-prim.h filter-prim.cpp dct-prim.h dct-prim.cpp loopfilter-prim.cpp loopfilter-prim.h intrapred-prim.cpp arm64-utils.cpp arm64-utils.h)\n+    enable_language(ASM)\n+    # add ARM assembly/intrinsic files here\n+    #set(A_SRCS )\n+    #set(VEC_PRIMITIVES)\n+\n+    #set(ARM64_ASMS \"${A_SRCS}\" CACHE INTERNAL \"ARM64 Assembly Sources\")\n+    foreach(SRC ${C_SRCS})\n+        set(ASM_PRIMITIVES ${ASM_PRIMITIVES} arm64/${SRC})\n+    endforeach()\n+    source_group(Assembly FILES ${ASM_PRIMITIVES})\n+endif(ENABLE_ASSEMBLY AND (ARM64 OR CROSS_COMPILE_ARM64))\n+\n+\n if(POWER)\n     set_source_files_properties(version.cpp PROPERTIES COMPILE_FLAGS -DX265_VERSION=${X265_VERSION})\n     if(ENABLE_ALTIVEC)\ndiff -Naur ./source/common/arm64/arm64-utils.cpp ../x265_apple_patch/source/common/arm64/arm64-utils.cpp\n--- ./source/common/arm64/arm64-utils.cpp\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/arm64-utils.cpp\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,290 @@\n+#include \"common.h\"\n+#include \"x265.h\"\n+#include \"arm64-utils.h\"\n+#include <arm_neon.h>\n+\n+#define COPY_16(d,s) *(uint8x16_t *)(d) = *(uint8x16_t *)(s)\n+namespace X265_NS {\n+\n+\n+\n+void transpose8x8(uint8_t* dst, const uint8_t* src, intptr_t dstride, intptr_t sstride)\n+{\n+    uint8x8_t a0,a1,a2,a3,a4,a5,a6,a7;\n+    uint8x8_t b0,b1,b2,b3,b4,b5,b6,b7;\n+\n+    a0 = *(uint8x8_t *)(src + 0*sstride);\n+    a1 = *(uint8x8_t *)(src + 1*sstride);\n+    a2 = *(uint8x8_t *)(src + 2*sstride);\n+    a3 = *(uint8x8_t *)(src + 3*sstride);\n+    a4 = *(uint8x8_t *)(src + 4*sstride);\n+    a5 = *(uint8x8_t *)(src + 5*sstride);\n+    a6 = *(uint8x8_t *)(src + 6*sstride);\n+    a7 = *(uint8x8_t *)(src + 7*sstride);\n+\n+    b0 = vtrn1_u32(a0,a4);\n+    b1 = vtrn1_u32(a1,a5);\n+    b2 = vtrn1_u32(a2,a6);\n+    b3 = vtrn1_u32(a3,a7);\n+    b4 = vtrn2_u32(a0,a4);\n+    b5 = vtrn2_u32(a1,a5);\n+    b6 = vtrn2_u32(a2,a6);\n+    b7 = vtrn2_u32(a3,a7);\n+\n+    a0 = vtrn1_u16(b0,b2);\n+    a1 = vtrn1_u16(b1,b3);\n+    a2 = vtrn2_u16(b0,b2);\n+    a3 = vtrn2_u16(b1,b3);\n+    a4 = vtrn1_u16(b4,b6);\n+    a5 = vtrn1_u16(b5,b7);\n+    a6 = vtrn2_u16(b4,b6);\n+    a7 = vtrn2_u16(b5,b7);\n+\n+    b0 = vtrn1_u8(a0,a1);\n+    b1 = vtrn2_u8(a0,a1);\n+    b2 = vtrn1_u8(a2,a3);\n+    b3 = vtrn2_u8(a2,a3);\n+    b4 = vtrn1_u8(a4,a5);\n+    b5 = vtrn2_u8(a4,a5);\n+    b6 = vtrn1_u8(a6,a7);\n+    b7 = vtrn2_u8(a6,a7);\n+\n+    *(uint8x8_t *)(dst + 0*dstride) = b0;\n+    *(uint8x8_t *)(dst + 1*dstride) = b1;\n+    *(uint8x8_t *)(dst + 2*dstride) = b2;\n+    *(uint8x8_t *)(dst + 3*dstride) = b3;\n+    *(uint8x8_t *)(dst + 4*dstride) = b4;\n+    *(uint8x8_t *)(dst + 5*dstride) = b5;\n+    *(uint8x8_t *)(dst + 6*dstride) = b6;\n+    *(uint8x8_t *)(dst + 7*dstride) = b7;\n+}\n+\n+\n+\n+\n+\n+\n+void transpose16x16(uint8_t* dst, const uint8_t* src, intptr_t dstride, intptr_t sstride)\n+{\n+    uint16x8_t a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aA,aB,aC,aD,aE,aF;\n+    uint16x8_t b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,bA,bB,bC,bD,bE,bF;\n+    uint16x8_t c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,cA,cB,cC,cD,cE,cF;\n+    uint16x8_t d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,dA,dB,dC,dD,dE,dF;\n+    \n+    a0 = *(uint16x8_t *)(src + 0*sstride);\n+    a1 = *(uint16x8_t *)(src + 1*sstride);\n+    a2 = *(uint16x8_t *)(src + 2*sstride);\n+    a3 = *(uint16x8_t *)(src + 3*sstride);\n+    a4 = *(uint16x8_t *)(src + 4*sstride);\n+    a5 = *(uint16x8_t *)(src + 5*sstride);\n+    a6 = *(uint16x8_t *)(src + 6*sstride);\n+    a7 = *(uint16x8_t *)(src + 7*sstride);\n+    a8 = *(uint16x8_t *)(src + 8*sstride);\n+    a9 = *(uint16x8_t *)(src + 9*sstride);\n+    aA = *(uint16x8_t *)(src + 10*sstride);\n+    aB = *(uint16x8_t *)(src + 11*sstride);\n+    aC = *(uint16x8_t *)(src + 12*sstride);\n+    aD = *(uint16x8_t *)(src + 13*sstride);\n+    aE = *(uint16x8_t *)(src + 14*sstride);\n+    aF = *(uint16x8_t *)(src + 15*sstride);\n+\n+    b0 = vtrn1q_u64(a0, a8);\n+    b1 = vtrn1q_u64(a1, a9);\n+    b2 = vtrn1q_u64(a2, aA);\n+    b3 = vtrn1q_u64(a3, aB);\n+    b4 = vtrn1q_u64(a4, aC);\n+    b5 = vtrn1q_u64(a5, aD);\n+    b6 = vtrn1q_u64(a6, aE);\n+    b7 = vtrn1q_u64(a7, aF);\n+    b8 = vtrn2q_u64(a0, a8);\n+    b9 = vtrn2q_u64(a1, a9);\n+    bA = vtrn2q_u64(a2, aA);\n+    bB = vtrn2q_u64(a3, aB);\n+    bC = vtrn2q_u64(a4, aC);\n+    bD = vtrn2q_u64(a5, aD);\n+    bE = vtrn2q_u64(a6, aE);\n+    bF = vtrn2q_u64(a7, aF);\n+\n+    c0 = vtrn1q_u32(b0, b4);\n+    c1 = vtrn1q_u32(b1, b5);\n+    c2 = vtrn1q_u32(b2, b6);\n+    c3 = vtrn1q_u32(b3, b7);\n+    c4 = vtrn2q_u32(b0, b4);\n+    c5 = vtrn2q_u32(b1, b5);\n+    c6 = vtrn2q_u32(b2, b6);\n+    c7 = vtrn2q_u32(b3, b7);\n+    c8 = vtrn1q_u32(b8, bC);\n+    c9 = vtrn1q_u32(b9, bD);\n+    cA = vtrn1q_u32(bA, bE);\n+    cB = vtrn1q_u32(bB, bF);\n+    cC = vtrn2q_u32(b8, bC);\n+    cD = vtrn2q_u32(b9, bD);\n+    cE = vtrn2q_u32(bA, bE);\n+    cF = vtrn2q_u32(bB, bF);\n+    \n+    d0 = vtrn1q_u16(c0, c2);\n+    d1 = vtrn1q_u16(c1, c3);\n+    d2 = vtrn2q_u16(c0, c2);\n+    d3 = vtrn2q_u16(c1, c3);\n+    d4 = vtrn1q_u16(c4, c6);\n+    d5 = vtrn1q_u16(c5, c7);\n+    d6 = vtrn2q_u16(c4, c6);\n+    d7 = vtrn2q_u16(c5, c7);\n+    d8 = vtrn1q_u16(c8, cA);\n+    d9 = vtrn1q_u16(c9, cB);\n+    dA = vtrn2q_u16(c8, cA);\n+    dB = vtrn2q_u16(c9, cB);\n+    dC = vtrn1q_u16(cC, cE);\n+    dD = vtrn1q_u16(cD, cF);\n+    dE = vtrn2q_u16(cC, cE);\n+    dF = vtrn2q_u16(cD, cF);\n+    \n+    *(uint16x8_t *)(dst + 0*dstride)  = vtrn1q_u8(d0, d1);\n+    *(uint16x8_t *)(dst + 1*dstride)  = vtrn2q_u8(d0, d1);\n+    *(uint16x8_t *)(dst + 2*dstride)  = vtrn1q_u8(d2, d3);\n+    *(uint16x8_t *)(dst + 3*dstride)  = vtrn2q_u8(d2, d3);\n+    *(uint16x8_t *)(dst + 4*dstride)  = vtrn1q_u8(d4, d5);\n+    *(uint16x8_t *)(dst + 5*dstride)  = vtrn2q_u8(d4, d5);\n+    *(uint16x8_t *)(dst + 6*dstride)  = vtrn1q_u8(d6, d7);\n+    *(uint16x8_t *)(dst + 7*dstride)  = vtrn2q_u8(d6, d7);\n+    *(uint16x8_t *)(dst + 8*dstride)  = vtrn1q_u8(d8, d9);\n+    *(uint16x8_t *)(dst + 9*dstride)  = vtrn2q_u8(d8, d9);\n+    *(uint16x8_t *)(dst + 10*dstride)  = vtrn1q_u8(dA, dB);\n+    *(uint16x8_t *)(dst + 11*dstride)  = vtrn2q_u8(dA, dB);\n+    *(uint16x8_t *)(dst + 12*dstride)  = vtrn1q_u8(dC, dD);\n+    *(uint16x8_t *)(dst + 13*dstride)  = vtrn2q_u8(dC, dD);\n+    *(uint16x8_t *)(dst + 14*dstride)  = vtrn1q_u8(dE, dF);\n+    *(uint16x8_t *)(dst + 15*dstride)  = vtrn2q_u8(dE, dF);\n+\n+    \n+}\n+\n+\n+void transpose32x32(uint8_t* dst, const uint8_t* src, intptr_t dstride, intptr_t sstride)\n+{\n+    //assumption: there is no partial overlap\n+    transpose16x16(dst,src,dstride,sstride);\n+    transpose16x16(dst+16*dstride+16,src+16*sstride+16,dstride,sstride);\n+    if (dst == src)\n+    {\n+        uint8_t tmp[16*16] __attribute__((aligned(64)));\n+        transpose16x16(tmp,src + 16,16,sstride);\n+        transpose16x16(dst + 16, src + 16*sstride,dstride,sstride);\n+        for (int i=0;i<16;i++) COPY_16(dst+(16 + i)*dstride,tmp + 16*i);\n+    }\n+    else\n+    {\n+        transpose16x16(dst+16*dstride,src + 16,dstride,sstride);\n+        transpose16x16(dst + 16, src + 16*sstride,dstride,sstride);\n+    }\n+    \n+}\n+\n+\n+\n+void transpose8x8(uint16_t* dst, const uint16_t* src, intptr_t dstride, intptr_t sstride)\n+{\n+    uint16x8_t a0,a1,a2,a3,a4,a5,a6,a7;\n+    uint16x8_t b0,b1,b2,b3,b4,b5,b6,b7;\n+\n+    a0 = *(uint16x8_t *)(src + 0*sstride);\n+    a1 = *(uint16x8_t *)(src + 1*sstride);\n+    a2 = *(uint16x8_t *)(src + 2*sstride);\n+    a3 = *(uint16x8_t *)(src + 3*sstride);\n+    a4 = *(uint16x8_t *)(src + 4*sstride);\n+    a5 = *(uint16x8_t *)(src + 5*sstride);\n+    a6 = *(uint16x8_t *)(src + 6*sstride);\n+    a7 = *(uint16x8_t *)(src + 7*sstride);\n+\n+    b0 = vtrn1q_u64(a0,a4);\n+    b1 = vtrn1q_u64(a1,a5);\n+    b2 = vtrn1q_u64(a2,a6);\n+    b3 = vtrn1q_u64(a3,a7);\n+    b4 = vtrn2q_u64(a0,a4);\n+    b5 = vtrn2q_u64(a1,a5);\n+    b6 = vtrn2q_u64(a2,a6);\n+    b7 = vtrn2q_u64(a3,a7);\n+\n+    a0 = vtrn1q_u32(b0,b2);\n+    a1 = vtrn1q_u32(b1,b3);\n+    a2 = vtrn2q_u32(b0,b2);\n+    a3 = vtrn2q_u32(b1,b3);\n+    a4 = vtrn1q_u32(b4,b6);\n+    a5 = vtrn1q_u32(b5,b7);\n+    a6 = vtrn2q_u32(b4,b6);\n+    a7 = vtrn2q_u32(b5,b7);\n+\n+    b0 = vtrn1q_u16(a0,a1);\n+    b1 = vtrn2q_u16(a0,a1);\n+    b2 = vtrn1q_u16(a2,a3);\n+    b3 = vtrn2q_u16(a2,a3);\n+    b4 = vtrn1q_u16(a4,a5);\n+    b5 = vtrn2q_u16(a4,a5);\n+    b6 = vtrn1q_u16(a6,a7);\n+    b7 = vtrn2q_u16(a6,a7);\n+\n+    *(uint16x8_t *)(dst + 0*dstride) = b0;\n+    *(uint16x8_t *)(dst + 1*dstride) = b1;\n+    *(uint16x8_t *)(dst + 2*dstride) = b2;\n+    *(uint16x8_t *)(dst + 3*dstride) = b3;\n+    *(uint16x8_t *)(dst + 4*dstride) = b4;\n+    *(uint16x8_t *)(dst + 5*dstride) = b5;\n+    *(uint16x8_t *)(dst + 6*dstride) = b6;\n+    *(uint16x8_t *)(dst + 7*dstride) = b7;\n+}\n+\n+void transpose16x16(uint16_t* dst, const uint16_t* src, intptr_t dstride, intptr_t sstride)\n+{\n+    //assumption: there is no partial overlap\n+    transpose8x8(dst,src,dstride,sstride);\n+    transpose8x8(dst+8*dstride+8,src+8*sstride+8,dstride,sstride);\n+\n+    if (dst == src)\n+    {\n+        uint16_t tmp[8*8];\n+        transpose8x8(tmp,src + 8,8,sstride);\n+        transpose8x8(dst + 8, src + 8*sstride,dstride,sstride);\n+        for (int i=0;i<8;i++) COPY_16(dst+(8 + i)*dstride,tmp + 8*i);\n+    }\n+    else\n+    {\n+        transpose8x8(dst+8*dstride,src + 8,dstride,sstride);\n+        transpose8x8(dst + 8, src + 8*sstride,dstride,sstride);\n+    }\n+    \n+}\n+\n+\n+\n+void transpose32x32(uint16_t* dst, const uint16_t* src, intptr_t dstride, intptr_t sstride)\n+{\n+    //assumption: there is no partial overlap\n+    for (int i=0;i<4;i++)\n+    {\n+        transpose8x8(dst+i*8*(1+dstride),src+i*8*(1+sstride),dstride,sstride);\n+        for (int j=i+1;j<4;j++)\n+        {\n+            if (dst == src)\n+            {\n+                uint16_t tmp[8*8] __attribute__((aligned(64)));\n+                transpose8x8(tmp,src + 8*i + 8*j*sstride,8,sstride);\n+                transpose8x8(dst + 8*i + 8*j*dstride, src + 8*j + 8*i*sstride,dstride,sstride);\n+                for (int k=0;k<8;k++) COPY_16(dst+ 8*j + (8*i+k)*dstride,tmp + 8*k);\n+            }\n+            else\n+            {\n+                transpose8x8(dst + 8*(j + i*dstride),src + 8*(i + j*sstride),dstride,sstride);\n+                transpose8x8(dst + 8*(i + j*dstride),src + 8*(j + i*sstride),dstride,sstride);\n+            }\n+            \n+        }\n+    }\n+}\n+\n+\n+\n+\n+}\n+\n+\n+\ndiff -Naur ./source/common/arm64/arm64-utils.h ../x265_apple_patch/source/common/arm64/arm64-utils.h\n--- ./source/common/arm64/arm64-utils.h\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/arm64-utils.h\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,14 @@\n+#ifndef __ARM64_UTILS_H__\n+#define __ARM64_UTILS_H__\n+\n+\n+namespace X265_NS {\n+void transpose8x8(uint8_t* dst, const uint8_t* src, intptr_t dstride, intptr_t sstride);\n+void transpose16x16(uint8_t* dst, const uint8_t* src, intptr_t dstride, intptr_t sstride);\n+void transpose32x32(uint8_t* dst, const uint8_t* src, intptr_t dstride, intptr_t sstride);\n+void transpose8x8(uint16_t* dst, const uint16_t* src, intptr_t dstride, intptr_t sstride);\n+void transpose16x16(uint16_t* dst, const uint16_t* src, intptr_t dstride, intptr_t sstride);\n+void transpose32x32(uint16_t* dst, const uint16_t* src, intptr_t dstride, intptr_t sstride);\n+}\n+\n+#endif\ndiff -Naur ./source/common/arm64/asm-primitives.cpp ../x265_apple_patch/source/common/arm64/asm-primitives.cpp\n--- ./source/common/arm64/asm-primitives.cpp\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/asm-primitives.cpp\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,53 @@\n+/*****************************************************************************\n+ * Copyright (C) 2013-2017 MulticoreWare, Inc\n+ *\n+ * Authors: Steve Borho <steve@borho.org>\n+ *          Praveen Kumar Tiwari <praveen@multicorewareinc.com>\n+ *          Min Chen <chenm003@163.com> <min.chen@multicorewareinc.com>\n+ *          Dnyaneshwar Gorade <dnyaneshwar@multicorewareinc.com>\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License as published by\n+ * the Free Software Foundation; either version 2 of the License, or\n+ * (at your option) any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU General Public License\n+ * along with this program; if not, write to the Free Software\n+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.\n+ *\n+ * This program is also available under a commercial proprietary license.\n+ * For more information, contact us at license @ x265.com.\n+ *****************************************************************************/\n+\n+#include \"common.h\"\n+#include \"primitives.h\"\n+#include \"x265.h\"\n+#include \"cpu.h\"\n+\n+#include \"pixel-prim.h\"\n+#include \"filter-prim.h\"\n+#include \"dct-prim.h\"\n+#include \"loopfilter-prim.h\"\n+#include \"intrapred-prim.h\"\n+\n+namespace X265_NS {\n+// private x265 namespace\n+\n+void setupAssemblyPrimitives(EncoderPrimitives &p, int cpuMask)\n+{\n+    if (cpuMask & X265_CPU_NEON)\n+    {\n+      setupPixelPrimitives_neon(p);\n+      setupFilterPrimitives_neon(p);\n+      setupDCTPrimitives_neon(p);\n+      setupLoopFilterPrimitives_neon(p);\n+      setupIntraPrimitives_neon(p);\n+    }\n+}\n+\n+} // namespace X265_NS\ndiff -Naur ./source/common/arm64/dct-prim.cpp ../x265_apple_patch/source/common/arm64/dct-prim.cpp\n--- ./source/common/arm64/dct-prim.cpp\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/dct-prim.cpp\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,933 @@\n+#include \"dct-prim.h\"\n+\n+\n+#if HAVE_NEON\n+\n+#include <arm_neon.h>\n+\n+\n+namespace {\n+using namespace X265_NS;\n+\n+\n+static int16x8_t rev16(const int16x8_t a)\n+{\n+    static const int8x16_t tbl = {14,15,12,13,10,11,8,9,6,7,4,5,2,3,0,1};\n+    return vqtbx1q_u8(a,a,tbl);\n+}\n+\n+static int32x4_t rev32(const int32x4_t a)\n+{\n+    static const int8x16_t tbl = {12,13,14,15,8,9,10,11,4,5,6,7,0,1,2,3};\n+    return vqtbx1q_u8(a,a,tbl);\n+}\n+    \n+static void transpose_4x4x16(int16x4_t& x0,int16x4_t& x1,int16x4_t& x2,int16x4_t& x3)\n+{\n+    int16x4_t s0,s1,s2,s3;\n+    s0 = vtrn1_s32(x0,x2);\n+    s1 = vtrn1_s32(x1,x3);\n+    s2 = vtrn2_s32(x0,x2);\n+    s3 = vtrn2_s32(x1,x3);\n+    \n+    x0 = vtrn1_s16(s0,s1);\n+    x1 = vtrn2_s16(s0,s1);\n+    x2 = vtrn1_s16(s2,s3);\n+    x3 = vtrn2_s16(s2,s3);\n+}\n+\n+\n+\n+static int scanPosLast_opt(const uint16_t *scan, const coeff_t *coeff, uint16_t *coeffSign, uint16_t *coeffFlag, uint8_t *coeffNum, int numSig, const uint16_t* /*scanCG4x4*/, const int /*trSize*/)\n+{\n+\n+    // This is an optimized function for scanPosLast, which removes the rmw dependency, once integrated into mainline x265, should replace reference implementation\n+    // For clarity, left the original reference code in comments\n+    int scanPosLast = 0;\n+    \n+    uint16_t cSign = 0;\n+    uint16_t cFlag = 0;\n+    uint8_t cNum = 0;\n+    \n+    uint32_t prevcgIdx = 0;\n+    do\n+    {\n+        const uint32_t cgIdx = (uint32_t)scanPosLast >> MLS_CG_SIZE;\n+\n+        const uint32_t posLast = scan[scanPosLast];\n+\n+        const int curCoeff = coeff[posLast];\n+        const uint32_t isNZCoeff = (curCoeff != 0);\n+        /*\n+        NOTE: the new algorithm is complicated, so I keep reference code here\n+        uint32_t posy   = posLast >> log2TrSize;\n+        uint32_t posx   = posLast - (posy << log2TrSize);\n+        uint32_t blkIdx0 = ((posy >> MLS_CG_LOG2_SIZE) << codingParameters.log2TrSizeCG) + (posx >> MLS_CG_LOG2_SIZE);\n+        const uint32_t blkIdx = ((posLast >> (2 * MLS_CG_LOG2_SIZE)) & ~maskPosXY) + ((posLast >> MLS_CG_LOG2_SIZE) & maskPosXY);\n+        sigCoeffGroupFlag64 |= ((uint64_t)isNZCoeff << blkIdx);\n+        */\n+\n+        // get L1 sig map\n+        numSig -= isNZCoeff;\n+\n+        if (scanPosLast % (1<<MLS_CG_SIZE) == 0)\n+        {\n+            coeffSign[prevcgIdx] = cSign;\n+            coeffFlag[prevcgIdx] = cFlag;\n+            coeffNum[prevcgIdx] = cNum;\n+            cSign = 0;\n+            cFlag = 0;\n+            cNum = 0;\n+        }\n+        // TODO: optimize by instruction BTS\n+       cSign += (uint16_t)(((curCoeff < 0) ? 1 : 0) << cNum);\n+       cFlag = (cFlag << 1) + (uint16_t)isNZCoeff;\n+       cNum += (uint8_t)isNZCoeff;\n+       prevcgIdx = cgIdx;\n+        scanPosLast++;\n+    }\n+    while (numSig > 0);\n+\n+    coeffSign[prevcgIdx] = cSign;\n+    coeffFlag[prevcgIdx] = cFlag;\n+    coeffNum[prevcgIdx] = cNum;\n+    return scanPosLast - 1;\n+}\n+\n+\n+#if (MLS_CG_SIZE == 4)\n+template<int log2TrSize>\n+static void nonPsyRdoQuant_neon(int16_t *m_resiDctCoeff, int64_t *costUncoded, int64_t *totalUncodedCost, int64_t *totalRdCost, uint32_t blkPos)\n+{\n+    const int transformShift = MAX_TR_DYNAMIC_RANGE - X265_DEPTH - log2TrSize; /* Represents scaling through forward transform */\n+    const int scaleBits = SCALE_BITS - 2 * transformShift;\n+    const uint32_t trSize = 1 << log2TrSize;\n+\n+    int64x2_t vcost_sum_0 = vdupq_n_s64(0);\n+    int64x2_t vcost_sum_1 = vdupq_n_s64(0);\n+    for (int y = 0; y < MLS_CG_SIZE; y++)\n+    {\n+      int16x4_t in = *(int16x4_t *)&m_resiDctCoeff[blkPos];\n+      int32x4_t mul = vmull_s16(in,in);\n+      int64x2_t cost0, cost1;\n+      cost0 = vshll_n_s32(vget_low_s32(mul),scaleBits);\n+      cost1 = vshll_high_n_s32(mul,scaleBits);\n+      *(int64x2_t *)&costUncoded[blkPos+0] = cost0;\n+      *(int64x2_t *)&costUncoded[blkPos+2] = cost1;\n+      vcost_sum_0 = vaddq_s64(vcost_sum_0,cost0);\n+      vcost_sum_1 = vaddq_s64(vcost_sum_1,cost1);\n+      blkPos += trSize;\n+    }\n+    int64_t sum = vaddvq_s64(vaddq_s64(vcost_sum_0,vcost_sum_1));\n+    *totalUncodedCost += sum;\n+    *totalRdCost += sum;\n+}\n+\n+template<int log2TrSize>\n+static void psyRdoQuant_neon(int16_t *m_resiDctCoeff, int16_t *m_fencDctCoeff, int64_t *costUncoded, int64_t *totalUncodedCost, int64_t *totalRdCost, int64_t *psyScale, uint32_t blkPos)\n+{\n+    const int transformShift = MAX_TR_DYNAMIC_RANGE - X265_DEPTH - log2TrSize; /* Represents scaling through forward transform */\n+    const int scaleBits = SCALE_BITS - 2 * transformShift;\n+    const uint32_t trSize = 1 << log2TrSize;\n+    //using preprocessor to bypass clang bug\n+    const int max = X265_MAX(0, (2 * transformShift + 1));\n+\n+    int64x2_t vcost_sum_0 = vdupq_n_s64(0);\n+    int64x2_t vcost_sum_1 = vdupq_n_s64(0);\n+    int32x4_t vpsy = vdupq_n_s32(*psyScale);\n+    for (int y = 0; y < MLS_CG_SIZE; y++)\n+    {\n+      int32x4_t signCoef = vmovl_s16(*(int16x4_t *)&m_resiDctCoeff[blkPos]);\n+      int32x4_t predictedCoef = vsubq_s32(vmovl_s16(*(int16x4_t *)&m_fencDctCoeff[blkPos]),signCoef);\n+      int64x2_t cost0, cost1;\n+      cost0 = vmull_s32(vget_low_s32(signCoef),vget_low_s32(signCoef));\n+      cost1 = vmull_high_s32(signCoef,signCoef);\n+      cost0 = vshlq_n_s64(cost0,scaleBits);\n+      cost1 = vshlq_n_s64(cost1,scaleBits);\n+      int64x2_t neg0 = vmull_s32(vget_low_s32(predictedCoef),vget_low_s32(vpsy));\n+      int64x2_t neg1 = vmull_high_s32(predictedCoef,vpsy);\n+      if (max > 0) {\n+        int64x2_t shift = vdupq_n_s64(-max);\n+        neg0 = vshlq_s64(neg0,shift);\n+        neg1 = vshlq_s64(neg1,shift);\n+      }\n+      cost0 = vsubq_s64(cost0,neg0);\n+      cost1 = vsubq_s64(cost1,neg1);\n+      *(int64x2_t *)&costUncoded[blkPos+0] = cost0;\n+      *(int64x2_t *)&costUncoded[blkPos+2] = cost1;\n+      vcost_sum_0 = vaddq_s64(vcost_sum_0,cost0);\n+      vcost_sum_1 = vaddq_s64(vcost_sum_1,cost1);\n+     \n+        blkPos += trSize;\n+    }\n+  int64_t sum = vaddvq_s64(vaddq_s64(vcost_sum_0,vcost_sum_1));\n+  *totalUncodedCost += sum;\n+  *totalRdCost += sum;\n+}\n+\n+#else\n+      #error \"MLS_CG_SIZE must be 4 for neon version\"\n+#endif\n+\n+\n+\n+template<int trSize>\n+int  count_nonzero_neon(const int16_t* quantCoeff)\n+{\n+  X265_CHECK(((intptr_t)quantCoeff & 15) == 0, \"quant buffer not aligned\\n\");\n+  int count = 0;\n+  int16x8_t vcount = vdupq_n_s16(0);\n+  const int numCoeff = trSize * trSize;\n+  int i = 0;\n+  for (; (i + 8) <= numCoeff; i+=8)\n+  {\n+    int16x8_t in = *(int16x8_t*)&quantCoeff[i];\n+    vcount = vaddq_s16(vcount,vtstq_s16(in,in));\n+  }\n+  for (; i < numCoeff; i++)\n+  {\n+      count += quantCoeff[i] != 0;\n+  }\n+\n+  return count - vaddvq_s16(vcount);\n+}\n+\n+template<int trSize>\n+uint32_t copy_count_neon(int16_t* coeff, const int16_t* residual, intptr_t resiStride)\n+{\n+  uint32_t numSig = 0;\n+  int16x8_t vcount = vdupq_n_s16(0);\n+  for (int k = 0; k < trSize; k++)\n+  {\n+    int j = 0;\n+    for (; (j + 8) <= trSize; j+=8)\n+    {\n+      int16x8_t in = *(int16x8_t*)&residual[j];\n+      *(int16x8_t*)&coeff[j] = in;\n+      vcount = vaddq_s16(vcount,vtstq_s16(in,in));\n+    }\n+    for (; j < trSize; j++)\n+    {\n+      coeff[j] = residual[j];\n+      numSig += (residual[j] != 0);\n+    }\n+    residual += resiStride;\n+    coeff += trSize;\n+  }\n+\n+  return numSig - vaddvq_s16(vcount);\n+}\n+\n+\n+static void partialButterfly16(const int16_t* src, int16_t* dst, int shift, int line)\n+{\n+    int j, k;\n+    int32x4_t E[2], O[2];\n+    int32x4_t EE, EO;\n+    int32x2_t EEE, EEO;\n+    const int add = 1 << (shift - 1);\n+    const int32x4_t _vadd = {add,0};\n+    \n+    for (j = 0; j < line; j++)\n+    {\n+        int16x8_t in0 = *(int16x8_t *)src;\n+        int16x8_t in1 = rev16(*(int16x8_t *)&src[8]);\n+        \n+        E[0] = vaddl_s16(vget_low_s16(in0),vget_low_s16(in1));\n+        O[0] = vsubl_s16(vget_low_s16(in0),vget_low_s16(in1));\n+        E[1] = vaddl_high_s16(in0,in1);\n+        O[1] = vsubl_high_s16(in0,in1);\n+\n+        for (k = 1; k < 16; k += 2)\n+        {\n+            int32x4_t c0 = vmovl_s16(*(int16x4_t *)&g_t16[k][0]);\n+            int32x4_t c1 = vmovl_s16(*(int16x4_t *)&g_t16[k][4]);\n+            \n+            int32x4_t res = _vadd;\n+            res = vmlaq_s32(res,c0,O[0]);\n+            res = vmlaq_s32(res,c1,O[1]);\n+            dst[k * line] = (int16_t)(vaddvq_s32(res) >> shift);\n+        }\n+\n+        /* EE and EO */\n+        EE = vaddq_s32(E[0],rev32(E[1]));\n+        EO = vsubq_s32(E[0],rev32(E[1]));\n+        \n+        for (k = 2; k < 16; k += 4)\n+        {\n+            int32x4_t c0 = vmovl_s16(*(int16x4_t *)&g_t16[k][0]);\n+            int32x4_t res = _vadd;\n+            res = vmlaq_s32(res,c0,EO);\n+            dst[k * line] = (int16_t)(vaddvq_s32(res) >> shift);\n+        }\n+\n+        /* EEE and EEO */\n+        EEE[0] = EE[0] + EE[3];\n+        EEO[0] = EE[0] - EE[3];\n+        EEE[1] = EE[1] + EE[2];\n+        EEO[1] = EE[1] - EE[2];\n+        \n+        dst[0] = (int16_t)((g_t16[0][0] * EEE[0] + g_t16[0][1] * EEE[1] + add) >> shift);\n+        dst[8 * line] = (int16_t)((g_t16[8][0] * EEE[0] + g_t16[8][1] * EEE[1] + add) >> shift);\n+        dst[4 * line] = (int16_t)((g_t16[4][0] * EEO[0] + g_t16[4][1] * EEO[1] + add) >> shift);\n+        dst[12 * line] = (int16_t)((g_t16[12][0] * EEO[0] + g_t16[12][1] * EEO[1] + add) >> shift);\n+        \n+  \n+        src += 16;\n+        dst++;\n+    }\n+}\n+\n+    \n+static void partialButterfly32(const int16_t* src, int16_t* dst, int shift, int line)\n+{\n+    int j, k;\n+    const int add = 1 << (shift - 1);\n+    \n+    \n+    for (j = 0; j < line; j++)\n+    {\n+        int32x4_t VE[4], VO0,VO1,VO2,VO3;\n+        int32x4_t VEE[2], VEO[2];\n+        int32x4_t VEEE, VEEO;\n+        int EEEE[2], EEEO[2];\n+\n+        int16x8x4_t inputs;\n+        inputs = *(int16x8x4_t *)&src[0];\n+        int16x8x4_t in_rev;\n+        \n+        in_rev.val[1] = rev16(inputs.val[2]);\n+        in_rev.val[0] = rev16(inputs.val[3]);\n+        \n+        VE[0] = vaddl_s16(vget_low_s16(inputs.val[0]),vget_low_s16(in_rev.val[0]));\n+        VE[1] = vaddl_high_s16(inputs.val[0],in_rev.val[0]);\n+        VO0 = vsubl_s16(vget_low_s16(inputs.val[0]),vget_low_s16(in_rev.val[0]));\n+        VO1 = vsubl_high_s16(inputs.val[0],in_rev.val[0]);\n+        VE[2] = vaddl_s16(vget_low_s16(inputs.val[1]),vget_low_s16(in_rev.val[1]));\n+        VE[3] = vaddl_high_s16(inputs.val[1],in_rev.val[1]);\n+        VO2 = vsubl_s16(vget_low_s16(inputs.val[1]),vget_low_s16(in_rev.val[1]));\n+        VO3 = vsubl_high_s16(inputs.val[1],in_rev.val[1]);\n+\n+        for (k = 1; k < 32; k += 2)\n+        {\n+            int32x4_t c0 = vmovl_s16(*(int16x4_t *)&g_t32[k][0]);\n+            int32x4_t c1 = vmovl_s16(*(int16x4_t *)&g_t32[k][4]);\n+            int32x4_t c2 = vmovl_s16(*(int16x4_t *)&g_t32[k][8]);\n+            int32x4_t c3 = vmovl_s16(*(int16x4_t *)&g_t32[k][12]);\n+            int32x4_t s = vmulq_s32(c0,VO0);\n+            s = vmlaq_s32(s,c1,VO1);\n+            s = vmlaq_s32(s,c2,VO2);\n+            s = vmlaq_s32(s,c3,VO3);\n+            \n+            dst[k * line] = (int16_t)((vaddvq_s32(s) + add) >> shift);\n+            \n+        }\n+        \n+        int32x4_t rev_VE[2];\n+        \n+        \n+        rev_VE[0] = rev32(VE[3]);\n+        rev_VE[1] = rev32(VE[2]);\n+        \n+        /* EE and EO */\n+        for (k = 0; k < 2; k++)\n+        {\n+            VEE[k] = vaddq_s32(VE[k],rev_VE[k]);\n+            VEO[k] = vsubq_s32(VE[k],rev_VE[k]);\n+        }\n+        for (k = 2; k < 32; k += 4)\n+        {\n+            int32x4_t c0 = vmovl_s16(*(int16x4_t *)&g_t32[k][0]);\n+            int32x4_t c1 = vmovl_s16(*(int16x4_t *)&g_t32[k][4]);\n+            int32x4_t s = vmulq_s32(c0,VEO[0]);\n+            s = vmlaq_s32(s,c1,VEO[1]);\n+            \n+            dst[k * line] = (int16_t)((vaddvq_s32(s) + add) >> shift);\n+            \n+        }\n+        \n+        int32x4_t tmp = rev32(VEE[1]);\n+        VEEE = vaddq_s32(VEE[0],tmp);\n+        VEEO = vsubq_s32(VEE[0],tmp);\n+        for (k = 4; k < 32; k += 8)\n+        {\n+            int32x4_t c = vmovl_s16(*(int16x4_t *)&g_t32[k][0]);\n+            int32x4_t s = vmulq_s32(c,VEEO);\n+            \n+            dst[k * line] = (int16_t)((vaddvq_s32(s) + add) >> shift);\n+        }\n+        \n+        /* EEEE and EEEO */\n+        EEEE[0] = VEEE[0] + VEEE[3];\n+        EEEO[0] = VEEE[0] - VEEE[3];\n+        EEEE[1] = VEEE[1] + VEEE[2];\n+        EEEO[1] = VEEE[1] - VEEE[2];\n+        \n+        dst[0] = (int16_t)((g_t32[0][0] * EEEE[0] + g_t32[0][1] * EEEE[1] + add) >> shift);\n+        dst[16 * line] = (int16_t)((g_t32[16][0] * EEEE[0] + g_t32[16][1] * EEEE[1] + add) >> shift);\n+        dst[8 * line] = (int16_t)((g_t32[8][0] * EEEO[0] + g_t32[8][1] * EEEO[1] + add) >> shift);\n+        dst[24 * line] = (int16_t)((g_t32[24][0] * EEEO[0] + g_t32[24][1] * EEEO[1] + add) >> shift);\n+        \n+        \n+        \n+        src += 32;\n+        dst++;\n+    }\n+}\n+\n+static void partialButterfly8(const int16_t* src, int16_t* dst, int shift, int line)\n+{\n+    int j, k;\n+    int E[4], O[4];\n+    int EE[2], EO[2];\n+    int add = 1 << (shift - 1);\n+\n+    for (j = 0; j < line; j++)\n+    {\n+        /* E and O*/\n+        for (k = 0; k < 4; k++)\n+        {\n+            E[k] = src[k] + src[7 - k];\n+            O[k] = src[k] - src[7 - k];\n+        }\n+\n+        /* EE and EO */\n+        EE[0] = E[0] + E[3];\n+        EO[0] = E[0] - E[3];\n+        EE[1] = E[1] + E[2];\n+        EO[1] = E[1] - E[2];\n+\n+        dst[0] = (int16_t)((g_t8[0][0] * EE[0] + g_t8[0][1] * EE[1] + add) >> shift);\n+        dst[4 * line] = (int16_t)((g_t8[4][0] * EE[0] + g_t8[4][1] * EE[1] + add) >> shift);\n+        dst[2 * line] = (int16_t)((g_t8[2][0] * EO[0] + g_t8[2][1] * EO[1] + add) >> shift);\n+        dst[6 * line] = (int16_t)((g_t8[6][0] * EO[0] + g_t8[6][1] * EO[1] + add) >> shift);\n+\n+        dst[line] = (int16_t)((g_t8[1][0] * O[0] + g_t8[1][1] * O[1] + g_t8[1][2] * O[2] + g_t8[1][3] * O[3] + add) >> shift);\n+        dst[3 * line] = (int16_t)((g_t8[3][0] * O[0] + g_t8[3][1] * O[1] + g_t8[3][2] * O[2] + g_t8[3][3] * O[3] + add) >> shift);\n+        dst[5 * line] = (int16_t)((g_t8[5][0] * O[0] + g_t8[5][1] * O[1] + g_t8[5][2] * O[2] + g_t8[5][3] * O[3] + add) >> shift);\n+        dst[7 * line] = (int16_t)((g_t8[7][0] * O[0] + g_t8[7][1] * O[1] + g_t8[7][2] * O[2] + g_t8[7][3] * O[3] + add) >> shift);\n+\n+        src += 8;\n+        dst++;\n+    }\n+}\n+\n+static void partialButterflyInverse4(const int16_t* src, int16_t* dst, int shift, int line)\n+{\n+    int j;\n+    int E[2], O[2];\n+    int add = 1 << (shift - 1);\n+\n+    for (j = 0; j < line; j++)\n+    {\n+        /* Utilizing symmetry properties to the maximum to minimize the number of multiplications */\n+        O[0] = g_t4[1][0] * src[line] + g_t4[3][0] * src[3 * line];\n+        O[1] = g_t4[1][1] * src[line] + g_t4[3][1] * src[3 * line];\n+        E[0] = g_t4[0][0] * src[0] + g_t4[2][0] * src[2 * line];\n+        E[1] = g_t4[0][1] * src[0] + g_t4[2][1] * src[2 * line];\n+\n+        /* Combining even and odd terms at each hierarchy levels to calculate the final spatial domain vector */\n+        dst[0] = (int16_t)(x265_clip3(-32768, 32767, (E[0] + O[0] + add) >> shift));\n+        dst[1] = (int16_t)(x265_clip3(-32768, 32767, (E[1] + O[1] + add) >> shift));\n+        dst[2] = (int16_t)(x265_clip3(-32768, 32767, (E[1] - O[1] + add) >> shift));\n+        dst[3] = (int16_t)(x265_clip3(-32768, 32767, (E[0] - O[0] + add) >> shift));\n+\n+        src++;\n+        dst += 4;\n+    }\n+}\n+\n+ \n+    \n+static void partialButterflyInverse16_neon(const int16_t* src, int16_t* orig_dst, int shift, int line)\n+{\n+#define FMAK(x,l) s[l] = vmlal_lane_s16(s[l],*(int16x4_t*)&src[(x)*line],*(int16x4_t *)&g_t16[x][k],l)\n+#define MULK(x,l) vmull_lane_s16(*(int16x4_t*)&src[x*line],*(int16x4_t *)&g_t16[x][k],l);\n+#define ODD3_15(k) FMAK(3,k);FMAK(5,k);FMAK(7,k);FMAK(9,k);FMAK(11,k);FMAK(13,k);FMAK(15,k);\n+#define EVEN6_14_STEP4(k) FMAK(6,k);FMAK(10,k);FMAK(14,k);\n+\n+\n+    int j, k;\n+    int32x4_t E[8], O[8];\n+    int32x4_t EE[4], EO[4];\n+    int32x4_t EEE[2], EEO[2];\n+    const int add = 1 << (shift - 1);\n+\n+    \n+#pragma unroll(4)\n+    for (j = 0; j < line; j+=4)\n+    {\n+        /* Utilizing symmetry properties to the maximum to minimize the number of multiplications */\n+        \n+#pragma unroll(2)\n+        for (k=0;k<2;k++) {\n+            int32x4_t s;\n+            s = vmull_s16(vdup_n_s16(g_t16[4][k]),*(int16x4_t*)&src[4*line]);;\n+            EEO[k] = vmlal_s16(s,vdup_n_s16(g_t16[12][k]),*(int16x4_t*)&src[(12)*line]);\n+            s = vmull_s16(vdup_n_s16(g_t16[0][k]),*(int16x4_t*)&src[0*line]);;\n+            EEE[k] = vmlal_s16(s,vdup_n_s16(g_t16[8][k]),*(int16x4_t*)&src[(8)*line]);\n+        }\n+        \n+        /* Combining even and odd terms at each hierarchy levels to calculate the final spatial domain vector */\n+        EE[0] = vaddq_s32(EEE[0] , EEO[0]);\n+        EE[2] = vsubq_s32(EEE[1] , EEO[1]);\n+        EE[1] = vaddq_s32(EEE[1] , EEO[1]);\n+        EE[3] = vsubq_s32(EEE[0] , EEO[0]);\n+\n+\n+#pragma unroll(1)\n+        for (k = 0; k < 4; k+=4)\n+        {\n+            int32x4_t s[4];\n+            s[0] = MULK(2,0);\n+            s[1] = MULK(2,1);\n+            s[2] = MULK(2,2);\n+            s[3] = MULK(2,3);\n+            \n+            EVEN6_14_STEP4(0);\n+            EVEN6_14_STEP4(1);\n+            EVEN6_14_STEP4(2);\n+            EVEN6_14_STEP4(3);\n+            \n+            EO[k] = s[0];\n+            EO[k+1] = s[1];\n+            EO[k+2] = s[2];\n+            EO[k+3] = s[3];\n+         }\n+        \n+\n+        \n+        static const int32x4_t min = vdupq_n_s32(-32768);\n+        static const int32x4_t max = vdupq_n_s32(32767);\n+        const int32x4_t minus_shift = vdupq_n_s32(-shift);\n+\n+#pragma unroll(4)\n+        for (k = 0; k < 4; k++)\n+        {\n+            E[k] = vaddq_s32(EE[k] , EO[k]);\n+            E[k + 4] = vsubq_s32(EE[3 - k] , EO[3 - k]);\n+        }\n+        \n+#pragma unroll(2)\n+        for (k = 0; k < 8; k+=4)\n+        {\n+            int32x4_t s[4];\n+            s[0] = MULK(1,0);\n+            s[1] = MULK(1,1);\n+            s[2] = MULK(1,2);\n+            s[3] = MULK(1,3);\n+            ODD3_15(0);\n+            ODD3_15(1);\n+            ODD3_15(2);\n+            ODD3_15(3);\n+            O[k] = s[0];\n+            O[k+1] = s[1];\n+            O[k+2] = s[2];\n+            O[k+3] = s[3];\n+            int32x4_t t;\n+            int16x4_t x0,x1,x2,x3;\n+            \n+            E[k] = vaddq_s32(vdupq_n_s32(add),E[k]);\n+            t = vaddq_s32(E[k],O[k]);\n+            t = vshlq_s32(t,minus_shift);\n+            t = vmaxq_s32(t,min);\n+            t = vminq_s32(t,max);\n+            x0 = vmovn_s32(t);\n+\n+            E[k+1] = vaddq_s32(vdupq_n_s32(add),E[k+1]);\n+            t = vaddq_s32(E[k+1],O[k+1]);\n+            t = vshlq_s32(t,minus_shift);\n+            t = vmaxq_s32(t,min);\n+            t = vminq_s32(t,max);\n+            x1 = vmovn_s32(t);\n+\n+            E[k+2] = vaddq_s32(vdupq_n_s32(add),E[k+2]);\n+            t = vaddq_s32(E[k+2],O[k+2]);\n+            t = vshlq_s32(t,minus_shift);\n+            t = vmaxq_s32(t,min);\n+            t = vminq_s32(t,max);\n+            x2 = vmovn_s32(t);\n+\n+            E[k+3] = vaddq_s32(vdupq_n_s32(add),E[k+3]);\n+            t = vaddq_s32(E[k+3],O[k+3]);\n+            t = vshlq_s32(t,minus_shift);\n+            t = vmaxq_s32(t,min);\n+            t = vminq_s32(t,max);\n+            x3 = vmovn_s32(t);\n+            \n+            transpose_4x4x16(x0,x1,x2,x3);\n+            *(int16x4_t*)&orig_dst[0*16+k] = x0;\n+            *(int16x4_t*)&orig_dst[1*16+k] = x1;\n+            *(int16x4_t*)&orig_dst[2*16+k] = x2;\n+            *(int16x4_t*)&orig_dst[3*16+k] = x3;\n+        }\n+\n+\n+#pragma unroll(2)\n+        for (k = 0; k < 8; k+=4)\n+        {\n+            int32x4_t t;\n+            int16x4_t x0,x1,x2,x3;\n+            \n+            t = vsubq_s32(E[7-k],O[7-k]);\n+            t = vshlq_s32(t,minus_shift);\n+            t = vmaxq_s32(t,min);\n+            t = vminq_s32(t,max);\n+            x0 = vmovn_s32(t);\n+            \n+            t = vsubq_s32(E[6-k],O[6-k]);\n+            t = vshlq_s32(t,minus_shift);\n+            t = vmaxq_s32(t,min);\n+            t = vminq_s32(t,max);\n+            x1 = vmovn_s32(t);\n+            \n+            t = vsubq_s32(E[5-k],O[5-k]);\n+ \n+            t = vshlq_s32(t,minus_shift);\n+            t = vmaxq_s32(t,min);\n+            t = vminq_s32(t,max);\n+            x2 = vmovn_s32(t);\n+            \n+            t = vsubq_s32(E[4-k],O[4-k]);\n+            t = vshlq_s32(t,minus_shift);\n+            t = vmaxq_s32(t,min);\n+            t = vminq_s32(t,max);\n+            x3 = vmovn_s32(t);\n+            \n+            transpose_4x4x16(x0,x1,x2,x3);\n+            *(int16x4_t*)&orig_dst[0*16+k+8] = x0;\n+            *(int16x4_t*)&orig_dst[1*16+k+8] = x1;\n+            *(int16x4_t*)&orig_dst[2*16+k+8] = x2;\n+            *(int16x4_t*)&orig_dst[3*16+k+8] = x3;\n+        }\n+        orig_dst += 4*16;\n+        src+=4;\n+    }\n+    \n+#undef MUL\n+#undef FMA\n+#undef FMAK\n+#undef MULK\n+#undef ODD3_15\n+#undef EVEN6_14_STEP4\n+\n+    \n+}\n+\n+\n+\n+static void partialButterflyInverse32_neon(const int16_t* src, int16_t* orig_dst, int shift, int line)\n+{\n+#define MUL(x) vmull_s16(vdup_n_s16(g_t32[x][k]),*(int16x4_t*)&src[x*line]);\n+#define FMA(x) s = vmlal_s16(s,vdup_n_s16(g_t32[x][k]),*(int16x4_t*)&src[(x)*line])\n+#define FMAK(x,l) s[l] = vmlal_lane_s16(s[l],*(int16x4_t*)&src[(x)*line],*(int16x4_t *)&g_t32[x][k],l)\n+#define MULK(x,l) vmull_lane_s16(*(int16x4_t*)&src[x*line],*(int16x4_t *)&g_t32[x][k],l);\n+#define ODD31(k) FMAK(3,k);FMAK(5,k);FMAK(7,k);FMAK(9,k);FMAK(11,k);FMAK(13,k);FMAK(15,k);FMAK(17,k);FMAK(19,k);FMAK(21,k);FMAK(23,k);FMAK(25,k);FMAK(27,k);FMAK(29,k);FMAK(31,k);\n+\n+#define ODD15(k) FMAK(6,k);FMAK(10,k);FMAK(14,k);FMAK(18,k);FMAK(22,k);FMAK(26,k);FMAK(30,k);\n+#define ODD7(k) FMAK(12,k);FMAK(20,k);FMAK(28,k);\n+\n+\n+    int j, k;\n+    int32x4_t E[16], O[16];\n+    int32x4_t EE[8], EO[8];\n+    int32x4_t EEE[4], EEO[4];\n+    int32x4_t EEEE[2], EEEO[2];\n+    int16x4_t dst[32];\n+    int add = 1 << (shift - 1);\n+    \n+#pragma unroll (8)\n+    for (j = 0; j < line; j+=4)\n+    {\n+#pragma unroll (4)\n+        for (k = 0; k < 16; k+=4)\n+        {\n+            int32x4_t s[4];\n+            s[0] = MULK(1,0);\n+            s[1] = MULK(1,1);\n+            s[2] = MULK(1,2);\n+            s[3] = MULK(1,3);\n+            ODD31(0);\n+            ODD31(1);\n+            ODD31(2);\n+            ODD31(3);\n+            O[k] = s[0];\n+            O[k+1] = s[1];\n+            O[k+2] = s[2];\n+            O[k+3] = s[3];\n+            \n+            \n+        }\n+        \n+        \n+#pragma unroll (2)\n+        for (k = 0; k < 8; k+=4)\n+        {\n+            int32x4_t s[4];\n+            s[0] = MULK(2,0);\n+            s[1] = MULK(2,1);\n+            s[2] = MULK(2,2);\n+            s[3] = MULK(2,3);\n+            \n+            ODD15(0);\n+            ODD15(1);\n+            ODD15(2);\n+            ODD15(3);\n+            \n+            EO[k] = s[0];\n+            EO[k+1] = s[1];\n+            EO[k+2] = s[2];\n+            EO[k+3] = s[3];\n+        }\n+        \n+        \n+        for (k = 0; k < 4; k+=4)\n+        {\n+            int32x4_t s[4];\n+            s[0] = MULK(4,0);\n+            s[1] = MULK(4,1);\n+            s[2] = MULK(4,2);\n+            s[3] = MULK(4,3);\n+            \n+            ODD7(0);\n+            ODD7(1);\n+            ODD7(2);\n+            ODD7(3);\n+            \n+            EEO[k] = s[0];\n+            EEO[k+1] = s[1];\n+            EEO[k+2] = s[2];\n+            EEO[k+3] = s[3];\n+        }\n+        \n+#pragma unroll (2)\n+        for (k=0;k<2;k++) {\n+            int32x4_t s;\n+            s = MUL(8);\n+            EEEO[k] = FMA(24);\n+            s = MUL(0);\n+            EEEE[k] = FMA(16);\n+        }\n+        /* Combining even and odd terms at each hierarchy levels to calculate the final spatial domain vector */\n+        EEE[0] = vaddq_s32(EEEE[0],EEEO[0]);\n+        EEE[3] = vsubq_s32(EEEE[0],EEEO[0]);\n+        EEE[1] = vaddq_s32(EEEE[1],EEEO[1]);\n+        EEE[2] = vsubq_s32(EEEE[1],EEEO[1]);\n+        \n+#pragma unroll (4)\n+        for (k = 0; k < 4; k++)\n+        {\n+            EE[k] = vaddq_s32(EEE[k],EEO[k]);\n+            EE[k + 4] = vsubq_s32((EEE[3 - k]), (EEO[3 - k]));\n+        }\n+        \n+#pragma unroll (8)\n+        for (k = 0; k < 8; k++)\n+        {\n+            E[k] = vaddq_s32(EE[k],EO[k]);\n+            E[k + 8] = vsubq_s32((EE[7 - k]),(EO[7 - k]));\n+        }\n+        \n+        static const int32x4_t min = vdupq_n_s32(-32768);\n+        static const int32x4_t max = vdupq_n_s32(32767);\n+        \n+        \n+        \n+#pragma unroll (16)\n+        for (k = 0; k < 16; k++)\n+        {\n+            int32x4_t adde = vaddq_s32(vdupq_n_s32(add),E[k]);\n+            int32x4_t s = vaddq_s32(adde,O[k]);\n+            s = vshlq_s32(s,vdupq_n_s32(-shift));\n+            s = vmaxq_s32(s,min);\n+            s = vminq_s32(s,max);\n+            \n+            \n+            \n+            dst[k] = vmovn_s32(s);\n+            adde = vaddq_s32(vdupq_n_s32(add),(E[15-k]));\n+            s  =vsubq_s32(adde,(O[15-k]));\n+            s = vshlq_s32(s,vdupq_n_s32(-shift));\n+            s = vmaxq_s32(s,min);\n+            s = vminq_s32(s,max);\n+            \n+            dst[k+16] = vmovn_s32(s);\n+        }\n+        \n+\n+#pragma unroll (8)\n+        for (k = 0; k < 32; k+=4)\n+        {\n+            int16x4_t x0 = dst[k+0];\n+            int16x4_t x1 = dst[k+1];\n+            int16x4_t x2 = dst[k+2];\n+            int16x4_t x3 = dst[k+3];\n+            transpose_4x4x16(x0,x1,x2,x3);\n+            *(int16x4_t*)&orig_dst[0*32+k] = x0;\n+            *(int16x4_t*)&orig_dst[1*32+k] = x1;\n+            *(int16x4_t*)&orig_dst[2*32+k] = x2;\n+            *(int16x4_t*)&orig_dst[3*32+k] = x3;\n+        }\n+        orig_dst += 4*32;\n+        src += 4;\n+    }\n+#undef MUL\n+#undef FMA\n+#undef FMAK\n+#undef MULK\n+#undef ODD31\n+#undef ODD15\n+#undef ODD7\n+\n+}\n+\n+\n+static void dct8_neon(const int16_t* src, int16_t* dst, intptr_t srcStride)\n+{\n+    const int shift_1st = 2 + X265_DEPTH - 8;\n+    const int shift_2nd = 9;\n+\n+    ALIGN_VAR_32(int16_t, coef[8 * 8]);\n+    ALIGN_VAR_32(int16_t, block[8 * 8]);\n+\n+    for (int i = 0; i < 8; i++)\n+    {\n+        memcpy(&block[i * 8], &src[i * srcStride], 8 * sizeof(int16_t));\n+    }\n+\n+    partialButterfly8(block, coef, shift_1st, 8);\n+    partialButterfly8(coef, dst, shift_2nd, 8);\n+}\n+\n+static void dct16_neon(const int16_t* src, int16_t* dst, intptr_t srcStride)\n+{\n+    const int shift_1st = 3 + X265_DEPTH - 8;\n+    const int shift_2nd = 10;\n+\n+    ALIGN_VAR_32(int16_t, coef[16 * 16]);\n+    ALIGN_VAR_32(int16_t, block[16 * 16]);\n+\n+    for (int i = 0; i < 16; i++)\n+    {\n+        memcpy(&block[i * 16], &src[i * srcStride], 16 * sizeof(int16_t));\n+    }\n+\n+    partialButterfly16(block, coef, shift_1st, 16);\n+    partialButterfly16(coef, dst, shift_2nd, 16);\n+}\n+\n+static void dct32_neon(const int16_t* src, int16_t* dst, intptr_t srcStride)\n+{\n+    const int shift_1st = 4 + X265_DEPTH - 8;\n+    const int shift_2nd = 11;\n+\n+    ALIGN_VAR_32(int16_t, coef[32 * 32]);\n+    ALIGN_VAR_32(int16_t, block[32 * 32]);\n+\n+    for (int i = 0; i < 32; i++)\n+    {\n+        memcpy(&block[i * 32], &src[i * srcStride], 32 * sizeof(int16_t));\n+    }\n+\n+    partialButterfly32(block, coef, shift_1st, 32);\n+    partialButterfly32(coef, dst, shift_2nd, 32);\n+}\n+\n+static void idct4_neon(const int16_t* src, int16_t* dst, intptr_t dstStride)\n+{\n+    const int shift_1st = 7;\n+    const int shift_2nd = 12 - (X265_DEPTH - 8);\n+\n+    ALIGN_VAR_32(int16_t, coef[4 * 4]);\n+    ALIGN_VAR_32(int16_t, block[4 * 4]);\n+\n+    partialButterflyInverse4(src, coef, shift_1st, 4); // Forward DST BY FAST ALGORITHM, block input, coef output\n+    partialButterflyInverse4(coef, block, shift_2nd, 4); // Forward DST BY FAST ALGORITHM, coef input, coeff output\n+\n+    for (int i = 0; i < 4; i++)\n+    {\n+        memcpy(&dst[i * dstStride], &block[i * 4], 4 * sizeof(int16_t));\n+    }\n+}\n+\n+static void idct16_neon(const int16_t* src, int16_t* dst, intptr_t dstStride)\n+{\n+    const int shift_1st = 7;\n+    const int shift_2nd = 12 - (X265_DEPTH - 8);\n+\n+    ALIGN_VAR_32(int16_t, coef[16 * 16]);\n+    ALIGN_VAR_32(int16_t, block[16 * 16]);\n+\n+    partialButterflyInverse16_neon(src, coef, shift_1st, 16);\n+    partialButterflyInverse16_neon(coef, block, shift_2nd, 16);\n+\n+    for (int i = 0; i < 16; i++)\n+    {\n+        memcpy(&dst[i * dstStride], &block[i * 16], 16 * sizeof(int16_t));\n+    }\n+}\n+\n+static void idct32_neon(const int16_t* src, int16_t* dst, intptr_t dstStride)\n+{\n+    const int shift_1st = 7;\n+    const int shift_2nd = 12 - (X265_DEPTH - 8);\n+\n+    ALIGN_VAR_32(int16_t, coef[32 * 32]);\n+    ALIGN_VAR_32(int16_t, block[32 * 32]);\n+\n+    partialButterflyInverse32_neon(src, coef, shift_1st, 32);\n+    partialButterflyInverse32_neon(coef, block, shift_2nd, 32);\n+\n+    for (int i = 0; i < 32; i++)\n+    {\n+        memcpy(&dst[i * dstStride], &block[i * 32], 32 * sizeof(int16_t));\n+    }\n+}\n+\n+\n+\n+}\n+\n+namespace X265_NS {\n+// x265 private namespace\n+void setupDCTPrimitives_neon(EncoderPrimitives& p) {\n+    p.cu[BLOCK_4x4].nonPsyRdoQuant   = nonPsyRdoQuant_neon<2>;\n+    p.cu[BLOCK_8x8].nonPsyRdoQuant   = nonPsyRdoQuant_neon<3>;\n+    p.cu[BLOCK_16x16].nonPsyRdoQuant = nonPsyRdoQuant_neon<4>;\n+    p.cu[BLOCK_32x32].nonPsyRdoQuant = nonPsyRdoQuant_neon<5>;\n+    p.cu[BLOCK_4x4].psyRdoQuant = psyRdoQuant_neon<2>;\n+    p.cu[BLOCK_8x8].psyRdoQuant = psyRdoQuant_neon<3>;\n+    p.cu[BLOCK_16x16].psyRdoQuant = psyRdoQuant_neon<4>;\n+    p.cu[BLOCK_32x32].psyRdoQuant = psyRdoQuant_neon<5>;\n+    p.cu[BLOCK_8x8].dct   = dct8_neon;\n+    p.cu[BLOCK_16x16].dct = dct16_neon;\n+    p.cu[BLOCK_32x32].dct = dct32_neon;\n+    p.cu[BLOCK_4x4].idct   = idct4_neon;\n+    p.cu[BLOCK_16x16].idct = idct16_neon;\n+    p.cu[BLOCK_32x32].idct = idct32_neon;\n+    p.cu[BLOCK_4x4].count_nonzero = count_nonzero_neon<4>;\n+    p.cu[BLOCK_8x8].count_nonzero = count_nonzero_neon<8>;\n+    p.cu[BLOCK_16x16].count_nonzero = count_nonzero_neon<16>;\n+    p.cu[BLOCK_32x32].count_nonzero = count_nonzero_neon<32>;\n+\n+    p.cu[BLOCK_4x4].copy_cnt   = copy_count_neon<4>;\n+    p.cu[BLOCK_8x8].copy_cnt   = copy_count_neon<8>;\n+    p.cu[BLOCK_16x16].copy_cnt = copy_count_neon<16>;\n+    p.cu[BLOCK_32x32].copy_cnt = copy_count_neon<32>;\n+    p.cu[BLOCK_4x4].psyRdoQuant_1p = nonPsyRdoQuant_neon<2>;\n+    p.cu[BLOCK_4x4].psyRdoQuant_2p = psyRdoQuant_neon<2>;\n+    p.cu[BLOCK_8x8].psyRdoQuant_1p = nonPsyRdoQuant_neon<3>;\n+    p.cu[BLOCK_8x8].psyRdoQuant_2p = psyRdoQuant_neon<3>;\n+    p.cu[BLOCK_16x16].psyRdoQuant_1p = nonPsyRdoQuant_neon<4>;\n+    p.cu[BLOCK_16x16].psyRdoQuant_2p = psyRdoQuant_neon<4>;\n+    p.cu[BLOCK_32x32].psyRdoQuant_1p = nonPsyRdoQuant_neon<5>;\n+    p.cu[BLOCK_32x32].psyRdoQuant_2p = psyRdoQuant_neon<5>;\n+    \n+    p.scanPosLast  =scanPosLast_opt;\n+\n+}\n+};\n+\n+\n+\n+#endif\ndiff -Naur ./source/common/arm64/dct-prim.h ../x265_apple_patch/source/common/arm64/dct-prim.h\n--- ./source/common/arm64/dct-prim.h\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/dct-prim.h\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,18 @@\n+#ifndef __DCT_PRIM_NEON_H__\n+#define __DCT_PRIM_NEON_H__\n+\n+\n+#include \"common.h\"\n+#include \"primitives.h\"\n+#include \"contexts.h\"   // costCoeffNxN_c\n+#include \"threading.h\"  // CLZ\n+\n+namespace X265_NS {\n+// x265 private namespace\n+void setupDCTPrimitives_neon(EncoderPrimitives& p);\n+};\n+\n+\n+\n+#endif\n+\ndiff -Naur ./source/common/arm64/filter-prim.cpp ../x265_apple_patch/source/common/arm64/filter-prim.cpp\n--- ./source/common/arm64/filter-prim.cpp\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/filter-prim.cpp\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,797 @@\n+\n+#if HAVE_NEON\n+\n+#include \"filter-prim.h\"\n+#include <arm_neon.h>\n+\n+namespace {\n+\n+using namespace X265_NS;\n+\n+\n+template<int width, int height>\n+void filterPixelToShort_neon(const pixel* src, intptr_t srcStride, int16_t* dst, intptr_t dstStride)\n+{\n+    const int shift = IF_INTERNAL_PREC - X265_DEPTH;\n+    int row, col;\n+    const int16x8_t off = vdupq_n_s16(IF_INTERNAL_OFFS);\n+    for (row = 0; row < height; row++)\n+    {\n+      \n+        for (col = 0; col < width; col+=8)\n+        {\n+          int16x8_t in;\n+          \n+#if HIGH_BIT_DEPTH\n+          in = *(int16x8_t *)&src[col];\n+#else\n+          in = vmovl_u8(*(uint8x8_t *)&src[col]);\n+#endif\n+          \n+          int16x8_t tmp = vshlq_n_s16(in,shift);\n+          tmp = vsubq_s16(tmp,off);\n+          *(int16x8_t *)&dst[col] = tmp;\n+          \n+        }\n+\n+        src += srcStride;\n+        dst += dstStride;\n+    }\n+}\n+\n+\n+template<int N, int width, int height>\n+void interp_horiz_pp_neon(const pixel* src, intptr_t srcStride, pixel* dst, intptr_t dstStride, int coeffIdx)\n+{\n+    const int16_t* coeff = (N == 4) ? g_chromaFilter[coeffIdx] : g_lumaFilter[coeffIdx];\n+    int headRoom = IF_FILTER_PREC;\n+    int offset =  (1 << (headRoom - 1));\n+    uint16_t maxVal = (1 << X265_DEPTH) - 1;\n+    int cStride = 1;\n+\n+    src -= (N / 2 - 1) * cStride;\n+    int16x8_t vc;\n+    vc = *(int16x8_t *)coeff;\n+    int16x4_t low_vc = vget_low_s16(vc);\n+    int16x4_t high_vc = vget_high_s16(vc);\n+\n+    const int32x4_t voffset = vdupq_n_s32(offset);\n+    const int32x4_t vhr = vdupq_n_s32(-headRoom);\n+    \n+    int row, col;\n+    for (row = 0; row < height; row++)\n+    {\n+        for (col = 0; col < width; col+=8)\n+        {\n+            int32x4_t vsum1,vsum2;\n+            \n+            int16x8_t input[N];\n+            \n+            for (int i=0;i<N;i++)\n+            {\n+#if HIGH_BIT_DEPTH\n+                input[i] = *(int16x8_t *)&src[col+i];\n+#else\n+                input[i] = vmovl_u8(*(uint8x8_t *)&src[col+i]);\n+#endif\n+            }\n+            vsum1 = voffset;\n+            vsum2 = voffset;\n+            \n+            vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[0]),low_vc,0);\n+            vsum2 = vmlal_high_lane_s16(vsum2,input[0],low_vc,0);\n+            \n+            vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[1]),low_vc,1);\n+            vsum2 = vmlal_high_lane_s16(vsum2,input[1],low_vc,1);\n+\n+            vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[2]),low_vc,2);\n+            vsum2 = vmlal_high_lane_s16(vsum2,input[2],low_vc,2);\n+\n+            vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[3]),low_vc,3);\n+            vsum2 = vmlal_high_lane_s16(vsum2,input[3],low_vc,3);\n+\n+            if (N == 8)\n+            {\n+                vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[4]),high_vc,0);\n+                vsum2 = vmlal_high_lane_s16(vsum2,input[4],high_vc,0);\n+                vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[5]),high_vc,1);\n+                vsum2 = vmlal_high_lane_s16(vsum2,input[5],high_vc,1);\n+                vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[6]),high_vc,2);\n+                vsum2 = vmlal_high_lane_s16(vsum2,input[6],high_vc,2);\n+                vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[7]),high_vc,3);\n+                vsum2 = vmlal_high_lane_s16(vsum2,input[7],high_vc,3);\n+                \n+            }\n+            \n+            vsum1 = vshlq_s32(vsum1, vhr);\n+            vsum2 = vshlq_s32(vsum2, vhr);\n+            \n+            int16x8_t vsum = vuzp1q_s16(vsum1,vsum2);\n+            vsum = vminq_s16(vsum,vdupq_n_s16(maxVal));\n+            vsum = vmaxq_s16(vsum,vdupq_n_s16(0));\n+#if HIGH_BIT_DEPTH\n+            *(int16x8_t *)&dst[col] = vsum;\n+#else\n+            uint8x16_t usum = vuzp1q_u8(vsum,vsum);\n+            *(uint8x8_t *)&dst[col] = vget_low_u8(usum);\n+#endif\n+          \n+        }\n+        \n+        src += srcStride;\n+        dst += dstStride;\n+    }\n+}\n+\n+#if HIGH_BIT_DEPTH\n+\n+template<int N, int width, int height>\n+void interp_horiz_ps_neon(const uint16_t * src, intptr_t srcStride, int16_t* dst, intptr_t dstStride, int coeffIdx, int isRowExt)\n+{\n+    const int16_t* coeff = (N == 4) ? g_chromaFilter[coeffIdx] : g_lumaFilter[coeffIdx];\n+    const int headRoom = IF_INTERNAL_PREC - X265_DEPTH;\n+    const int shift = IF_FILTER_PREC - headRoom;\n+    const int offset = (unsigned)-IF_INTERNAL_OFFS << shift;\n+\n+    int blkheight = height;\n+    src -= N / 2 - 1;\n+\n+    if (isRowExt)\n+    {\n+        src -= (N / 2 - 1) * srcStride;\n+        blkheight += N - 1;\n+    }\n+    int32x4_t vc0 = vmovl_s16(*(int16x4_t *)coeff);\n+    int32x4_t vc1;\n+    \n+    if (N ==8) {\n+        vc1 = vmovl_s16(*(int16x4_t *)(coeff + 4));\n+    }\n+    \n+    const int32x4_t voffset = vdupq_n_s32(offset);\n+    const int32x4_t vhr = vdupq_n_s32(-shift);\n+    \n+    int row, col;\n+    for (row = 0; row < blkheight; row++)\n+    {\n+        for (col = 0; col < width; col+=4)\n+        {\n+            int32x4_t vsum;\n+            \n+            int32x4_t input[N];\n+            \n+            for (int i=0;i<N;i++)\n+            {\n+                input[i] = vmovl_s16(*(int16x4_t *)&src[col+i]);\n+            }\n+            vsum = voffset;\n+            vsum = vmlaq_laneq_s32(vsum,(input[0]),vc0,0);\n+            vsum = vmlaq_laneq_s32(vsum,(input[1]),vc0,1);\n+            vsum = vmlaq_laneq_s32(vsum,(input[2]),vc0,2);\n+            vsum = vmlaq_laneq_s32(vsum,(input[3]),vc0,3);\n+\n+\n+            if (N == 8)\n+            {\n+                vsum = vmlaq_laneq_s32(vsum,(input[4]),vc1,0);\n+                vsum = vmlaq_laneq_s32(vsum,(input[5]),vc1,1);\n+                vsum = vmlaq_laneq_s32(vsum,(input[6]),vc1,2);\n+                vsum = vmlaq_laneq_s32(vsum,(input[7]),vc1,3);\n+                \n+            }\n+            \n+            vsum = vshlq_s32(vsum, vhr);\n+            *(int16x4_t *)&dst[col] = vmovn_u32(vsum);\n+        }\n+        \n+        src += srcStride;\n+        dst += dstStride;\n+    }\n+  }\n+\n+\n+#else\n+\n+template<int N, int width, int height>\n+void interp_horiz_ps_neon(const uint8_t* src, intptr_t srcStride, int16_t* dst, intptr_t dstStride, int coeffIdx, int isRowExt)\n+{\n+    const int16_t* coeff = (N == 4) ? g_chromaFilter[coeffIdx] : g_lumaFilter[coeffIdx];\n+    const int headRoom = IF_INTERNAL_PREC - X265_DEPTH;\n+    const int shift = IF_FILTER_PREC - headRoom;\n+    const int offset = (unsigned)-IF_INTERNAL_OFFS << shift;\n+\n+    int blkheight = height;\n+    src -= N / 2 - 1;\n+\n+    if (isRowExt)\n+    {\n+        src -= (N / 2 - 1) * srcStride;\n+        blkheight += N - 1;\n+    }\n+    int16x8_t vc;\n+    vc = *(int16x8_t *)coeff;\n+\n+    const int16x8_t voffset = vdupq_n_s16(offset);\n+    const int16x8_t vhr = vdupq_n_s16(-shift);\n+    \n+    int row, col;\n+    for (row = 0; row < blkheight; row++)\n+    {\n+        for (col = 0; col < width; col+=8)\n+        {\n+            int16x8_t vsum;\n+            \n+            int16x8_t input[N];\n+            \n+            for (int i=0;i<N;i++)\n+            {\n+                input[i] = vmovl_u8(*(uint8x8_t *)&src[col+i]);\n+            }\n+            vsum = voffset;\n+            vsum = vmlaq_laneq_s16(vsum,(input[0]),vc,0);\n+            vsum = vmlaq_laneq_s16(vsum,(input[1]),vc,1);\n+            vsum = vmlaq_laneq_s16(vsum,(input[2]),vc,2);\n+            vsum = vmlaq_laneq_s16(vsum,(input[3]),vc,3);\n+\n+\n+            if (N == 8)\n+            {\n+                vsum = vmlaq_laneq_s16(vsum,(input[4]),vc,4);\n+                vsum = vmlaq_laneq_s16(vsum,(input[5]),vc,5);\n+                vsum = vmlaq_laneq_s16(vsum,(input[6]),vc,6);\n+                vsum = vmlaq_laneq_s16(vsum,(input[7]),vc,7);\n+                \n+            }\n+            \n+            vsum = vshlq_s16(vsum, vhr);\n+            *(int16x8_t *)&dst[col] = vsum;\n+        }\n+        \n+        src += srcStride;\n+        dst += dstStride;\n+    }\n+  }\n+\n+#endif\n+\n+\n+template<int N, int width, int height>\n+void interp_vert_ss_neon(const int16_t* src, intptr_t srcStride, int16_t* dst, intptr_t dstStride, int coeffIdx)\n+{\n+    const int16_t* c = (N == 8 ? g_lumaFilter[coeffIdx] : g_chromaFilter[coeffIdx]);\n+    int shift = IF_FILTER_PREC;\n+    src -= (N / 2 - 1) * srcStride;\n+      int16x8_t vc;\n+      vc = *(int16x8_t *)c;\n+      int16x4_t low_vc = vget_low_s16(vc);\n+      int16x4_t high_vc = vget_high_s16(vc);\n+\n+      const int32x4_t vhr = vdupq_n_s32(-shift);\n+      \n+      int row, col;\n+      for (row = 0; row < height; row++)\n+      {\n+          for (col = 0; col < width; col+=8)\n+          {\n+              int32x4_t vsum1,vsum2;\n+              \n+              int16x8_t input[N];\n+              \n+              for (int i=0;i<N;i++)\n+              {\n+                  input[i] = *(int16x8_t *)&src[col+i*srcStride];\n+              }\n+              \n+              vsum1 = vmull_lane_s16(vget_low_s16(input[0]),low_vc,0);\n+              vsum2 = vmull_high_lane_s16(input[0],low_vc,0);\n+              \n+              vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[1]),low_vc,1);\n+              vsum2 = vmlal_high_lane_s16(vsum2,input[1],low_vc,1);\n+\n+              vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[2]),low_vc,2);\n+              vsum2 = vmlal_high_lane_s16(vsum2,input[2],low_vc,2);\n+\n+              vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[3]),low_vc,3);\n+              vsum2 = vmlal_high_lane_s16(vsum2,input[3],low_vc,3);\n+\n+              if (N == 8)\n+              {\n+                  vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[4]),high_vc,0);\n+                  vsum2 = vmlal_high_lane_s16(vsum2,input[4],high_vc,0);\n+                  vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[5]),high_vc,1);\n+                  vsum2 = vmlal_high_lane_s16(vsum2,input[5],high_vc,1);\n+                  vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[6]),high_vc,2);\n+                  vsum2 = vmlal_high_lane_s16(vsum2,input[6],high_vc,2);\n+                  vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[7]),high_vc,3);\n+                  vsum2 = vmlal_high_lane_s16(vsum2,input[7],high_vc,3);\n+                  \n+              }\n+              \n+              vsum1 = vshlq_s32(vsum1, vhr);\n+              vsum2 = vshlq_s32(vsum2, vhr);\n+              \n+              int16x8_t vsum = vuzp1q_s16(vsum1,vsum2);\n+              *(int16x8_t *)&dst[col] = vsum;\n+          }\n+          \n+          src += srcStride;\n+          dst += dstStride;\n+      }\n+\n+}\n+\n+\n+#if HIGH_BIT_DEPTH\n+\n+template<int N, int width, int height>\n+void interp_vert_pp_neon(const uint16_t* src, intptr_t srcStride, uint16_t* dst, intptr_t dstStride, int coeffIdx)\n+{\n+    \n+    const int16_t* c = (N == 4) ? g_chromaFilter[coeffIdx] : g_lumaFilter[coeffIdx];\n+    int shift = IF_FILTER_PREC;\n+    int offset = 1 << (shift - 1);\n+    const uint16_t maxVal = (1 << X265_DEPTH) - 1;\n+\n+    src -= (N / 2 - 1) * srcStride;\n+    int16x8_t vc;\n+    vc = *(int16x8_t *)c;\n+    int32x4_t low_vc = vmovl_s16(vget_low_s16(vc));\n+    int32x4_t high_vc = vmovl_s16(vget_high_s16(vc));\n+\n+    const int32x4_t voffset = vdupq_n_s32(offset);\n+    const int32x4_t vhr = vdupq_n_s32(-shift);\n+    \n+    int row, col;\n+    for (row = 0; row < height; row++)\n+    {\n+        for (col = 0; col < width; col+=4)\n+        {\n+            int32x4_t vsum;\n+            \n+            int32x4_t input[N];\n+            \n+            for (int i=0;i<N;i++)\n+            {\n+                input[i] = vmovl_u16(*(uint16x4_t *)&src[col+i*srcStride]);\n+            }\n+            vsum = voffset;\n+            \n+            vsum = vmlaq_laneq_s32(vsum,(input[0]),low_vc,0);\n+            vsum = vmlaq_laneq_s32(vsum,(input[1]),low_vc,1);\n+            vsum = vmlaq_laneq_s32(vsum,(input[2]),low_vc,2);\n+            vsum = vmlaq_laneq_s32(vsum,(input[3]),low_vc,3);\n+\n+            if (N == 8)\n+            {\n+              vsum = vmlaq_laneq_s32(vsum,(input[4]),high_vc,0);\n+              vsum = vmlaq_laneq_s32(vsum,(input[5]),high_vc,1);\n+              vsum = vmlaq_laneq_s32(vsum,(input[6]),high_vc,2);\n+              vsum = vmlaq_laneq_s32(vsum,(input[7]),high_vc,3);\n+            }\n+            \n+            vsum = vshlq_s32(vsum, vhr);\n+            vsum = vminq_s32(vsum,vdupq_n_s32(maxVal));\n+            vsum = vmaxq_s32(vsum,vdupq_n_s32(0));\n+            *(uint16x4_t *)&dst[col] = vmovn_u32(vsum);\n+        }\n+        src += srcStride;\n+        dst += dstStride;\n+    }\n+}\n+\n+\n+\n+\n+#else\n+\n+template<int N, int width, int height>\n+void interp_vert_pp_neon(const uint8_t* src, intptr_t srcStride, uint8_t* dst, intptr_t dstStride, int coeffIdx)\n+{\n+    \n+    const int16_t* c = (N == 4) ? g_chromaFilter[coeffIdx] : g_lumaFilter[coeffIdx];\n+    int shift = IF_FILTER_PREC;\n+    int offset = 1 << (shift - 1);\n+    const uint16_t maxVal = (1 << X265_DEPTH) - 1;\n+\n+    src -= (N / 2 - 1) * srcStride;\n+    int16x8_t vc;\n+    vc = *(int16x8_t *)c;\n+\n+    const int16x8_t voffset = vdupq_n_s16(offset);\n+    const int16x8_t vhr = vdupq_n_s16(-shift);\n+    \n+    int row, col;\n+    for (row = 0; row < height; row++)\n+    {\n+        for (col = 0; col < width; col+=8)\n+        {\n+            int16x8_t vsum;\n+            \n+            int16x8_t input[N];\n+            \n+            for (int i=0;i<N;i++)\n+            {\n+                input[i] = vmovl_u8(*(uint8x8_t *)&src[col+i*srcStride]);\n+            }\n+            vsum = voffset;\n+            \n+            vsum = vmlaq_laneq_s16(vsum,(input[0]),vc,0);\n+            vsum = vmlaq_laneq_s16(vsum,(input[1]),vc,1);\n+            vsum = vmlaq_laneq_s16(vsum,(input[2]),vc,2);\n+            vsum = vmlaq_laneq_s16(vsum,(input[3]),vc,3);\n+\n+            if (N == 8)\n+            {\n+              vsum = vmlaq_laneq_s16(vsum,(input[4]),vc,4);\n+              vsum = vmlaq_laneq_s16(vsum,(input[5]),vc,5);\n+              vsum = vmlaq_laneq_s16(vsum,(input[6]),vc,6);\n+              vsum = vmlaq_laneq_s16(vsum,(input[7]),vc,7);\n+\n+            }\n+            \n+            vsum = vshlq_s16(vsum, vhr);\n+            \n+            vsum = vminq_s16(vsum,vdupq_n_s16(maxVal));\n+            vsum = vmaxq_s16(vsum,vdupq_n_s16(0));\n+            uint8x16_t usum = vuzp1q_u8(vsum,vsum);\n+            *(uint8x8_t *)&dst[col] = vget_low_u8(usum);\n+          \n+        }\n+        \n+        src += srcStride;\n+        dst += dstStride;\n+    }\n+}\n+\n+\n+#endif\n+\n+\n+#if HIGH_BIT_DEPTH\n+\n+template<int N, int width, int height>\n+void interp_vert_ps_neon(const uint16_t* src, intptr_t srcStride, int16_t* dst, intptr_t dstStride, int coeffIdx)\n+{\n+    const int16_t* c = (N == 4) ? g_chromaFilter[coeffIdx] : g_lumaFilter[coeffIdx];\n+    int headRoom = IF_INTERNAL_PREC - X265_DEPTH;\n+    int shift = IF_FILTER_PREC - headRoom;\n+    int offset = (unsigned)-IF_INTERNAL_OFFS << shift;\n+    src -= (N / 2 - 1) * srcStride;\n+\n+    int16x8_t vc;\n+    vc = *(int16x8_t *)c;\n+    int32x4_t low_vc = vmovl_s16(vget_low_s16(vc));\n+    int32x4_t high_vc = vmovl_s16(vget_high_s16(vc));\n+\n+    const int32x4_t voffset = vdupq_n_s32(offset);\n+    const int32x4_t vhr = vdupq_n_s32(-shift);\n+    \n+    int row, col;\n+    for (row = 0; row < height; row++)\n+    {\n+        for (col = 0; col < width; col+=4)\n+        {\n+            int16x8_t vsum;\n+            \n+            int16x8_t input[N];\n+            \n+            for (int i=0;i<N;i++)\n+            {\n+                input[i] = vmovl_u16(*(uint16x4_t *)&src[col+i*srcStride]);\n+            }\n+            vsum = voffset;\n+            \n+            vsum = vmlaq_laneq_s32(vsum,(input[0]),low_vc,0);\n+            vsum = vmlaq_laneq_s32(vsum,(input[1]),low_vc,1);\n+            vsum = vmlaq_laneq_s32(vsum,(input[2]),low_vc,2);\n+            vsum = vmlaq_laneq_s32(vsum,(input[3]),low_vc,3);\n+\n+            if (N == 8)\n+            {\n+                int16x8_t  vsum1 = vmulq_laneq_s32((input[4]),high_vc,0);\n+                vsum1 = vmlaq_laneq_s32(vsum1,(input[5]),high_vc,1);\n+                vsum1 = vmlaq_laneq_s32(vsum1,(input[6]),high_vc,2);\n+                vsum1 = vmlaq_laneq_s32(vsum1,(input[7]),high_vc,3);\n+                vsum = vaddq_s32(vsum,vsum1);\n+            }\n+            \n+            vsum = vshlq_s32(vsum, vhr);\n+            \n+            *(uint16x4_t *)&dst[col] = vmovn_s32(vsum);\n+        }\n+        \n+        src += srcStride;\n+        dst += dstStride;\n+    }\n+}\n+\n+#else\n+\n+template<int N, int width, int height>\n+void interp_vert_ps_neon(const uint8_t* src, intptr_t srcStride, int16_t* dst, intptr_t dstStride, int coeffIdx)\n+{\n+    const int16_t* c = (N == 4) ? g_chromaFilter[coeffIdx] : g_lumaFilter[coeffIdx];\n+    int headRoom = IF_INTERNAL_PREC - X265_DEPTH;\n+    int shift = IF_FILTER_PREC - headRoom;\n+    int offset = (unsigned)-IF_INTERNAL_OFFS << shift;\n+    src -= (N / 2 - 1) * srcStride;\n+\n+    int16x8_t vc;\n+    vc = *(int16x8_t *)c;\n+\n+    const int16x8_t voffset = vdupq_n_s16(offset);\n+    const int16x8_t vhr = vdupq_n_s16(-shift);\n+    \n+    int row, col;\n+    for (row = 0; row < height; row++)\n+    {\n+        for (col = 0; col < width; col+=8)\n+        {\n+            int16x8_t vsum;\n+            \n+            int16x8_t input[N];\n+            \n+            for (int i=0;i<N;i++)\n+            {\n+                input[i] = vmovl_u8(*(uint8x8_t *)&src[col+i*srcStride]);\n+            }\n+            vsum = voffset;\n+            \n+            vsum = vmlaq_laneq_s16(vsum,(input[0]),vc,0);\n+            vsum = vmlaq_laneq_s16(vsum,(input[1]),vc,1);\n+            vsum = vmlaq_laneq_s16(vsum,(input[2]),vc,2);\n+            vsum = vmlaq_laneq_s16(vsum,(input[3]),vc,3);\n+\n+            if (N == 8)\n+            {\n+                int16x8_t  vsum1 = vmulq_laneq_s16((input[4]),vc,4);\n+                vsum1 = vmlaq_laneq_s16(vsum1,(input[5]),vc,5);\n+                vsum1 = vmlaq_laneq_s16(vsum1,(input[6]),vc,6);\n+                vsum1 = vmlaq_laneq_s16(vsum1,(input[7]),vc,7);\n+                vsum = vaddq_s16(vsum,vsum1);\n+            }\n+            \n+            vsum = vshlq_s32(vsum, vhr);\n+            *(int16x8_t *)&dst[col] = vsum;\n+        }\n+        \n+        src += srcStride;\n+        dst += dstStride;\n+    }\n+}\n+\n+#endif\n+\n+\n+\n+template<int N, int width, int height>\n+void interp_vert_sp_neon(const int16_t* src, intptr_t srcStride, pixel* dst, intptr_t dstStride, int coeffIdx)\n+{\n+    int headRoom = IF_INTERNAL_PREC - X265_DEPTH;\n+    int shift = IF_FILTER_PREC + headRoom;\n+    int offset = (1 << (shift - 1)) + (IF_INTERNAL_OFFS << IF_FILTER_PREC);\n+    uint16_t maxVal = (1 << X265_DEPTH) - 1;\n+    const int16_t* coeff = (N == 8 ? g_lumaFilter[coeffIdx] : g_chromaFilter[coeffIdx]);\n+\n+    src -= (N / 2 - 1) * srcStride;\n+\n+    int16x8_t vc;\n+    vc = *(int16x8_t *)coeff;\n+    int16x4_t low_vc = vget_low_s16(vc);\n+    int16x4_t high_vc = vget_high_s16(vc);\n+\n+    const int32x4_t voffset = vdupq_n_s32(offset);\n+    const int32x4_t vhr = vdupq_n_s32(-shift);\n+\n+    int row, col;\n+    for (row = 0; row < height; row++)\n+    {\n+        for (col = 0; col < width; col+=8)\n+        {\n+            int32x4_t vsum1,vsum2;\n+\n+            int16x8_t input[N];\n+\n+            for (int i=0;i<N;i++)\n+            {\n+                input[i] = *(int16x8_t *)&src[col+i*srcStride];\n+            }\n+            vsum1 = voffset;\n+            vsum2 = voffset;\n+\n+            vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[0]),low_vc,0);\n+            vsum2 = vmlal_high_lane_s16(vsum2,input[0],low_vc,0);\n+\n+            vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[1]),low_vc,1);\n+            vsum2 = vmlal_high_lane_s16(vsum2,input[1],low_vc,1);\n+\n+            vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[2]),low_vc,2);\n+            vsum2 = vmlal_high_lane_s16(vsum2,input[2],low_vc,2);\n+\n+            vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[3]),low_vc,3);\n+            vsum2 = vmlal_high_lane_s16(vsum2,input[3],low_vc,3);\n+\n+            if (N == 8)\n+            {\n+                vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[4]),high_vc,0);\n+                vsum2 = vmlal_high_lane_s16(vsum2,input[4],high_vc,0);\n+                vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[5]),high_vc,1);\n+                vsum2 = vmlal_high_lane_s16(vsum2,input[5],high_vc,1);\n+                vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[6]),high_vc,2);\n+                vsum2 = vmlal_high_lane_s16(vsum2,input[6],high_vc,2);\n+                vsum1 = vmlal_lane_s16(vsum1,vget_low_s16(input[7]),high_vc,3);\n+                vsum2 = vmlal_high_lane_s16(vsum2,input[7],high_vc,3);\n+            }\n+\n+            vsum1 = vshlq_s32(vsum1, vhr);\n+            vsum2 = vshlq_s32(vsum2, vhr);\n+\n+            int16x8_t vsum = vuzp1q_s16(vsum1,vsum2);\n+            vsum = vminq_s16(vsum,vdupq_n_s16(maxVal));\n+            vsum = vmaxq_s16(vsum,vdupq_n_s16(0));\n+#if HIGH_BIT_DEPTH\n+            *(int16x8_t *)&dst[col] = vsum;\n+#else\n+            uint8x16_t usum = vuzp1q_u8(vsum,vsum);\n+            *(uint8x8_t *)&dst[col] = vget_low_u8(usum);\n+#endif\n+\n+        }\n+          \n+        src += srcStride;\n+        dst += dstStride;\n+    }\n+}\n+\n+\n+\n+\n+\n+\n+template<int N, int width, int height>\n+void interp_hv_pp_neon(const pixel* src, intptr_t srcStride, pixel* dst, intptr_t dstStride, int idxX, int idxY)\n+{\n+    ALIGN_VAR_32(int16_t, immed[width * (height + N - 1)]);\n+\n+    interp_horiz_ps_neon<N, width, height>(src, srcStride, immed, width, idxX, 1);\n+    interp_vert_sp_neon<N,width,height>(immed + (N / 2 - 1) * width, width, dst, dstStride, idxY);\n+}\n+\n+\n+\n+}\n+\n+\n+\n+\n+namespace X265_NS {\n+   #define CHROMA_420(W, H) \\\n+       p.chroma[X265_CSP_I420].pu[CHROMA_420_ ## W ## x ## H].filter_hpp = interp_horiz_pp_neon<4, W, H>; \\\n+       p.chroma[X265_CSP_I420].pu[CHROMA_420_ ## W ## x ## H].filter_hps = interp_horiz_ps_neon<4, W, H>; \\\n+       p.chroma[X265_CSP_I420].pu[CHROMA_420_ ## W ## x ## H].filter_vpp = interp_vert_pp_neon<4, W, H>;  \\\n+       p.chroma[X265_CSP_I420].pu[CHROMA_420_ ## W ## x ## H].filter_vps = interp_vert_ps_neon<4, W, H>;  \\\n+       p.chroma[X265_CSP_I420].pu[CHROMA_420_ ## W ## x ## H].filter_vsp = interp_vert_sp_neon<4, W, H>;  \\\n+       p.chroma[X265_CSP_I420].pu[CHROMA_420_ ## W ## x ## H].filter_vss = interp_vert_ss_neon<4, W, H>; \\\n+       p.chroma[X265_CSP_I420].pu[CHROMA_420_ ## W ## x ## H].p2s[NONALIGNED] = filterPixelToShort_neon<W, H>;\\\n+       p.chroma[X265_CSP_I420].pu[CHROMA_420_ ## W ## x ## H].p2s[ALIGNED] = filterPixelToShort_neon<W, H>;\n+\n+   #define CHROMA_422(W, H) \\\n+       p.chroma[X265_CSP_I422].pu[CHROMA_422_ ## W ## x ## H].filter_hpp = interp_horiz_pp_neon<4, W, H>; \\\n+       p.chroma[X265_CSP_I422].pu[CHROMA_422_ ## W ## x ## H].filter_hps = interp_horiz_ps_neon<4, W, H>; \\\n+       p.chroma[X265_CSP_I422].pu[CHROMA_422_ ## W ## x ## H].filter_vpp = interp_vert_pp_neon<4, W, H>;  \\\n+       p.chroma[X265_CSP_I422].pu[CHROMA_422_ ## W ## x ## H].filter_vps = interp_vert_ps_neon<4, W, H>;  \\\n+       p.chroma[X265_CSP_I422].pu[CHROMA_422_ ## W ## x ## H].filter_vsp = interp_vert_sp_neon<4, W, H>;  \\\n+       p.chroma[X265_CSP_I422].pu[CHROMA_422_ ## W ## x ## H].filter_vss = interp_vert_ss_neon<4, W, H>; \\\n+       p.chroma[X265_CSP_I422].pu[CHROMA_422_ ## W ## x ## H].p2s[NONALIGNED] = filterPixelToShort_neon<W, H>;\\\n+       p.chroma[X265_CSP_I422].pu[CHROMA_422_ ## W ## x ## H].p2s[ALIGNED] = filterPixelToShort_neon<W, H>;\n+\n+   #define CHROMA_444(W, H) \\\n+       p.chroma[X265_CSP_I444].pu[LUMA_ ## W ## x ## H].filter_hpp = interp_horiz_pp_neon<4, W, H>; \\\n+       p.chroma[X265_CSP_I444].pu[LUMA_ ## W ## x ## H].filter_hps = interp_horiz_ps_neon<4, W, H>; \\\n+       p.chroma[X265_CSP_I444].pu[LUMA_ ## W ## x ## H].filter_vpp = interp_vert_pp_neon<4, W, H>;  \\\n+       p.chroma[X265_CSP_I444].pu[LUMA_ ## W ## x ## H].filter_vps = interp_vert_ps_neon<4, W, H>;  \\\n+       p.chroma[X265_CSP_I444].pu[LUMA_ ## W ## x ## H].filter_vsp = interp_vert_sp_neon<4, W, H>;  \\\n+       p.chroma[X265_CSP_I444].pu[LUMA_ ## W ## x ## H].filter_vss = interp_vert_ss_neon<4, W, H>; \\\n+       p.chroma[X265_CSP_I444].pu[LUMA_ ## W ## x ## H].p2s[NONALIGNED] = filterPixelToShort_neon<W, H>;\\\n+       p.chroma[X265_CSP_I444].pu[LUMA_ ## W ## x ## H].p2s[ALIGNED] = filterPixelToShort_neon<W, H>;\n+\n+   #define LUMA(W, H) \\\n+       p.pu[LUMA_ ## W ## x ## H].luma_hpp     = interp_horiz_pp_neon<8, W, H>; \\\n+       p.pu[LUMA_ ## W ## x ## H].luma_hps     = interp_horiz_ps_neon<8, W, H>; \\\n+       p.pu[LUMA_ ## W ## x ## H].luma_vpp     = interp_vert_pp_neon<8, W, H>;  \\\n+       p.pu[LUMA_ ## W ## x ## H].luma_vps     = interp_vert_ps_neon<8, W, H>;  \\\n+       p.pu[LUMA_ ## W ## x ## H].luma_vsp     = interp_vert_sp_neon<8, W, H>;  \\\n+       p.pu[LUMA_ ## W ## x ## H].luma_vss     = interp_vert_ss_neon<8, W, H>;  \\\n+       p.pu[LUMA_ ## W ## x ## H].luma_hvpp    = interp_hv_pp_neon<8, W, H>; \\\n+       p.pu[LUMA_ ## W ## x ## H].convert_p2s[NONALIGNED] = filterPixelToShort_neon<W, H>;\\\n+       p.pu[LUMA_ ## W ## x ## H].convert_p2s[ALIGNED] = filterPixelToShort_neon<W, H>;\n+\n+  \n+void setupFilterPrimitives_neon(EncoderPrimitives &p)\n+{\n+  \n+  // All neon functions assume width of multiple of 8, (2,4,12 variants are not optimized)\n+  \n+  LUMA(8, 8);\n+  LUMA(8, 4);\n+  LUMA(16, 16);\n+  CHROMA_420(8,  8);\n+  LUMA(16,  8);\n+  CHROMA_420(8,  4);\n+  LUMA(8, 16);\n+  LUMA(16, 12);\n+  CHROMA_420(8,  6);\n+  LUMA(16,  4);\n+  CHROMA_420(8,  2);\n+  LUMA(32, 32);\n+  CHROMA_420(16, 16);\n+  LUMA(32, 16);\n+  CHROMA_420(16, 8);\n+  LUMA(16, 32);\n+  CHROMA_420(8,  16);\n+  LUMA(32, 24);\n+  CHROMA_420(16, 12);\n+  LUMA(24, 32);\n+  LUMA(32,  8);\n+  CHROMA_420(16, 4);\n+  LUMA(8, 32);\n+  LUMA(64, 64);\n+  CHROMA_420(32, 32);\n+  LUMA(64, 32);\n+  CHROMA_420(32, 16);\n+  LUMA(32, 64);\n+  CHROMA_420(16, 32);\n+  LUMA(64, 48);\n+  CHROMA_420(32, 24);\n+  LUMA(48, 64);\n+  CHROMA_420(24, 32);\n+  LUMA(64, 16);\n+  CHROMA_420(32, 8);\n+  LUMA(16, 64);\n+  CHROMA_420(8,  32);\n+  CHROMA_422(8,  16);\n+  CHROMA_422(8,  8);\n+  CHROMA_422(8,  12);\n+  CHROMA_422(8,  4);\n+  CHROMA_422(16, 32);\n+  CHROMA_422(16, 16);\n+  CHROMA_422(8,  32);\n+  CHROMA_422(16, 24);\n+  CHROMA_422(16, 8);\n+  CHROMA_422(32, 64);\n+  CHROMA_422(32, 32);\n+  CHROMA_422(16, 64);\n+  CHROMA_422(32, 48);\n+  CHROMA_422(24, 64);\n+  CHROMA_422(32, 16);\n+  CHROMA_422(8,  64);\n+  CHROMA_444(8,  8);\n+  CHROMA_444(8,  4);\n+  CHROMA_444(16, 16);\n+  CHROMA_444(16, 8);\n+  CHROMA_444(8,  16);\n+  CHROMA_444(16, 12);\n+  CHROMA_444(16, 4);\n+  CHROMA_444(32, 32);\n+  CHROMA_444(32, 16);\n+  CHROMA_444(16, 32);\n+  CHROMA_444(32, 24);\n+  CHROMA_444(24, 32);\n+  CHROMA_444(32, 8);\n+  CHROMA_444(8,  32);\n+  CHROMA_444(64, 64);\n+  CHROMA_444(64, 32);\n+  CHROMA_444(32, 64);\n+  CHROMA_444(64, 48);\n+  CHROMA_444(48, 64);\n+  CHROMA_444(64, 16);\n+  CHROMA_444(16, 64);\n+\n+}\n+\n+};\n+\n+\n+#endif\n+\n+\ndiff -Naur ./source/common/arm64/filter-prim.h ../x265_apple_patch/source/common/arm64/filter-prim.h\n--- ./source/common/arm64/filter-prim.h\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/filter-prim.h\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,20 @@\n+#ifndef _FILTER_PRIM_ARM64_H__\n+#define _FILTER_PRIM_ARM64_H__\n+\n+\n+#include \"common.h\"\n+#include \"slicetype.h\"      // LOWRES_COST_MASK\n+#include \"primitives.h\"\n+#include \"x265.h\"\n+\n+\n+namespace X265_NS {\n+   \n+  \n+void setupFilterPrimitives_neon(EncoderPrimitives &p);\n+\n+};\n+\n+\n+#endif\n+\ndiff -Naur ./source/common/arm64/intrapred-prim.cpp ../x265_apple_patch/source/common/arm64/intrapred-prim.cpp\n--- ./source/common/arm64/intrapred-prim.cpp\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/intrapred-prim.cpp\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,266 @@\n+/*****************************************************************************\n+ * Copyright (C) 2013-2017 MulticoreWare, Inc\n+ *\n+ * Authors: Min Chen <chenm003@163.com>\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License as published by\n+ * the Free Software Foundation; either version 2 of the License, or\n+ * (at your option) any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU General Public License\n+ * along with this program; if not, write to the Free Software\n+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.\n+ *\n+ * This program is also available under a commercial proprietary license.\n+ * For more information, contact us at license @ x265.com.\n+ *****************************************************************************/\n+\n+\n+#include \"common.h\"\n+#include \"primitives.h\"\n+\n+\n+#if 1\n+#include \"arm64-utils.h\"\n+#include <arm_neon.h>\n+\n+using namespace X265_NS;\n+\n+namespace {\n+\n+\n+\n+template<int width>\n+void intra_pred_ang_neon(pixel* dst, intptr_t dstStride, const pixel *srcPix0, int dirMode, int bFilter)\n+{\n+    int width2 = width << 1;\n+    // Flip the neighbours in the horizontal case.\n+    int horMode = dirMode < 18;\n+    pixel neighbourBuf[129];\n+    const pixel *srcPix = srcPix0;\n+\n+    if (horMode)\n+    {\n+        neighbourBuf[0] = srcPix[0];\n+        //for (int i = 0; i < width << 1; i++)\n+        //{\n+        //    neighbourBuf[1 + i] = srcPix[width2 + 1 + i];\n+        //    neighbourBuf[width2 + 1 + i] = srcPix[1 + i];\n+        //}\n+        memcpy(&neighbourBuf[1],&srcPix[width2+1],sizeof(pixel)*(width << 1));\n+        memcpy(&neighbourBuf[width2 + 1],&srcPix[1],sizeof(pixel)*(width << 1));\n+        srcPix = neighbourBuf;\n+    }\n+\n+    // Intra prediction angle and inverse angle tables.\n+    const int8_t angleTable[17] = { -32, -26, -21, -17, -13, -9, -5, -2, 0, 2, 5, 9, 13, 17, 21, 26, 32 };\n+    const int16_t invAngleTable[8] = { 4096, 1638, 910, 630, 482, 390, 315, 256 };\n+\n+    // Get the prediction angle.\n+    int angleOffset = horMode ? 10 - dirMode : dirMode - 26;\n+    int angle = angleTable[8 + angleOffset];\n+\n+    // Vertical Prediction.\n+    if (!angle)\n+    {\n+        for (int y = 0; y < width; y++) {\n+            memcpy(&dst[y * dstStride],srcPix + 1,sizeof(pixel)*width);\n+        }\n+        if (bFilter)\n+        {\n+            int topLeft = srcPix[0], top = srcPix[1];\n+            for (int y = 0; y < width; y++)\n+                dst[y * dstStride] = x265_clip((int16_t)(top + ((srcPix[width2 + 1 + y] - topLeft) >> 1)));\n+        }\n+    }\n+    else // Angular prediction.\n+    {\n+        // Get the reference pixels. The reference base is the first pixel to the top (neighbourBuf[1]).\n+        pixel refBuf[64];\n+        const pixel *ref;\n+\n+        // Use the projected left neighbours and the top neighbours.\n+        if (angle < 0)\n+        {\n+            // Number of neighbours projected.\n+            int nbProjected = -((width * angle) >> 5) - 1;\n+            pixel *ref_pix = refBuf + nbProjected + 1;\n+\n+            // Project the neighbours.\n+            int invAngle = invAngleTable[- angleOffset - 1];\n+            int invAngleSum = 128;\n+            for (int i = 0; i < nbProjected; i++)\n+            {\n+                invAngleSum += invAngle;\n+                ref_pix[- 2 - i] = srcPix[width2 + (invAngleSum >> 8)];\n+            }\n+\n+            // Copy the top-left and top pixels.\n+            //for (int i = 0; i < width + 1; i++)\n+                //ref_pix[-1 + i] = srcPix[i];\n+            \n+            memcpy(&ref_pix[-1],srcPix,(width+1)*sizeof(pixel));\n+            ref = ref_pix;\n+        }\n+        else // Use the top and top-right neighbours.\n+            ref = srcPix + 1;\n+\n+        // Pass every row.\n+        int angleSum = 0;\n+        for (int y = 0; y < width; y++)\n+        {\n+            angleSum += angle;\n+            int offset = angleSum >> 5;\n+            int fraction = angleSum & 31;\n+\n+            if (fraction) // Interpolate\n+            {\n+                if (width >= 8 && sizeof(pixel) == 1)\n+                {\n+                    const int16x8_t f0 = vdupq_n_s16(32-fraction);\n+                    const int16x8_t f1 = vdupq_n_s16(fraction);\n+                    for (int x = 0;x<width;x+=8) {\n+                        uint8x8_t in0 = *(uint8x8_t *)&ref[offset + x];\n+                        uint8x8_t in1 = *(uint8x8_t *)&ref[offset+ x + 1];\n+                        int16x8_t lo = vmlaq_s16(vdupq_n_s16(16),vmovl_u8(in0),f0);\n+                        lo = vmlaq_s16(lo,vmovl_u8(in1),f1);\n+                        lo = vshrq_n_s16(lo,5);\n+                        *(uint8x8_t *)&dst[y * dstStride + x] = vmovn_u16(lo);\n+                    }\n+                }\n+                else if (width >= 4 && sizeof(pixel) == 2)\n+                {\n+                    const int32x4_t f0 = vdupq_n_s32(32-fraction);\n+                    const int32x4_t f1 = vdupq_n_s32(fraction);\n+                    for (int x = 0;x<width;x+=4) {\n+                        uint16x4_t in0 = *(uint16x4_t *)&ref[offset + x];\n+                        uint16x4_t in1 = *(uint16x4_t *)&ref[offset+ x + 1];\n+                        int32x4_t lo = vmlaq_s32(vdupq_n_s32(16),vmovl_u16(in0),f0);\n+                        lo = vmlaq_s32(lo,vmovl_u16(in1),f1);\n+                        lo = vshrq_n_s32(lo,5);\n+                        *(uint16x4_t *)&dst[y * dstStride + x] = vmovn_u32(lo);\n+                    }\n+                }\n+                else {\n+                    for (int x = 0; x < width; x++)\n+                        dst[y * dstStride + x] = (pixel)(((32 - fraction) * ref[offset + x] + fraction * ref[offset + x + 1] + 16) >> 5);\n+                }\n+            }\n+            else // Copy.\n+            {\n+                memcpy(&dst[y * dstStride],&ref[offset],sizeof(pixel)*width);\n+            }\n+        }\n+    }\n+\n+    // Flip for horizontal.\n+    if (horMode)\n+    {\n+        if (width == 8)  transpose8x8(dst,dst,dstStride,dstStride);\n+        else if (width == 16) transpose16x16(dst,dst,dstStride,dstStride);\n+        else if (width == 32) transpose32x32(dst,dst,dstStride,dstStride);\n+        else {\n+            for (int y = 0; y < width - 1; y++)\n+            {\n+                for (int x = y + 1; x < width; x++)\n+                {\n+                    pixel tmp              = dst[y * dstStride + x];\n+                    dst[y * dstStride + x] = dst[x * dstStride + y];\n+                    dst[x * dstStride + y] = tmp;\n+                }\n+            }\n+        }\n+    }\n+}\n+\n+template<int log2Size>\n+void all_angs_pred_neon(pixel *dest, pixel *refPix, pixel *filtPix, int bLuma)\n+{\n+    const int size = 1 << log2Size;\n+    for (int mode = 2; mode <= 34; mode++)\n+    {\n+        pixel *srcPix  = (g_intraFilterFlags[mode] & size ? filtPix  : refPix);\n+        pixel *out = dest + ((mode - 2) << (log2Size * 2));\n+\n+        intra_pred_ang_neon<size>(out, size, srcPix, mode, bLuma);\n+\n+        // Optimize code don't flip buffer\n+        bool modeHor = (mode < 18);\n+\n+        // transpose the block if this is a horizontal mode\n+        if (modeHor)\n+        {\n+            if (size == 8) transpose8x8(out,out,size,size);\n+            else if (size == 16) transpose16x16(out,out,size,size);\n+            else if (size == 32) transpose32x32(out,out,size,size);\n+            else {\n+                for (int k = 0; k < size - 1; k++)\n+                {\n+                    for (int l = k + 1; l < size; l++)\n+                    {\n+                        pixel tmp         = out[k * size + l];\n+                        out[k * size + l] = out[l * size + k];\n+                        out[l * size + k] = tmp;\n+                    }\n+                }\n+            }\n+        }\n+    }\n+}\n+}\n+\n+namespace X265_NS {\n+// x265 private namespace\n+\n+void setupIntraPrimitives_neon(EncoderPrimitives& p)\n+{\n+//    p.cu[BLOCK_4x4].intra_filter = intraFilter<4>;\n+//    p.cu[BLOCK_8x8].intra_filter = intraFilter<8>;\n+//    p.cu[BLOCK_16x16].intra_filter = intraFilter<16>;\n+//    p.cu[BLOCK_32x32].intra_filter = intraFilter<32>;\n+\n+//    p.cu[BLOCK_4x4].intra_pred[PLANAR_IDX] = planar_pred_neon<2>;\n+//    p.cu[BLOCK_8x8].intra_pred[PLANAR_IDX] = planar_pred_neon<3>;\n+//    p.cu[BLOCK_16x16].intra_pred[PLANAR_IDX] = planar_pred_neon<4>;\n+//    p.cu[BLOCK_32x32].intra_pred[PLANAR_IDX] = planar_pred_neon<5>;\n+//\n+//    p.cu[BLOCK_4x4].intra_pred[DC_IDX] = intra_pred_dc_neon<4>;\n+//    p.cu[BLOCK_8x8].intra_pred[DC_IDX] = intra_pred_dc_neon<8>;\n+//    p.cu[BLOCK_16x16].intra_pred[DC_IDX] = intra_pred_dc_neon<16>;\n+//    p.cu[BLOCK_32x32].intra_pred[DC_IDX] = intra_pred_dc_neon<32>;\n+\n+    for (int i = 2; i < NUM_INTRA_MODE; i++)\n+    {\n+        p.cu[BLOCK_4x4].intra_pred[i] = intra_pred_ang_neon<4>;\n+        p.cu[BLOCK_8x8].intra_pred[i] = intra_pred_ang_neon<8>;\n+        p.cu[BLOCK_16x16].intra_pred[i] = intra_pred_ang_neon<16>;\n+        p.cu[BLOCK_32x32].intra_pred[i] = intra_pred_ang_neon<32>;\n+    }\n+\n+    p.cu[BLOCK_4x4].intra_pred_allangs = all_angs_pred_neon<2>;\n+    p.cu[BLOCK_8x8].intra_pred_allangs = all_angs_pred_neon<3>;\n+    p.cu[BLOCK_16x16].intra_pred_allangs = all_angs_pred_neon<4>;\n+    p.cu[BLOCK_32x32].intra_pred_allangs = all_angs_pred_neon<5>;\n+}\n+}\n+\n+\n+\n+#else\n+\n+namespace X265_NS {\n+// x265 private namespace\n+void setupIntraPrimitives_neon(EncoderPrimitives& p)\n+{}\n+}\n+\n+#endif\n+\n+\n+\ndiff -Naur ./source/common/arm64/intrapred-prim.h ../x265_apple_patch/source/common/arm64/intrapred-prim.h\n--- ./source/common/arm64/intrapred-prim.h\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/intrapred-prim.h\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,14 @@\n+#ifndef INTRAPRED_PRIM_H__\n+\n+#if defined(__aarch64__)\n+\n+namespace X265_NS {\n+// x265 private namespace\n+\n+void setupIntraPrimitives_neon(EncoderPrimitives& p);\n+}\n+\n+#endif\n+\n+#endif\n+\ndiff -Naur ./source/common/arm64/loopfilter-prim.cpp ../x265_apple_patch/source/common/arm64/loopfilter-prim.cpp\n--- ./source/common/arm64/loopfilter-prim.cpp\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/loopfilter-prim.cpp\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,305 @@\n+/*****************************************************************************\n+* Copyright (C) 2013-2017 MulticoreWare, Inc\n+*\n+* Authors: Praveen Kumar Tiwari <praveen@multicorewareinc.com>\n+*          Dnyaneshwar Gorade <dnyaneshwar@multicorewareinc.com>\n+*          Min Chen <chenm003@163.com>\n+*\n+* This program is free software; you can redistribute it and/or modify\n+* it under the terms of the GNU General Public License as published by\n+* the Free Software Foundation; either version 2 of the License, or\n+* (at your option) any later version.\n+*\n+* This program is distributed in the hope that it will be useful,\n+* but WITHOUT ANY WARRANTY; without even the implied warranty of\n+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+* GNU General Public License for more details.\n+*\n+* You should have received a copy of the GNU General Public License\n+* along with this program; if not, write to the Free Software\n+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.\n+*\n+* This program is also available under a commercial proprietary license.\n+* For more information, contact us at license @ x265.com.\n+*****************************************************************************/\n+#include \"loopfilter-prim.h\"\n+\n+#define PIXEL_MIN 0\n+\n+\n+\n+#if !(HIGH_BIT_DEPTH) && defined(HAVE_NEON)\n+#include<arm_neon.h>\n+\n+namespace {\n+\n+\n+/* get the sign of input variable (TODO: this is a dup, make common) */\n+static inline int8_t signOf(int x)\n+{\n+    return (x >> 31) | ((int)((((uint32_t)-x)) >> 31));\n+}\n+\n+static inline int8x8_t sign_diff_neon(const uint8x8_t in0, const uint8x8_t in1)\n+{\n+  int16x8_t in = vsubl_u8(in0,in1);\n+  return vmovn_s16(vmaxq_s16(vminq_s16(in,vdupq_n_s16(1)),vdupq_n_s16(-1)));\n+}\n+\n+static void calSign_neon(int8_t *dst, const pixel *src1, const pixel *src2, const int endX)\n+{\n+  int x = 0;\n+  for (; (x + 8) <= endX; x += 8) {\n+    *(int8x8_t *)&dst[x]  = sign_diff_neon(*(uint8x8_t *)&src1[x],*(uint8x8_t *)&src2[x]);\n+  }\n+\n+    for (; x < endX; x++)\n+        dst[x] = signOf(src1[x] - src2[x]);\n+}\n+\n+static void processSaoCUE0_neon(pixel * rec, int8_t * offsetEo, int width, int8_t* signLeft, intptr_t stride)\n+{\n+\n+  \n+    int y;\n+    int8_t signRight, signLeft0;\n+    int8_t edgeType;\n+\n+    for (y = 0; y < 2; y++)\n+    {\n+        signLeft0 = signLeft[y];\n+        int x = 0;\n+\n+        if (width >= 8) {\n+            int8x8_t vsignRight;\n+            int8x8x2_t shifter;\n+            shifter.val[1][0] = signLeft0;\n+            static const int8x8_t index = {8,0,1,2,3,4,5,6};\n+            int8x8_t tbl = *(int8x8_t *)offsetEo;\n+            for (; (x+8) <= width; x+=8)\n+            {\n+                uint8x8_t in = *(uint8x8_t *)&rec[x];\n+                vsignRight = sign_diff_neon(in,*(uint8x8_t *)&rec[x+1]);\n+                shifter.val[0] = vneg_s8(vsignRight);\n+                int8x8_t tmp = shifter.val[0];\n+                int8x8_t edge = vtbl2_s8(shifter,index);\n+                int8x8_t vedgeType = vadd_s8(vadd_s8(vsignRight,edge),vdup_n_s8(2));\n+                shifter.val[1][0] = tmp[7];\n+                int16x8_t t1 = vmovl_s8(vtbl1_s8(tbl,vedgeType));\n+                t1 = vaddw_u8(t1,in);\n+                t1 = vmaxq_s16(t1,vdupq_n_s16(0));\n+                t1 = vminq_s16(t1,vdupq_n_s16(255));\n+                *(uint8x8_t *)&rec[x] = vmovn_u16(t1);\n+            }\n+            signLeft0 = shifter.val[1][0];\n+        }\n+        for (; x < width; x++)\n+        {\n+            signRight = ((rec[x] - rec[x + 1]) < 0) ? -1 : ((rec[x] - rec[x + 1]) > 0) ? 1 : 0;\n+            edgeType = signRight + signLeft0 + 2;\n+            signLeft0 = -signRight;\n+            rec[x] = x265_clip(rec[x] + offsetEo[edgeType]);\n+        }\n+        rec += stride;\n+    }\n+}\n+\n+static void processSaoCUE1_neon(pixel* rec, int8_t* upBuff1, int8_t* offsetEo, intptr_t stride, int width)\n+{\n+    int x = 0;\n+    int8_t signDown;\n+    int edgeType;\n+\n+    if (width >= 8) {\n+        int8x8_t tbl = *(int8x8_t *)offsetEo;\n+        for (; (x+8) <= width; x+=8)\n+        {\n+            uint8x8_t in0 = *(uint8x8_t *)&rec[x];\n+            uint8x8_t in1 = *(uint8x8_t *)&rec[x+stride];\n+            int8x8_t vsignDown = sign_diff_neon(in0,in1);\n+            int8x8_t vedgeType = vadd_s8(vadd_s8(vsignDown,*(int8x8_t *)&upBuff1[x]),vdup_n_s8(2));\n+            *(int8x8_t *)&upBuff1[x] = vneg_s8(vsignDown);\n+            int16x8_t t1 = vmovl_s8(vtbl1_s8(tbl,vedgeType));\n+            t1 = vaddw_u8(t1,in0);\n+            *(uint8x8_t *)&rec[x] = vqmovun_s16(t1);\n+      }\n+    }\n+    for (; x < width; x++)\n+    {\n+        signDown = signOf(rec[x] - rec[x + stride]);\n+        edgeType = signDown + upBuff1[x] + 2;\n+        upBuff1[x] = -signDown;\n+        rec[x] = x265_clip(rec[x] + offsetEo[edgeType]);\n+    }\n+}\n+\n+static void processSaoCUE1_2Rows_neon(pixel* rec, int8_t* upBuff1, int8_t* offsetEo, intptr_t stride, int width)\n+{\n+    int y;\n+    int8_t signDown;\n+    int edgeType;\n+\n+    for (y = 0; y < 2; y++)\n+    {\n+      int x=0;\n+      if (width >= 8) {\n+        int8x8_t tbl = *(int8x8_t *)offsetEo;\n+        for (; (x+8) <= width; x+=8)\n+        {\n+          uint8x8_t in0 = *(uint8x8_t *)&rec[x];\n+          uint8x8_t in1 = *(uint8x8_t *)&rec[x+stride];\n+          int8x8_t vsignDown = sign_diff_neon(in0,in1);\n+          int8x8_t vedgeType = vadd_s8(vadd_s8(vsignDown,*(int8x8_t *)&upBuff1[x]),vdup_n_s8(2));\n+          *(int8x8_t *)&upBuff1[x] = vneg_s8(vsignDown);\n+          int16x8_t t1 = vmovl_s8(vtbl1_s8(tbl,vedgeType));\n+          t1 = vaddw_u8(t1,in0);\n+          t1 = vmaxq_s16(t1,vdupq_n_s16(0));\n+          t1 = vminq_s16(t1,vdupq_n_s16(255));\n+          *(uint8x8_t *)&rec[x] = vmovn_u16(t1);\n+\n+        }\n+      }\n+      for (; x < width; x++)\n+      {\n+          signDown = signOf(rec[x] - rec[x + stride]);\n+          edgeType = signDown + upBuff1[x] + 2;\n+          upBuff1[x] = -signDown;\n+          rec[x] = x265_clip(rec[x] + offsetEo[edgeType]);\n+      }\n+      rec += stride;\n+  }\n+}\n+\n+static void processSaoCUE2_neon(pixel * rec, int8_t * bufft, int8_t * buff1, int8_t * offsetEo, int width, intptr_t stride)\n+{\n+    int x;\n+  \n+    if (abs(buff1-bufft) < 16)\n+    {\n+      for (x = 0; x < width; x++)\n+      {\n+          int8_t signDown = signOf(rec[x] - rec[x + stride + 1]);\n+          int edgeType = signDown + buff1[x] + 2;\n+          bufft[x + 1] = -signDown;\n+          rec[x] = x265_clip(rec[x] + offsetEo[edgeType]);;\n+      }\n+    }\n+    else\n+    {\n+      int8x8_t tbl = *(int8x8_t *)offsetEo;\n+      x=0;\n+      for (; (x + 8) <= width; x+=8)\n+      {\n+          uint8x8_t in0 = *(uint8x8_t *)&rec[x];\n+          uint8x8_t in1 = *(uint8x8_t *)&rec[x+stride+1];\n+          int8x8_t vsignDown = sign_diff_neon(in0,in1);\n+          int8x8_t vedgeType = vadd_s8(vadd_s8(vsignDown,*(int8x8_t *)&buff1[x]),vdup_n_s8(2));\n+          *(int8x8_t *)&bufft[x+1] = vneg_s8(vsignDown);\n+          int16x8_t t1 = vmovl_s8(vtbl1_s8(tbl,vedgeType));\n+          t1 = vaddw_u8(t1,in0);\n+          t1 = vmaxq_s16(t1,vdupq_n_s16(0));\n+          t1 = vminq_s16(t1,vdupq_n_s16(255));\n+          *(uint8x8_t *)&rec[x] = vmovn_u16(t1);\n+      }\n+      for (; x < width; x++)\n+      {\n+          int8_t signDown = signOf(rec[x] - rec[x + stride + 1]);\n+          int edgeType = signDown + buff1[x] + 2;\n+          bufft[x + 1] = -signDown;\n+          rec[x] = x265_clip(rec[x] + offsetEo[edgeType]);;\n+      }\n+\n+    }\n+}\n+ \n+\n+static void processSaoCUE3_neon(pixel *rec, int8_t *upBuff1, int8_t *offsetEo, intptr_t stride, int startX, int endX)\n+{\n+    int8_t signDown;\n+    int8_t edgeType;\n+  int8x8_t tbl = *(int8x8_t *)offsetEo;\n+\n+    int x = startX + 1;\n+  for (; (x+8) <= endX; x+=8 )\n+  {\n+    uint8x8_t in0 = *(uint8x8_t *)&rec[x];\n+    uint8x8_t in1 = *(uint8x8_t *)&rec[x+stride];\n+    int8x8_t vsignDown = sign_diff_neon(in0,in1);\n+    int8x8_t vedgeType = vadd_s8(vadd_s8(vsignDown,*(int8x8_t *)&upBuff1[x]),vdup_n_s8(2));\n+    *(int8x8_t *)&upBuff1[x-1] = vneg_s8(vsignDown);\n+    int16x8_t t1 = vmovl_s8(vtbl1_s8(tbl,vedgeType));\n+    t1 = vaddw_u8(t1,in0);\n+    t1 = vmaxq_s16(t1,vdupq_n_s16(0));\n+    t1 = vminq_s16(t1,vdupq_n_s16(255));\n+    *(uint8x8_t *)&rec[x] = vmovn_u16(t1);\n+\n+  }\n+    for (; x < endX; x++)\n+    {\n+        signDown = signOf(rec[x] - rec[x + stride]);\n+        edgeType = signDown + upBuff1[x] + 2;\n+        upBuff1[x - 1] = -signDown;\n+        rec[x] = x265_clip(rec[x] + offsetEo[edgeType]);\n+    }\n+}\n+\n+static void processSaoCUB0_neon(pixel* rec, const int8_t* offset, int ctuWidth, int ctuHeight, intptr_t stride)\n+{\n+    #define SAO_BO_BITS 5\n+    const int boShift = X265_DEPTH - SAO_BO_BITS;\n+    int x, y;\n+  int8x8x4_t table;\n+  table = *(int8x8x4_t *)offset;\n+  \n+    for (y = 0; y < ctuHeight; y++)\n+    {\n+      \n+        for (x = 0; (x+8) <= ctuWidth; x+=8)\n+        {\n+          int8x8_t in = *(int8x8_t*)&rec[x];\n+          int8x8_t offsets = vtbl4_s8(table,vshr_n_u8(in,boShift));\n+          int16x8_t tmp = vmovl_s8(offsets);\n+          tmp = vaddw_u8(tmp,in);\n+          tmp = vmaxq_s16(tmp,vdupq_n_s16(0));\n+          tmp = vminq_s16(tmp,vdupq_n_s16(255));\n+          *(uint8x8_t *)&rec[x] = vmovn_u16(tmp);\n+        }\n+        for (; x < ctuWidth; x++)\n+        {\n+            rec[x] = x265_clip(rec[x] + offset[rec[x] >> boShift]);\n+        }\n+        rec += stride;\n+    }\n+}\n+\n+}\n+\n+\n+\n+namespace X265_NS {\n+void setupLoopFilterPrimitives_neon(EncoderPrimitives &p)\n+{\n+    p.saoCuOrgE0 = processSaoCUE0_neon;\n+    p.saoCuOrgE1 = processSaoCUE1_neon;\n+    p.saoCuOrgE1_2Rows = processSaoCUE1_2Rows_neon;\n+    p.saoCuOrgE2[0] = processSaoCUE2_neon;\n+    p.saoCuOrgE2[1] = processSaoCUE2_neon;\n+    p.saoCuOrgE3[0] = processSaoCUE3_neon;\n+    p.saoCuOrgE3[1] = processSaoCUE3_neon;\n+    p.saoCuOrgB0 = processSaoCUB0_neon;\n+    p.sign = calSign_neon;\n+\n+}\n+\n+#else //HIGH_BIT_DEPTH\n+\n+\n+namespace X265_NS {\n+void setupLoopFilterPrimitives_neon(EncoderPrimitives &)\n+{\n+}\n+\n+#endif\n+\n+\n+}\ndiff -Naur ./source/common/arm64/loopfilter-prim.h ../x265_apple_patch/source/common/arm64/loopfilter-prim.h\n--- ./source/common/arm64/loopfilter-prim.h\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/loopfilter-prim.h\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,43 @@\n+#ifndef _LOOPFILTER_NEON_H__\n+#define _LOOPFILTER_NEON_H__\n+\n+\n+/*****************************************************************************\n+* Copyright (C) 2013-2017 MulticoreWare, Inc\n+*\n+* Authors: Praveen Kumar Tiwari <praveen@multicorewareinc.com>\n+*          Dnyaneshwar Gorade <dnyaneshwar@multicorewareinc.com>\n+*          Min Chen <chenm003@163.com>\n+*\n+* This program is free software; you can redistribute it and/or modify\n+* it under the terms of the GNU General Public License as published by\n+* the Free Software Foundation; either version 2 of the License, or\n+* (at your option) any later version.\n+*\n+* This program is distributed in the hope that it will be useful,\n+* but WITHOUT ANY WARRANTY; without even the implied warranty of\n+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+* GNU General Public License for more details.\n+*\n+* You should have received a copy of the GNU General Public License\n+* along with this program; if not, write to the Free Software\n+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.\n+*\n+* This program is also available under a commercial proprietary license.\n+* For more information, contact us at license @ x265.com.\n+*****************************************************************************/\n+\n+\n+\n+#include \"common.h\"\n+#include \"primitives.h\"\n+\n+#define PIXEL_MIN 0\n+\n+namespace X265_NS {\n+void setupLoopFilterPrimitives_neon(EncoderPrimitives &p);\n+\n+};\n+\n+\n+#endif\ndiff -Naur ./source/common/arm64/pixel-prim.cpp ../x265_apple_patch/source/common/arm64/pixel-prim.cpp\n--- ./source/common/arm64/pixel-prim.cpp\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/pixel-prim.cpp\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,1940 @@\n+#include \"common.h\"\n+#include \"slicetype.h\"      // LOWRES_COST_MASK\n+#include \"primitives.h\"\n+#include \"x265.h\"\n+\n+#include \"pixel-prim.h\"\n+#include \"arm64-utils.h\"\n+#if HAVE_NEON\n+\n+#include <arm_neon.h>\n+\n+using namespace X265_NS;\n+\n+\n+\n+namespace  {\n+\n+\n+/* SATD SA8D variants - based on x264 */\n+static inline void SUMSUB_AB(int16x8_t& sum, int16x8_t& sub, const int16x8_t a, const int16x8_t b)\n+{\n+    sum = vaddq_s16(a,b);\n+    sub = vsubq_s16(a,b);\n+}\n+\n+static inline void transpose_8h(int16x8_t& t1, int16x8_t& t2, const int16x8_t s1, const int16x8_t s2)\n+{\n+    t1 = vtrn1q_s16(s1, s2);\n+    t2 = vtrn2q_s16(s1, s2);\n+}\n+\n+static inline void transpose_4s(int16x8_t& t1, int16x8_t& t2, const int16x8_t s1, const int16x8_t s2)\n+{\n+    t1 = vtrn1q_s32(s1, s2);\n+    t2 = vtrn2q_s32(s1, s2);\n+}\n+\n+#if (X265_DEPTH <= 10)\n+static inline void transpose_2d(int16x8_t& t1, int16x8_t& t2, const int16x8_t s1, const int16x8_t s2)\n+{\n+    t1 = vtrn1q_s64(s1, s2);\n+    t2 = vtrn2q_s64(s1, s2);\n+}\n+#endif\n+\n+\n+static inline void SUMSUB_ABCD(int16x8_t& s1, int16x8_t& d1, int16x8_t& s2, int16x8_t& d2,\n+                        int16x8_t a,int16x8_t  b,int16x8_t  c,int16x8_t  d)\n+{\n+    SUMSUB_AB(s1,d1,a,b);\n+    SUMSUB_AB(s2,d2,c,d);\n+}\n+\n+static inline void HADAMARD4_V(int16x8_t& r1,int16x8_t& r2,int16x8_t& r3,int16x8_t& r4,\n+                        int16x8_t& t1,int16x8_t& t2,int16x8_t& t3,int16x8_t& t4)\n+{\n+    SUMSUB_ABCD(t1, t2, t3, t4, r1, r2, r3, r4);\n+    SUMSUB_ABCD(r1, r3, r2, r4, t1, t3, t2, t4);\n+}\n+\n+\n+static int _satd_4x8_8x4_end_neon(int16x8_t v0,int16x8_t v1,int16x8_t v2, int16x8_t v3)\n+                                 \n+{\n+    \n+    int16x8_t v4,v5,v6,v7,v16,v17,v18,v19;\n+\n+    \n+    SUMSUB_AB   (v16, v17, v0,  v1);\n+    SUMSUB_AB   (v18, v19, v2,  v3);\n+\n+    SUMSUB_AB   (v4 , v6 , v16, v18);\n+    SUMSUB_AB   (v5 , v7 , v17, v19);\n+\n+    v0 = vtrn1q_s16(v4, v5);\n+    v1 = vtrn2q_s16(v4, v5);\n+    v2 = vtrn1q_s16(v6, v7);\n+    v3 = vtrn2q_s16(v6, v7);\n+\n+    SUMSUB_AB   (v16, v17, v0,  v1);\n+    SUMSUB_AB   (v18, v19, v2,  v3);\n+\n+    v0 = vtrn1q_s32(v16, v18);\n+    v1 = vtrn2q_s32(v16, v18);\n+    v2 = vtrn1q_s32(v17, v19);\n+    v3 = vtrn2q_s32(v17, v19);\n+\n+    v0 = vabsq_s16(v0);\n+    v1 = vabsq_s16(v1);\n+    v2 = vabsq_s16(v2);\n+    v3 = vabsq_s16(v3);\n+    \n+    v0 = vmaxq_u16(v0, v1);\n+    v1 = vmaxq_u16(v2, v3);\n+\n+    v0 = vaddq_u16(v0, v1);\n+    return vaddlvq_u16(v0);\n+}\n+\n+static inline int _satd_4x4_neon(int16x8_t v0, int16x8_t v1)\n+{\n+    int16x8_t v2,v3;\n+    SUMSUB_AB   (v2,  v3,  v0,  v1);\n+\n+    v0 = vzip1q_s64(v2,v3);\n+    v1 = vzip2q_s64(v2,v3);\n+    SUMSUB_AB   (v2,  v3,  v0,  v1);\n+\n+    v0 = vtrn1q_s16(v2,v3);\n+    v1 = vtrn2q_s16(v2,v3);\n+    SUMSUB_AB   (v2,  v3,  v0,  v1);\n+\n+    v0 = vtrn1q_s32(v2,v3);\n+    v1 = vtrn2q_s32(v2,v3);\n+\n+    v0 = vabsq_s16(v0);\n+    v1 = vabsq_s16(v1);\n+    v0 = vmaxq_u16(v0, v1);\n+    \n+    return vaddlvq_s16(v0);\n+}\n+\n+static void _satd_8x4v_8x8h_neon(int16x8_t& v0,int16x8_t& v1, int16x8_t&v2,int16x8_t& v3,int16x8_t& v20,int16x8_t& v21, int16x8_t&v22,int16x8_t& v23)\n+{\n+    int16x8_t v16,v17,v18,v19,v4,v5,v6,v7;\n+    \n+    SUMSUB_AB(v16, v18, v0,  v2);\n+    SUMSUB_AB(v17, v19, v1,  v3);\n+\n+    HADAMARD4_V (v20, v21, v22, v23, v0,  v1, v2, v3);\n+\n+    transpose_8h(   v0,  v1,  v16, v17);\n+    transpose_8h(   v2,  v3,  v18, v19);\n+    transpose_8h(   v4,  v5,  v20, v21);\n+    transpose_8h(   v6,  v7,  v22, v23);\n+\n+    SUMSUB_AB   (v16, v17, v0,  v1);\n+    SUMSUB_AB   (v18, v19, v2,  v3);\n+    SUMSUB_AB   (v20, v21, v4,  v5);\n+    SUMSUB_AB   (v22, v23, v6,  v7);\n+\n+    transpose_4s(   v0,  v2,  v16, v18);\n+    transpose_4s(   v1,  v3,  v17, v19);\n+    transpose_4s(   v4,  v6,  v20, v22);\n+    transpose_4s(   v5,  v7,  v21, v23);\n+\n+    v0 = vabsq_s16(v0);\n+    v1 = vabsq_s16(v1);\n+    v2 = vabsq_s16(v2);\n+    v3 = vabsq_s16(v3);\n+    v4 = vabsq_s16(v4);\n+    v5 = vabsq_s16(v5);\n+    v6 = vabsq_s16(v6);\n+    v7 = vabsq_s16(v7);\n+\n+    v0 = vmaxq_u16(v0,v2);\n+    v1 = vmaxq_u16(v1,v3);\n+    v2 = vmaxq_u16(v4,v6);\n+    v3 = vmaxq_u16(v5,v7);\n+\n+}\n+\n+#if HIGH_BIT_DEPTH\n+\n+#if (X265_DEPTH > 10)\n+static inline void transpose_2d(int32x4_t& t1, int32x4_t& t2, const int32x4_t s1, const int32x4_t s2)\n+{\n+    t1 = vtrn1q_s64(s1, s2);\n+    t2 = vtrn2q_s64(s1, s2);\n+}\n+\n+static inline void ISUMSUB_AB(int32x4_t& sum, int32x4_t& sub, const int32x4_t a, const int32x4_t b)\n+{\n+    sum = vaddq_s32(a,b);\n+    sub = vsubq_s32(a,b);\n+}\n+\n+static inline void ISUMSUB_AB_FROM_INT16(int32x4_t& suml, int32x4_t& sumh, int32x4_t& subl, int32x4_t& subh, const int16x8_t a, const int16x8_t b)\n+{\n+    suml = vaddl_s16(vget_low_s16(a),vget_low_s16(b));\n+    sumh = vaddl_high_s16(a,b);\n+    subl = vsubl_s16(vget_low_s16(a),vget_low_s16(b));\n+    subh = vsubl_high_s16(a, b);\n+}\n+\n+#endif\n+\n+static inline void _sub_8x8_fly(const uint16_t* pix1, intptr_t stride_pix1, const uint16_t* pix2, intptr_t stride_pix2,\n+                            int16x8_t& v0,int16x8_t& v1, int16x8_t& v2,int16x8_t& v3,\n+                            int16x8_t& v20,int16x8_t& v21, int16x8_t& v22,int16x8_t& v23)\n+{\n+    uint16x8_t r0,r1,r2,r3;\n+    uint16x8_t t0,t1,t2,t3;\n+    int16x8_t v16,v17;\n+    int16x8_t v18,v19;\n+    \n+    r0 = *(uint16x8_t*)(pix1 + 0*stride_pix1);\n+    r1 = *(uint16x8_t*)(pix1 + 1*stride_pix1);\n+    r2 = *(uint16x8_t*)(pix1 + 2*stride_pix1);\n+    r3 = *(uint16x8_t*)(pix1 + 3*stride_pix1);\n+\n+    t0 = *(uint16x8_t*)(pix2 + 0*stride_pix2);\n+    t1 = *(uint16x8_t*)(pix2 + 1*stride_pix2);\n+    t2 = *(uint16x8_t*)(pix2 + 2*stride_pix2);\n+    t3 = *(uint16x8_t*)(pix2 + 3*stride_pix2);\n+\n+    v16 = vsubq_u16(r0,t0);\n+    v17 = vsubq_u16(r1,t1);\n+    v18 = vsubq_u16(r2,t2);\n+    v19 = vsubq_u16(r3,t3);\n+\n+    r0 = *(uint16x8_t*)(pix1 + 4*stride_pix1);\n+    r1 = *(uint16x8_t*)(pix1 + 5*stride_pix1);\n+    r2 = *(uint16x8_t*)(pix1 + 6*stride_pix1);\n+    r3 = *(uint16x8_t*)(pix1 + 7*stride_pix1);\n+\n+    t0 = *(uint16x8_t*)(pix2 + 4*stride_pix2);\n+    t1 = *(uint16x8_t*)(pix2 + 5*stride_pix2);\n+    t2 = *(uint16x8_t*)(pix2 + 6*stride_pix2);\n+    t3 = *(uint16x8_t*)(pix2 + 7*stride_pix2);\n+    \n+    v20 = vsubq_u16(r0,t0);\n+    v21 = vsubq_u16(r1,t1);\n+    v22 = vsubq_u16(r2,t2);\n+    v23 = vsubq_u16(r3,t3);\n+\n+    SUMSUB_AB   (v0,  v1,  v16, v17);\n+    SUMSUB_AB   (v2,  v3,  v18, v19);\n+ \n+}\n+\n+\n+\n+\n+static void _satd_16x4_neon(const uint16_t* pix1, intptr_t stride_pix1, const uint16_t* pix2, intptr_t stride_pix2,\n+                            int16x8_t& v0,int16x8_t&v1, int16x8_t&v2,int16x8_t&v3)\n+{\n+    uint8x16_t r0,r1,r2,r3;\n+    uint8x16_t t0,t1,t2,t3;\n+    int16x8_t v16,v17,v20,v21;\n+    int16x8_t v18,v19,v22,v23;\n+    \n+    r0 = *(int16x8_t*)(pix1 + 0*stride_pix1);\n+    r1 = *(int16x8_t*)(pix1 + 1*stride_pix1);\n+    r2 = *(int16x8_t*)(pix1 + 2*stride_pix1);\n+    r3 = *(int16x8_t*)(pix1 + 3*stride_pix1);\n+\n+    t0 = *(int16x8_t*)(pix2 + 0*stride_pix2);\n+    t1 = *(int16x8_t*)(pix2 + 1*stride_pix2);\n+    t2 = *(int16x8_t*)(pix2 + 2*stride_pix2);\n+    t3 = *(int16x8_t*)(pix2 + 3*stride_pix2);\n+  \n+    \n+    v16 = vsubq_u16((r0),(t0) );\n+    v17 = vsubq_u16((r1),(t1) );\n+    v18 = vsubq_u16((r2),(t2) );\n+    v19 = vsubq_u16((r3),(t3) );\n+\n+    r0 = *(int16x8_t*)(pix1 + 0*stride_pix1 + 8);\n+    r1 = *(int16x8_t*)(pix1 + 1*stride_pix1 + 8);\n+    r2 = *(int16x8_t*)(pix1 + 2*stride_pix1 + 8);\n+    r3 = *(int16x8_t*)(pix1 + 3*stride_pix1 + 8);\n+\n+    t0 = *(int16x8_t*)(pix2 + 0*stride_pix2 + 8);\n+    t1 = *(int16x8_t*)(pix2 + 1*stride_pix2 + 8);\n+    t2 = *(int16x8_t*)(pix2 + 2*stride_pix2 + 8);\n+    t3 = *(int16x8_t*)(pix2 + 3*stride_pix2 + 8);\n+\n+    \n+    v20 = vsubq_u16(r0,t0);\n+    v21 = vsubq_u16(r1,t1);\n+    v22 = vsubq_u16(r2,t2);\n+    v23 = vsubq_u16(r3,t3);\n+\n+    SUMSUB_AB   (v0,  v1,  v16, v17);\n+    SUMSUB_AB   (v2,  v3,  v18, v19);\n+    \n+    _satd_8x4v_8x8h_neon(v0,v1,v2,v3,v20,v21,v22,v23);\n+    \n+}\n+\n+\n+int pixel_satd_4x4_neon(const uint16_t* pix1, intptr_t stride_pix1, const uint16_t* pix2, intptr_t stride_pix2)\n+{\n+    uint64x2_t t0,t1,r0,r1;\n+    t0[0] = *(uint64_t *)(pix1 + 0*stride_pix1);\n+    t1[0] = *(uint64_t *)(pix1 + 1*stride_pix1);\n+    t0[1] = *(uint64_t *)(pix1 + 2*stride_pix1);\n+    t1[1] = *(uint64_t *)(pix1 + 3*stride_pix1);\n+\n+    r0[0] = *(uint64_t *)(pix2 + 0*stride_pix1);\n+    r1[0] = *(uint64_t *)(pix2 + 1*stride_pix2);\n+    r0[1] = *(uint64_t *)(pix2 + 2*stride_pix2);\n+    r1[1] = *(uint64_t *)(pix2 + 3*stride_pix2);\n+    \n+    return _satd_4x4_neon(vsubq_u16(t0,r0), vsubq_u16(r1,t1));\n+}\n+\n+\n+\n+\n+\n+\n+int pixel_satd_8x4_neon(const uint16_t* pix1, intptr_t stride_pix1, const uint16_t* pix2, intptr_t stride_pix2)\n+{\n+    uint16x8_t i0,i1,i2,i3,i4,i5,i6,i7;\n+    \n+    i0 = *(uint16x8_t *)(pix1 + 0*stride_pix1);\n+    i1 = *(uint16x8_t *)(pix2 + 0*stride_pix2);\n+    i2 = *(uint16x8_t *)(pix1 + 1*stride_pix1);\n+    i3 = *(uint16x8_t *)(pix2 + 1*stride_pix2);\n+    i4 = *(uint16x8_t *)(pix1 + 2*stride_pix1);\n+    i5 = *(uint16x8_t *)(pix2 + 2*stride_pix2);\n+    i6 = *(uint16x8_t *)(pix1 + 3*stride_pix1);\n+    i7 = *(uint16x8_t *)(pix2 + 3*stride_pix2);\n+\n+    int16x8_t v0 = vsubq_u16(i0,i1);\n+    int16x8_t v1 = vsubq_u16(i2,i3);\n+    int16x8_t v2 = vsubq_u16(i4,i5);\n+    int16x8_t v3 = vsubq_u16(i6,i7);\n+\n+    return _satd_4x8_8x4_end_neon(v0,v1,v2,v3);\n+}\n+\n+\n+int pixel_satd_16x16_neon(const uint16_t* pix1, intptr_t stride_pix1, const uint16_t* pix2, intptr_t stride_pix2)\n+{\n+    int32x4_t v30 = vdupq_n_u32(0),v31= vdupq_n_u32(0);\n+    int16x8_t v0,v1,v2,v3;\n+    \n+    _satd_16x4_neon(pix1,stride_pix1,pix2,stride_pix2,v0,v1,v2,v3);\n+    v30 = vpadalq_u16(v30,v0);\n+    v30 = vpadalq_u16(v30,v1);\n+    v31 = vpadalq_u16(v31,v2);\n+    v31 = vpadalq_u16(v31,v3);\n+\n+    _satd_16x4_neon(pix1 + 4*stride_pix1,stride_pix1,pix2+4*stride_pix2,stride_pix2,v0,v1,v2,v3);\n+    v30 = vpadalq_u16(v30,v0);\n+    v30 = vpadalq_u16(v30,v1);\n+    v31 = vpadalq_u16(v31,v2);\n+    v31 = vpadalq_u16(v31,v3);\n+\n+    _satd_16x4_neon(pix1 + 8*stride_pix1,stride_pix1,pix2+8*stride_pix2,stride_pix2,v0,v1,v2,v3);\n+    v30 = vpadalq_u16(v30,v0);\n+    v30 = vpadalq_u16(v30,v1);\n+    v31 = vpadalq_u16(v31,v2);\n+    v31 = vpadalq_u16(v31,v3);\n+\n+    _satd_16x4_neon(pix1 + 12*stride_pix1,stride_pix1,pix2+12*stride_pix2,stride_pix2,v0,v1,v2,v3);\n+    v30 = vpadalq_u16(v30,v0);\n+    v30 = vpadalq_u16(v30,v1);\n+    v31 = vpadalq_u16(v31,v2);\n+    v31 = vpadalq_u16(v31,v3);\n+\n+    return vaddvq_s32(vaddq_s32(v30,v31));\n+    \n+}\n+\n+#else       //HIGH_BIT_DEPTH\n+\n+static void _satd_16x4_neon(const uint8_t* pix1, intptr_t stride_pix1, const uint8_t* pix2, intptr_t stride_pix2,\n+                            int16x8_t& v0,int16x8_t&v1, int16x8_t&v2,int16x8_t&v3)\n+{\n+    uint8x16_t r0,r1,r2,r3;\n+    uint8x16_t t0,t1,t2,t3;\n+    int16x8_t v16,v17,v20,v21;\n+    int16x8_t v18,v19,v22,v23;\n+    \n+    r0 = *(uint8x16_t*)(pix1 + 0*stride_pix1);\n+    r1 = *(uint8x16_t*)(pix1 + 1*stride_pix1);\n+    r2 = *(uint8x16_t*)(pix1 + 2*stride_pix1);\n+    r3 = *(uint8x16_t*)(pix1 + 3*stride_pix1);\n+\n+    t0 = *(uint8x16_t*)(pix2 + 0*stride_pix2);\n+    t1 = *(uint8x16_t*)(pix2 + 1*stride_pix2);\n+    t2 = *(uint8x16_t*)(pix2 + 2*stride_pix2);\n+    t3 = *(uint8x16_t*)(pix2 + 3*stride_pix2);\n+\n+    \n+    \n+    v16 = vsubl_u8(vget_low_u8(r0),vget_low_u8(t0) );\n+    v20 = vsubl_high_u8(r0,t0);\n+    v17 = vsubl_u8(vget_low_u8(r1),vget_low_u8(t1) );\n+    v21 = vsubl_high_u8(r1,t1);\n+    v18 = vsubl_u8(vget_low_u8(r2),vget_low_u8(t2) );\n+    v22 = vsubl_high_u8(r2,t2);\n+    v19 = vsubl_u8(vget_low_u8(r3),vget_low_u8(t3) );\n+    v23 = vsubl_high_u8(r3,t3);\n+\n+    SUMSUB_AB   (v0,  v1,  v16, v17);\n+    SUMSUB_AB   (v2,  v3,  v18, v19);\n+    \n+    _satd_8x4v_8x8h_neon(v0,v1,v2,v3,v20,v21,v22,v23);\n+    \n+}\n+\n+\n+static inline void _sub_8x8_fly(const uint8_t* pix1, intptr_t stride_pix1, const uint8_t* pix2, intptr_t stride_pix2,\n+                            int16x8_t& v0,int16x8_t& v1, int16x8_t& v2,int16x8_t& v3,\n+                            int16x8_t& v20,int16x8_t& v21, int16x8_t& v22,int16x8_t& v23)\n+{\n+    uint8x8_t r0,r1,r2,r3;\n+    uint8x8_t t0,t1,t2,t3;\n+    int16x8_t v16,v17;\n+    int16x8_t v18,v19;\n+    \n+    r0 = *(uint8x8_t*)(pix1 + 0*stride_pix1);\n+    r1 = *(uint8x8_t*)(pix1 + 1*stride_pix1);\n+    r2 = *(uint8x8_t*)(pix1 + 2*stride_pix1);\n+    r3 = *(uint8x8_t*)(pix1 + 3*stride_pix1);\n+\n+    t0 = *(uint8x8_t*)(pix2 + 0*stride_pix2);\n+    t1 = *(uint8x8_t*)(pix2 + 1*stride_pix2);\n+    t2 = *(uint8x8_t*)(pix2 + 2*stride_pix2);\n+    t3 = *(uint8x8_t*)(pix2 + 3*stride_pix2);\n+\n+    v16 = vsubl_u8(r0,t0);\n+    v17 = vsubl_u8(r1,t1);\n+    v18 = vsubl_u8(r2,t2);\n+    v19 = vsubl_u8(r3,t3);\n+\n+    r0 = *(uint8x8_t*)(pix1 + 4*stride_pix1);\n+    r1 = *(uint8x8_t*)(pix1 + 5*stride_pix1);\n+    r2 = *(uint8x8_t*)(pix1 + 6*stride_pix1);\n+    r3 = *(uint8x8_t*)(pix1 + 7*stride_pix1);\n+\n+    t0 = *(uint8x8_t*)(pix2 + 4*stride_pix2);\n+    t1 = *(uint8x8_t*)(pix2 + 5*stride_pix2);\n+    t2 = *(uint8x8_t*)(pix2 + 6*stride_pix2);\n+    t3 = *(uint8x8_t*)(pix2 + 7*stride_pix2);\n+    \n+    v20 = vsubl_u8(r0,t0);\n+    v21 = vsubl_u8(r1,t1);\n+    v22 = vsubl_u8(r2,t2);\n+    v23 = vsubl_u8(r3,t3);\n+\n+\n+    SUMSUB_AB   (v0,  v1,  v16, v17);\n+    SUMSUB_AB   (v2,  v3,  v18, v19);\n+    \n+}\n+\n+int pixel_satd_4x4_neon(const uint8_t* pix1, intptr_t stride_pix1, const uint8_t* pix2, intptr_t stride_pix2)\n+{\n+    uint32x2_t t0,t1,r0,r1;\n+    t0[0] = *(uint32_t *)(pix1 + 0*stride_pix1);\n+    t1[0] = *(uint32_t *)(pix1 + 1*stride_pix1);\n+    t0[1] = *(uint32_t *)(pix1 + 2*stride_pix1);\n+    t1[1] = *(uint32_t *)(pix1 + 3*stride_pix1);\n+\n+    r0[0] = *(uint32_t *)(pix2 + 0*stride_pix1);\n+    r1[0] = *(uint32_t *)(pix2 + 1*stride_pix2);\n+    r0[1] = *(uint32_t *)(pix2 + 2*stride_pix2);\n+    r1[1] = *(uint32_t *)(pix2 + 3*stride_pix2);\n+    \n+    return _satd_4x4_neon(vsubl_u8(t0,r0), vsubl_u8(r1,t1));\n+}\n+\n+\n+int pixel_satd_8x4_neon(const uint8_t* pix1, intptr_t stride_pix1, const uint8_t* pix2, intptr_t stride_pix2)\n+{\n+    uint8x8_t i0,i1,i2,i3,i4,i5,i6,i7;\n+    \n+    i0 = *(uint8x8_t *)(pix1 + 0*stride_pix1);\n+    i1 = *(uint8x8_t *)(pix2 + 0*stride_pix2);\n+    i2 = *(uint8x8_t *)(pix1 + 1*stride_pix1);\n+    i3 = *(uint8x8_t *)(pix2 + 1*stride_pix2);\n+    i4 = *(uint8x8_t *)(pix1 + 2*stride_pix1);\n+    i5 = *(uint8x8_t *)(pix2 + 2*stride_pix2);\n+    i6 = *(uint8x8_t *)(pix1 + 3*stride_pix1);\n+    i7 = *(uint8x8_t *)(pix2 + 3*stride_pix2);\n+\n+    int16x8_t v0 = vsubl_u8(i0,i1);\n+    int16x8_t v1 = vsubl_u8(i2,i3);\n+    int16x8_t v2 = vsubl_u8(i4,i5);\n+    int16x8_t v3 = vsubl_u8(i6,i7);\n+\n+    return _satd_4x8_8x4_end_neon(v0,v1,v2,v3);\n+}\n+\n+int pixel_satd_16x16_neon(const uint8_t* pix1, intptr_t stride_pix1, const uint8_t* pix2, intptr_t stride_pix2)\n+{\n+    int16x8_t v30,v31;\n+    int16x8_t v0,v1,v2,v3;\n+    \n+    _satd_16x4_neon(pix1,stride_pix1,pix2,stride_pix2,v0,v1,v2,v3);\n+    v30 = vaddq_s16(v0,v1);\n+    v31 = vaddq_s16(v2,v3);\n+    \n+    _satd_16x4_neon(pix1 + 4*stride_pix1,stride_pix1,pix2+4*stride_pix2,stride_pix2,v0,v1,v2,v3);\n+    v0 = vaddq_s16(v0,v1);\n+    v1 = vaddq_s16(v2,v3);\n+    v30 = vaddq_s16(v30, v0);\n+    v31 = vaddq_s16(v31, v1);\n+\n+    _satd_16x4_neon(pix1 + 8*stride_pix1,stride_pix1,pix2+8*stride_pix2,stride_pix2,v0,v1,v2,v3);\n+    v0 = vaddq_s16(v0,v1);\n+    v1 = vaddq_s16(v2,v3);\n+    v30 = vaddq_s16(v30, v0);\n+    v31 = vaddq_s16(v31, v1);\n+\n+    _satd_16x4_neon(pix1 + 12*stride_pix1,stride_pix1,pix2+12*stride_pix2,stride_pix2,v0,v1,v2,v3);\n+    v0 = vaddq_s16(v0,v1);\n+    v1 = vaddq_s16(v2,v3);\n+    v30 = vaddq_s16(v30, v0);\n+    v31 = vaddq_s16(v31, v1);\n+\n+    int32x4_t sum0 = vpaddlq_u16(v30);\n+    int32x4_t sum1 = vpaddlq_u16(v31);\n+    sum0 = vaddq_s32(sum0,sum1);\n+    return vaddvq_s32(sum0);\n+    \n+}\n+#endif      //HIGH_BIT_DEPTH\n+\n+\n+static inline void _sa8d_8x8_neon_end(int16x8_t& v0,int16x8_t& v1,int16x8_t v2,int16x8_t v3,\n+                                     int16x8_t v20,int16x8_t v21,int16x8_t v22,int16x8_t v23)\n+{\n+    int16x8_t v16,v17,v18,v19;\n+    int16x8_t v4,v5,v6,v7;\n+    \n+    SUMSUB_AB   (v16, v18, v0,  v2);\n+    SUMSUB_AB   (v17, v19, v1,  v3);\n+\n+    HADAMARD4_V (v20, v21, v22, v23, v0,  v1, v2, v3);\n+\n+    SUMSUB_AB   (v0,  v16, v16, v20);\n+    SUMSUB_AB   (v1,  v17, v17, v21);\n+    SUMSUB_AB   (v2,  v18, v18, v22);\n+    SUMSUB_AB   (v3,  v19, v19, v23);\n+\n+    transpose_8h   (v20, v21, v16, v17);\n+    transpose_8h   (v4,  v5,  v0,  v1);\n+    transpose_8h   (v22, v23, v18, v19);\n+    transpose_8h   (v6,  v7,  v2,  v3);\n+    \n+#if (X265_DEPTH <= 10)\n+\n+    int16x8_t v24,v25;\n+\n+    SUMSUB_AB   (v2,  v3,  v20, v21);\n+    SUMSUB_AB   (v24, v25, v4,  v5);\n+    SUMSUB_AB   (v0,  v1,  v22, v23);\n+    SUMSUB_AB   (v4,  v5,  v6,  v7);\n+\n+    transpose_4s   (v20, v22, v2,  v0);\n+    transpose_4s   (v21, v23, v3,  v1);\n+    transpose_4s   (v16, v18, v24, v4);\n+    transpose_4s   (v17, v19, v25, v5);\n+\n+    SUMSUB_AB   (v0,  v2,  v20, v22);\n+    SUMSUB_AB   (v1,  v3,  v21, v23);\n+    SUMSUB_AB   (v4,  v6,  v16, v18);\n+    SUMSUB_AB   (v5,  v7,  v17, v19);\n+\n+    transpose_2d   (v16, v20,  v0,  v4);\n+    transpose_2d   (v17, v21,  v1,  v5);\n+    transpose_2d   (v18, v22,  v2,  v6);\n+    transpose_2d   (v19, v23,  v3,  v7);\n+\n+    \n+    v16 = vabsq_s16(v16);\n+    v17 = vabsq_s16(v17);\n+    v18 = vabsq_s16(v18);\n+    v19 = vabsq_s16(v19);\n+    v20 = vabsq_s16(v20);\n+    v21 = vabsq_s16(v21);\n+    v22 = vabsq_s16(v22);\n+    v23 = vabsq_s16(v23);\n+\n+    v16 = vmaxq_u16(v16,v20);\n+    v17 = vmaxq_u16(v17,v21);\n+    v18 = vmaxq_u16(v18,v22);\n+    v19 = vmaxq_u16(v19,v23);\n+\n+#if HIGH_BIT_DEPTH\n+    v0 = vpaddlq_u16(v16);\n+    v1 = vpaddlq_u16(v17);\n+    v0 = vpadalq_u16(v0,v18);\n+    v1 = vpadalq_u16(v1,v19);\n+    \n+#else //HIGH_BIT_DEPTH\n+    \n+    v0 = vaddq_u16(v16,v17);\n+    v1 = vaddq_u16(v18,v19);\n+\n+#endif //HIGH_BIT_DEPTH\n+    \n+#else // HIGH_BIT_DEPTH 12 bit only, switching math to int32, each int16x8 is up-convreted to 2 int32x4 (low and high)\n+\n+    int32x4_t v2l,v2h,v3l,v3h,v24l,v24h,v25l,v25h,v0l,v0h,v1l,v1h;\n+    int32x4_t v22l,v22h,v23l,v23h;\n+    int32x4_t v4l,v4h,v5l,v5h;\n+    int32x4_t v6l,v6h,v7l,v7h;\n+    int32x4_t v16l,v16h,v17l,v17h;\n+    int32x4_t v18l,v18h,v19l,v19h;\n+    int32x4_t v20l,v20h,v21l,v21h;\n+\n+    ISUMSUB_AB_FROM_INT16(v2l, v2h, v3l, v3h, v20, v21);\n+    ISUMSUB_AB_FROM_INT16(v24l, v24h, v25l, v25h, v4, v5);\n+\n+    v22l = vmovl_s16(vget_low_s16(v22));\n+    v22h = vmovl_high_s16(v22);\n+    v23l = vmovl_s16(vget_low_s16(v23));\n+    v23h = vmovl_high_s16(v23);\n+    \n+    ISUMSUB_AB(v0l,  v1l,  v22l, v23l);\n+    ISUMSUB_AB(v0h,  v1h,  v22h, v23h);\n+\n+    v6l = vmovl_s16(vget_low_s16(v6));\n+    v6h = vmovl_high_s16(v6);\n+    v7l = vmovl_s16(vget_low_s16(v7));\n+    v7h = vmovl_high_s16(v7);\n+\n+    ISUMSUB_AB   (v4l,  v5l,  v6l,  v7l);\n+    ISUMSUB_AB   (v4h,  v5h,  v6h,  v7h);\n+\n+    transpose_2d   (v20l, v22l, v2l,  v0l);\n+    transpose_2d   (v21l, v23l, v3l,  v1l);\n+    transpose_2d   (v16l, v18l, v24l, v4l);\n+    transpose_2d   (v17l, v19l, v25l, v5l);\n+\n+    transpose_2d   (v20h, v22h, v2h,  v0h);\n+    transpose_2d   (v21h, v23h, v3h,  v1h);\n+    transpose_2d   (v16h, v18h, v24h, v4h);\n+    transpose_2d   (v17h, v19h, v25h, v5h);\n+\n+    ISUMSUB_AB   (v0l,  v2l,  v20l, v22l);\n+    ISUMSUB_AB   (v1l,  v3l,  v21l, v23l);\n+    ISUMSUB_AB   (v4l,  v6l,  v16l, v18l);\n+    ISUMSUB_AB   (v5l,  v7l,  v17l, v19l);\n+\n+    ISUMSUB_AB   (v0h,  v2h,  v20h, v22h);\n+    ISUMSUB_AB   (v1h,  v3h,  v21h, v23h);\n+    ISUMSUB_AB   (v4h,  v6h,  v16h, v18h);\n+    ISUMSUB_AB   (v5h,  v7h,  v17h, v19h);\n+\n+    v16l = v0l;\n+    v16h = v4l;\n+    v20l = v0h;\n+    v20h = v4h;\n+    \n+    v17l = v1l;\n+    v17h = v5l;\n+    v21l = v1h;\n+    v21h = v5h;\n+    \n+    v18l = v2l;\n+    v18h = v6l;\n+    v22l = v2h;\n+    v22h = v6h;\n+    \n+    v19l = v3l;\n+    v19h = v7l;\n+    v23l = v3h;\n+    v23h = v7h;\n+\n+    v16l = vabsq_s32(v16l);\n+    v17l = vabsq_s32(v17l);\n+    v18l = vabsq_s32(v18l);\n+    v19l = vabsq_s32(v19l);\n+    v20l = vabsq_s32(v20l);\n+    v21l = vabsq_s32(v21l);\n+    v22l = vabsq_s32(v22l);\n+    v23l = vabsq_s32(v23l);\n+\n+    v16h = vabsq_s32(v16h);\n+    v17h = vabsq_s32(v17h);\n+    v18h = vabsq_s32(v18h);\n+    v19h = vabsq_s32(v19h);\n+    v20h = vabsq_s32(v20h);\n+    v21h = vabsq_s32(v21h);\n+    v22h = vabsq_s32(v22h);\n+    v23h = vabsq_s32(v23h);\n+\n+    v16l = vmaxq_u32(v16l,v20l);\n+    v17l = vmaxq_u32(v17l,v21l);\n+    v18l = vmaxq_u32(v18l,v22l);\n+    v19l = vmaxq_u32(v19l,v23l);\n+\n+    v16h = vmaxq_u32(v16h,v20h);\n+    v17h = vmaxq_u32(v17h,v21h);\n+    v18h = vmaxq_u32(v18h,v22h);\n+    v19h = vmaxq_u32(v19h,v23h);\n+\n+    v16l = vaddq_u32(v16l,v16h);\n+    v17l = vaddq_u32(v17l,v17h);\n+    v18l = vaddq_u32(v18l,v18h);\n+    v19l = vaddq_u32(v19l,v19h);\n+\n+    v0 = vaddq_u32(v16l, v17l);\n+    v1 = vaddq_u32(v18l,v19l);\n+    \n+    \n+#endif\n+    \n+}\n+\n+\n+\n+static inline void _satd_8x8_neon(const pixel* pix1, intptr_t stride_pix1, const pixel* pix2, intptr_t stride_pix2,\n+                            int16x8_t& v0,int16x8_t&v1, int16x8_t&v2,int16x8_t&v3)\n+{\n+    \n+    int16x8_t v20,v21,v22,v23;\n+    _sub_8x8_fly(pix1,stride_pix1,pix2,stride_pix2,v0,v1,v2,v3,v20,v21,v22,v23);\n+    _satd_8x4v_8x8h_neon(v0,v1,v2,v3,v20,v21,v22,v23);\n+    \n+}\n+\n+\n+\n+int pixel_satd_8x8_neon(const pixel* pix1, intptr_t stride_pix1, const pixel* pix2, intptr_t stride_pix2)\n+{\n+    int16x8_t v30,v31;\n+    int16x8_t v0,v1,v2,v3;\n+    \n+    _satd_8x8_neon(pix1,stride_pix1,pix2,stride_pix2,v0,v1,v2,v3);\n+#if !(HIGH_BIT_DEPTH)\n+    v30 = vaddq_u16(v0,v1);\n+    v31 = vaddq_u16(v2,v3);\n+    \n+    uint16x8_t sum = vaddq_u16(v30,v31);\n+    return vaddvq_s32(vpaddlq_u16(sum));\n+#else\n+    \n+    v30 = vaddq_u16(v0,v1);\n+    v31 = vaddq_u16(v2,v3);\n+\n+    int32x4_t sum = vpaddlq_u16(v30);\n+    sum = vpadalq_u16(sum, v31);\n+    return vaddvq_s32(sum);\n+#endif\n+}\n+\n+\n+int pixel_sa8d_8x8_neon(const pixel* pix1, intptr_t stride_pix1, const pixel* pix2, intptr_t stride_pix2)\n+{\n+    int16x8_t v0,v1,v2,v3;\n+    int16x8_t v20,v21,v22,v23;\n+    \n+    _sub_8x8_fly(pix1, stride_pix1, pix2, stride_pix2, v0, v1, v2, v3, v20, v21, v22, v23);\n+    _sa8d_8x8_neon_end(v0, v1, v2, v3, v20, v21, v22, v23);\n+\n+#if HIGH_BIT_DEPTH\n+//#if 1//HIGH_BIT_DEPTH\n+    int32x4_t s = vaddq_u32(v0,v1);\n+    return (vaddvq_u32(s) + 1) >> 1;\n+#else\n+    return (vaddlvq_s16(vaddq_u16(v0, v1)) + 1) >> 1;\n+#endif\n+}\n+\n+\n+\n+\n+\n+int pixel_sa8d_16x16_neon(const pixel* pix1, intptr_t stride_pix1, const pixel* pix2, intptr_t stride_pix2)\n+{\n+    int16x8_t v0,v1,v2,v3;\n+    int16x8_t v20,v21,v22,v23;\n+    int32x4_t v30,v31;\n+    \n+    _sub_8x8_fly(pix1, stride_pix1, pix2, stride_pix2, v0, v1, v2, v3, v20, v21, v22, v23);\n+    _sa8d_8x8_neon_end(v0, v1, v2, v3, v20, v21, v22, v23);\n+\n+#if !(HIGH_BIT_DEPTH)\n+    v30 = vpaddlq_u16(v0);\n+    v31 = vpaddlq_u16(v1);\n+#else\n+    v30 = vaddq_s32(v0,v1);\n+#endif\n+    \n+    _sub_8x8_fly(pix1 + 8, stride_pix1, pix2 + 8, stride_pix2, v0, v1, v2, v3, v20, v21, v22, v23);\n+    _sa8d_8x8_neon_end(v0, v1, v2, v3, v20, v21, v22, v23);\n+\n+#if !(HIGH_BIT_DEPTH)\n+     v30 = vpadalq_u16(v30,v0);\n+     v31 = vpadalq_u16(v31,v1);\n+#else\n+     v31 = vaddq_s32(v0,v1);\n+#endif\n+\n+\n+    _sub_8x8_fly(pix1 + 8*stride_pix1, stride_pix1, pix2 + 8*stride_pix2, stride_pix2, v0, v1, v2, v3, v20, v21, v22, v23);\n+    _sa8d_8x8_neon_end(v0, v1, v2, v3, v20, v21, v22, v23);\n+\n+#if !(HIGH_BIT_DEPTH)\n+    v30 = vpadalq_u16(v30,v0);\n+    v31 = vpadalq_u16(v31,v1);\n+#else\n+    v30 = vaddq_s32(v30,v0);\n+    v31 = vaddq_s32(v31,v1);\n+#endif\n+\n+    _sub_8x8_fly(pix1 + 8*stride_pix1 + 8, stride_pix1, pix2 + 8*stride_pix2 + 8, stride_pix2, v0, v1, v2, v3, v20, v21, v22, v23);\n+    _sa8d_8x8_neon_end(v0, v1, v2, v3, v20, v21, v22, v23);\n+\n+#if !(HIGH_BIT_DEPTH)\n+     v30 = vpadalq_u16(v30,v0);\n+     v31 = vpadalq_u16(v31,v1);\n+#else\n+     v30 = vaddq_s32(v30,v0);\n+     v31 = vaddq_s32(v31,v1);\n+#endif\n+\n+    v30 = vaddq_u32(v30,v31);\n+    \n+    return (vaddvq_u32(v30) + 1) >> 1;\n+}\n+\n+\n+\n+\n+\n+\n+\n+\n+template<int size>\n+void blockfill_s_neon(int16_t* dst, intptr_t dstride, int16_t val)\n+{\n+  for (int y = 0; y < size; y++) {\n+    int x = 0;\n+    int16x8_t v = vdupq_n_s16(val);\n+    for (; (x + 8) <= size; x+=8) {\n+        *(int16x8_t*)&dst[y * dstride + x] = v;\n+    }\n+    for (; x < size; x++) {\n+        dst[y * dstride + x] = val;\n+    }\n+  }\n+}\n+\n+template<int lx, int ly>\n+int sad_pp_neon(const pixel* pix1, intptr_t stride_pix1, const pixel* pix2, intptr_t stride_pix2)\n+{\n+  int sum = 0;\n+\n+\n+  for (int y = 0; y < ly; y++)\n+  {\n+#if HIGH_BIT_DEPTH\n+      int x=0;\n+      uint16x8_t vsum16_1 = vdupq_n_u16(0);\n+      for (; (x + 8) <= lx; x+=8) {\n+        uint16x8_t p1 = *(uint16x8_t*)&pix1[x];\n+        uint16x8_t p2 = *(uint16x8_t*)&pix2[x];\n+        vsum16_1 = vabaq_s16(vsum16_1,p1,p2);\n+              \n+      }\n+      if (lx & 4) {\n+        uint16x4_t p1 = *(uint16x4_t*)&pix1[x];\n+        uint16x4_t p2 = *(uint16x4_t*)&pix2[x];\n+        sum += vaddlv_s16(vaba_s16(vdup_n_s16(0),p1,p2));\n+        x += 4;\n+      }\n+      if (lx >= 4) {\n+        sum += vaddlvq_s16(vsum16_1);\n+      }\n+\n+#else\n+\n+    int x=0;\n+    uint16x8_t vsum16_1 = vdupq_n_u16(0);\n+    uint16x8_t vsum16_2 = vdupq_n_u16(0);\n+\n+    for (; (x + 16) <= lx; x+=16) {\n+      uint8x16_t p1 = *(uint8x16_t*)&pix1[x];\n+      uint8x16_t p2 = *(uint8x16_t*)&pix2[x];\n+      vsum16_1 = vabal_u8(vsum16_1,vget_low_u8(p1),vget_low_u8(p2));\n+      vsum16_2 = vabal_high_u8(vsum16_2,p1,p2);\n+    }\n+    if (lx & 8) {\n+      uint8x8_t p1 = *(uint8x8_t*)&pix1[x];\n+      uint8x8_t p2 = *(uint8x8_t*)&pix2[x];\n+      vsum16_1 = vabal_u8(vsum16_1,p1,p2);\n+      x += 8;\n+    }\n+    if (lx & 4) {\n+      uint32x2_t p1 = vdup_n_u32(0);\n+      p1[0] = *(uint32_t*)&pix1[x];\n+      uint32x2_t p2 = vdup_n_u32(0);\n+      p2[0] = *(uint32_t*)&pix2[x];\n+      vsum16_1 = vabal_u8(vsum16_1,p1,p2);\n+      x += 4;\n+    }\n+    if (lx >= 16) {\n+      vsum16_1 = vaddq_u16(vsum16_1,vsum16_2);\n+    }\n+    if (lx >= 4) {\n+      sum += vaddvq_u16(vsum16_1);\n+    }\n+\n+#endif\n+    if (lx & 3) for (; x < lx; x++) {\n+        sum += abs(pix1[x] - pix2[x]);\n+    }\n+    \n+    pix1 += stride_pix1;\n+    pix2 += stride_pix2;\n+  }\n+\n+  return sum;\n+}\n+\n+template<int lx, int ly>\n+void sad_x3_neon(const pixel* pix1, const pixel* pix2, const pixel* pix3, const pixel* pix4, intptr_t frefstride, int32_t* res)\n+{\n+  res[0] = 0;\n+  res[1] = 0;\n+  res[2] = 0;\n+  for (int y = 0; y < ly; y++)\n+  {\n+    int x = 0;\n+    uint16x8_t vsum16_0 = vdupq_n_u16(0);\n+    uint16x8_t vsum16_1 = vdupq_n_u16(0);\n+    uint16x8_t vsum16_2 = vdupq_n_u16(0);\n+#if HIGH_BIT_DEPTH\n+      for (; (x + 8) <= lx; x+=8) {\n+        uint16x8_t p1 = *(uint16x8_t*)&pix1[x];\n+        uint16x8_t p2 = *(uint16x8_t*)&pix2[x];\n+        uint16x8_t p3 = *(uint16x8_t*)&pix3[x];\n+        uint16x8_t p4 = *(uint16x8_t*)&pix4[x];\n+        vsum16_0 = vabaq_s16(vsum16_0,p1,p2);\n+        vsum16_1 = vabaq_s16(vsum16_1,p1,p3);\n+        vsum16_2 = vabaq_s16(vsum16_2,p1,p4);\n+\n+      }\n+      if (lx & 4) {\n+        uint16x4_t p1 = *(uint16x4_t*)&pix1[x];\n+        uint16x4_t p2 = *(uint16x4_t*)&pix2[x];\n+        uint16x4_t p3 = *(uint16x4_t*)&pix3[x];\n+        uint16x4_t p4 = *(uint16x4_t*)&pix4[x];\n+        res[0] += vaddlv_s16(vaba_s16(vdup_n_s16(0),p1,p2));\n+        res[1] += vaddlv_s16(vaba_s16(vdup_n_s16(0),p1,p3));\n+        res[2] += vaddlv_s16(vaba_s16(vdup_n_s16(0),p1,p4));\n+        x += 4;\n+      }\n+      if (lx >= 4) {\n+        res[0] += vaddlvq_s16(vsum16_0);\n+        res[1] += vaddlvq_s16(vsum16_1);\n+        res[2] += vaddlvq_s16(vsum16_2);\n+      }\n+#else\n+    \n+    for (; (x + 16) <= lx; x+=16) {\n+      uint8x16_t p1 = *(uint8x16_t*)&pix1[x];\n+      uint8x16_t p2 = *(uint8x16_t*)&pix2[x];\n+      uint8x16_t p3 = *(uint8x16_t*)&pix3[x];\n+      uint8x16_t p4 = *(uint8x16_t*)&pix4[x];\n+      vsum16_0 = vabal_u8(vsum16_0,vget_low_u8(p1),vget_low_u8(p2));\n+      vsum16_0 = vabal_high_u8(vsum16_0,p1,p2);\n+      vsum16_1 = vabal_u8(vsum16_1,vget_low_u8(p1),vget_low_u8(p3));\n+      vsum16_1 = vabal_high_u8(vsum16_1,p1,p3);\n+      vsum16_2 = vabal_u8(vsum16_2,vget_low_u8(p1),vget_low_u8(p4));\n+      vsum16_2 = vabal_high_u8(vsum16_2,p1,p4);\n+    }\n+    if (lx & 8) {\n+      uint8x8_t p1 = *(uint8x8_t*)&pix1[x];\n+      uint8x8_t p2 = *(uint8x8_t*)&pix2[x];\n+      uint8x8_t p3 = *(uint8x8_t*)&pix3[x];\n+      uint8x8_t p4 = *(uint8x8_t*)&pix4[x];\n+      vsum16_0 = vabal_u8(vsum16_0,p1,p2);\n+      vsum16_1 = vabal_u8(vsum16_1,p1,p3);\n+      vsum16_2 = vabal_u8(vsum16_2,p1,p4);\n+      x += 8;\n+    }\n+    if (lx & 4) {\n+      uint32x2_t p1 = vdup_n_u32(0);\n+      p1[0] = *(uint32_t*)&pix1[x];\n+      uint32x2_t p2 = vdup_n_u32(0);\n+      p2[0] = *(uint32_t*)&pix2[x];\n+      uint32x2_t p3 = vdup_n_u32(0);\n+      p3[0] = *(uint32_t*)&pix3[x];\n+      uint32x2_t p4 = vdup_n_u32(0);\n+      p4[0] = *(uint32_t*)&pix4[x];\n+      vsum16_0 = vabal_u8(vsum16_0,p1,p2);\n+      vsum16_1 = vabal_u8(vsum16_1,p1,p3);\n+      vsum16_2 = vabal_u8(vsum16_2,p1,p4);\n+      x += 4;\n+    }\n+    if (lx >= 4) {\n+      res[0] += vaddvq_u16(vsum16_0);\n+      res[1] += vaddvq_u16(vsum16_1);\n+      res[2] += vaddvq_u16(vsum16_2);\n+    }\n+\n+#endif\n+    if (lx & 3) for (; x < lx; x++)\n+    {\n+      res[0] += abs(pix1[x] - pix2[x]);\n+      res[1] += abs(pix1[x] - pix3[x]);\n+      res[2] += abs(pix1[x] - pix4[x]);\n+    }\n+\n+    pix1 += FENC_STRIDE;\n+    pix2 += frefstride;\n+    pix3 += frefstride;\n+    pix4 += frefstride;\n+  }\n+}\n+\n+template<int lx, int ly>\n+void sad_x4_neon(const pixel* pix1, const pixel* pix2, const pixel* pix3, const pixel* pix4, const pixel* pix5, intptr_t frefstride, int32_t* res)\n+{\n+  res[0] = 0;\n+  res[1] = 0;\n+  res[2] = 0;\n+  res[3] = 0;\n+  for (int y = 0; y < ly; y++)\n+  {\n+    int x=0;\n+    uint16x8_t vsum16_0 = vdupq_n_u16(0);\n+    uint16x8_t vsum16_1 = vdupq_n_u16(0);\n+    uint16x8_t vsum16_2 = vdupq_n_u16(0);\n+    uint16x8_t vsum16_3 = vdupq_n_u16(0);\n+#if HIGH_BIT_DEPTH\n+      for (; (x + 8) <= lx; x+=8) {\n+        uint16x8_t p1 = *(uint16x8_t*)&pix1[x];\n+        uint16x8_t p2 = *(uint16x8_t*)&pix2[x];\n+        uint16x8_t p3 = *(uint16x8_t*)&pix3[x];\n+        uint16x8_t p4 = *(uint16x8_t*)&pix4[x];\n+        uint16x8_t p5 = *(uint16x8_t*)&pix5[x];\n+        vsum16_0 = vabaq_s16(vsum16_0,p1,p2);\n+        vsum16_1 = vabaq_s16(vsum16_1,p1,p3);\n+        vsum16_2 = vabaq_s16(vsum16_2,p1,p4);\n+        vsum16_3 = vabaq_s16(vsum16_3,p1,p5);\n+\n+      }\n+      if (lx & 4) {\n+        uint16x4_t p1 = *(uint16x4_t*)&pix1[x];\n+        uint16x4_t p2 = *(uint16x4_t*)&pix2[x];\n+        uint16x4_t p3 = *(uint16x4_t*)&pix3[x];\n+        uint16x4_t p4 = *(uint16x4_t*)&pix4[x];\n+        uint16x4_t p5 = *(uint16x4_t*)&pix5[x];\n+        res[0] += vaddlv_s16(vaba_s16(vdup_n_s16(0),p1,p2));\n+        res[1] += vaddlv_s16(vaba_s16(vdup_n_s16(0),p1,p3));\n+        res[2] += vaddlv_s16(vaba_s16(vdup_n_s16(0),p1,p4));\n+        res[3] += vaddlv_s16(vaba_s16(vdup_n_s16(0),p1,p5));\n+        x += 4;\n+      }\n+      if (lx >= 4) {\n+        res[0] += vaddlvq_s16(vsum16_0);\n+        res[1] += vaddlvq_s16(vsum16_1);\n+        res[2] += vaddlvq_s16(vsum16_2);\n+        res[3] += vaddlvq_s16(vsum16_3);\n+      }\n+\n+#else\n+    \n+    for (; (x + 16) <= lx; x+=16) {\n+      uint8x16_t p1 = *(uint8x16_t*)&pix1[x];\n+      uint8x16_t p2 = *(uint8x16_t*)&pix2[x];\n+      uint8x16_t p3 = *(uint8x16_t*)&pix3[x];\n+      uint8x16_t p4 = *(uint8x16_t*)&pix4[x];\n+      uint8x16_t p5 = *(uint8x16_t*)&pix5[x];\n+      vsum16_0 = vabal_u8(vsum16_0,vget_low_u8(p1),vget_low_u8(p2));\n+      vsum16_0 = vabal_high_u8(vsum16_0,p1,p2);\n+      vsum16_1 = vabal_u8(vsum16_1,vget_low_u8(p1),vget_low_u8(p3));\n+      vsum16_1 = vabal_high_u8(vsum16_1,p1,p3);\n+      vsum16_2 = vabal_u8(vsum16_2,vget_low_u8(p1),vget_low_u8(p4));\n+      vsum16_2 = vabal_high_u8(vsum16_2,p1,p4);\n+      vsum16_3 = vabal_u8(vsum16_3,vget_low_u8(p1),vget_low_u8(p5));\n+      vsum16_3 = vabal_high_u8(vsum16_3,p1,p5);\n+    }\n+    if (lx & 8) {\n+      uint8x8_t p1 = *(uint8x8_t*)&pix1[x];\n+      uint8x8_t p2 = *(uint8x8_t*)&pix2[x];\n+      uint8x8_t p3 = *(uint8x8_t*)&pix3[x];\n+      uint8x8_t p4 = *(uint8x8_t*)&pix4[x];\n+      uint8x8_t p5 = *(uint8x8_t*)&pix5[x];\n+      vsum16_0 = vabal_u8(vsum16_0,p1,p2);\n+      vsum16_1 = vabal_u8(vsum16_1,p1,p3);\n+      vsum16_2 = vabal_u8(vsum16_2,p1,p4);\n+      vsum16_3 = vabal_u8(vsum16_3,p1,p5);\n+      x += 8;\n+    }\n+    if (lx & 4) {\n+      uint32x2_t p1 = vdup_n_u32(0);\n+      p1[0] = *(uint32_t*)&pix1[x];\n+      uint32x2_t p2 = vdup_n_u32(0);\n+      p2[0] = *(uint32_t*)&pix2[x];\n+      uint32x2_t p3 = vdup_n_u32(0);\n+      p3[0] = *(uint32_t*)&pix3[x];\n+      uint32x2_t p4 = vdup_n_u32(0);\n+      p4[0] = *(uint32_t*)&pix4[x];\n+      uint32x2_t p5 = vdup_n_u32(0);\n+      p5[0] = *(uint32_t*)&pix5[x];\n+      vsum16_0 = vabal_u8(vsum16_0,p1,p2);\n+      vsum16_1 = vabal_u8(vsum16_1,p1,p3);\n+      vsum16_2 = vabal_u8(vsum16_2,p1,p4);\n+      vsum16_3 = vabal_u8(vsum16_3,p1,p5);\n+      x += 4;\n+    }\n+    if (lx >= 4) {\n+      res[0] += vaddvq_u16(vsum16_0);\n+      res[1] += vaddvq_u16(vsum16_1);\n+      res[2] += vaddvq_u16(vsum16_2);\n+      res[3] += vaddvq_u16(vsum16_3);\n+    }\n+\n+#endif\n+    if (lx & 3) for (; x < lx; x++)\n+    {\n+      res[0] += abs(pix1[x] - pix2[x]);\n+      res[1] += abs(pix1[x] - pix3[x]);\n+      res[2] += abs(pix1[x] - pix4[x]);\n+      res[3] += abs(pix1[x] - pix5[x]);\n+    }\n+\n+    pix1 += FENC_STRIDE;\n+    pix2 += frefstride;\n+    pix3 += frefstride;\n+    pix4 += frefstride;\n+    pix5 += frefstride;\n+  }\n+}\n+\n+\n+template<int lx, int ly, class T1, class T2>\n+sse_t sse_neon(const T1* pix1, intptr_t stride_pix1, const T2* pix2, intptr_t stride_pix2)\n+{\n+    sse_t sum = 0;\n+\n+    int32x4_t vsum1 = vdupq_n_s32(0);\n+    int32x4_t vsum2 = vdupq_n_s32(0);\n+    for (int y = 0; y < ly; y++)\n+    {\n+      int x = 0;\n+        for (; (x+8) <= lx; x+=8)\n+        {\n+          int16x8_t tmp;\n+          if (sizeof(T1) == 2 && sizeof(T2) == 2) {\n+            tmp = vsubq_s16(*(int16x8_t *)&pix1[x],*(int16x8_t *)&pix2[x]);\n+          } else if (sizeof(T1) == 1 && sizeof(T2) == 1){\n+            tmp = vsubl_u8(*(uint8x8_t *)&pix1[x],*(uint8x8_t *)&pix2[x]);\n+          }\n+          else {\n+            X265_CHECK(false,\"unsupported sse\");\n+          }\n+          vsum1 = vmlal_s16(vsum1,vget_low_s16(tmp),vget_low_s16(tmp));\n+          vsum2 = vmlal_high_s16(vsum2,tmp,tmp);\n+        }\n+        for (; x < lx; x++)\n+        {\n+            int tmp = pix1[x] - pix2[x];\n+            sum += (tmp * tmp);\n+        }\n+        \n+        if (sizeof(T1) == 2 && sizeof(T2) == 2)\n+        {\n+            int32x4_t vsum = vaddq_u32(vsum1,vsum2);;\n+            sum += vaddvq_u32(vsum);\n+            vsum1 = vsum2 = vdupq_n_u16(0);\n+        }\n+\n+        pix1 += stride_pix1;\n+        pix2 += stride_pix2;\n+    }\n+    int32x4_t vsum = vaddq_u32(vsum1,vsum2);\n+\n+    return sum + vaddvq_u32(vsum);\n+}\n+\n+\n+template<int bx, int by>\n+void blockcopy_ps_neon(int16_t* a, intptr_t stridea, const pixel* b, intptr_t strideb)\n+{\n+    for (int y = 0; y < by; y++)\n+    {\n+      int x= 0;\n+      for (; (x + 8) <= bx; x+=8)\n+      {\n+#if HIGH_BIT_DEPTH\n+        *(int16x8_t *)&a[x] = *(int16x8_t *)&b[x];\n+#else\n+        *(int16x8_t *)&a[x] = vmovl_u8(*(int8x8_t *)&b[x]);\n+#endif\n+      }\n+      for (; x < bx; x++) {\n+          a[x] = (int16_t)b[x];\n+      }\n+      \n+      a += stridea;\n+      b += strideb;\n+    }\n+}\n+\n+\n+template<int bx, int by>\n+void blockcopy_pp_neon(pixel* a, intptr_t stridea, const pixel* b, intptr_t strideb)\n+{\n+    for (int y = 0; y < by; y++)\n+    {\n+      int x = 0;\n+#if HIGH_BIT_DEPTH\n+      for (; (x + 8) <= bx; x+=8)\n+      {\n+        *(int16x8_t *)&a[x] = *(int16x8_t *)&b[x];\n+      }\n+      if (bx & 4)\n+      {\n+        *(uint64_t *)&a[x] = *(uint64_t *)&b[x];\n+        x += 4;\n+      }\n+#else\n+      for (; (x + 16) <= bx; x+=16)\n+      {\n+        *(uint8x16_t *)&a[x] = *(uint8x16_t *)&b[x];\n+      }\n+      if (bx & 8)\n+      {\n+          *(uint8x8_t *)&a[x] = *(uint8x8_t *)&b[x];\n+          x += 8;\n+      }\n+      if (bx & 4)\n+      {\n+          *(uint32_t *)&a[x] = *(uint32_t *)&b[x];\n+          x += 4;\n+      }\n+#endif\n+      for (; x < bx; x++) {\n+          a[x] = b[x];\n+      }\n+\n+      a += stridea;\n+      b += strideb;\n+    }\n+}\n+\n+\n+template<int bx, int by>\n+void pixel_sub_ps_neon(int16_t* a, intptr_t dstride, const pixel* b0, const pixel* b1, intptr_t sstride0, intptr_t sstride1)\n+{\n+    for (int y = 0; y < by; y++)\n+    {\n+      int x = 0;\n+      for (; (x + 8) <= bx; x+=8) {\n+#if HIGH_BIT_DEPTH\n+        *(int16x8_t *)&a[x] = vsubq_s16(*(int16x8_t *)&b0[x], *(int16x8_t *)&b1[x]);\n+#else\n+        *(int16x8_t *)&a[x] = vsubl_u8(*(uint8x8_t *)&b0[x], *(uint8x8_t *)&b1[x]);\n+#endif\n+      }\n+      for (; x < bx; x++)\n+          a[x] = (int16_t)(b0[x] - b1[x]);\n+\n+        b0 += sstride0;\n+        b1 += sstride1;\n+        a += dstride;\n+    }\n+}\n+\n+template<int bx, int by>\n+void pixel_add_ps_neon(pixel* a, intptr_t dstride, const pixel* b0, const int16_t* b1, intptr_t sstride0, intptr_t sstride1)\n+{\n+        for (int y = 0; y < by; y++)\n+        {\n+          int x = 0;\n+          for (; (x + 8) <= bx; x+=8) {\n+            int16x8_t t;\n+            int16x8_t b1e = *(int16x8_t *)&b1[x];\n+            int16x8_t b0e;\n+#if HIGH_BIT_DEPTH\n+            b0e = *(int16x8_t *)&b0[x];\n+            t = vaddq_s16(b0e,b1e);\n+            t = vminq_s16(t,vdupq_n_s16((1 << X265_DEPTH) - 1));\n+            t = vmaxq_s16(t,vdupq_n_s16(0));\n+            *(int16x8_t *)&a[x] = t;\n+#else\n+            b0e = vmovl_u8(*(uint8x8_t *)&b0[x]);\n+            t = vaddq_s16(b0e,b1e);\n+            *(uint8x8_t *)&a[x] = vqmovun_s16(t);\n+#endif\n+          }\n+          for (; x < bx; x++)\n+              a[x] = (int16_t)x265_clip(b0[x] + b1[x]);\n+\n+          b0 += sstride0;\n+          b1 += sstride1;\n+          a += dstride;\n+        }\n+}\n+\n+template<int bx, int by>\n+void addAvg_neon(const int16_t* src0, const int16_t* src1, pixel* dst, intptr_t src0Stride, intptr_t src1Stride, intptr_t dstStride)\n+{\n+\n+    const int shiftNum = IF_INTERNAL_PREC + 1 - X265_DEPTH;\n+    const int offset = (1 << (shiftNum - 1)) + 2 * IF_INTERNAL_OFFS;\n+\n+    const int32x4_t addon = vdupq_n_s32(offset);\n+    for (int y = 0; y < by; y++)\n+    {\n+      int x = 0;\n+      \n+        for (; (x + 8) <= bx; x += 8)\n+        {\n+          int16x8_t in0 = *(int16x8_t*)&src0[x];\n+          int16x8_t in1 = *(int16x8_t*)&src1[x];\n+          int32x4_t t1 = vaddl_s16(vget_low_s16(in0),vget_low_s16(in1));\n+          int32x4_t t2 = vaddl_high_s16(in0,in1);\n+          t1 = vaddq_s32(t1,addon);\n+          t2 = vaddq_s32(t2,addon);\n+          t1 = vshrq_n_s32(t1,shiftNum);\n+          t2 = vshrq_n_s32(t2,shiftNum);\n+          int16x8_t t = vuzp1q_s16(t1,t2);\n+#if HIGH_BIT_DEPTH\n+          t = vminq_s16(t,vdupq_n_s16((1 << X265_DEPTH) - 1));\n+          t = vmaxq_s16(t,vdupq_n_s16(0));\n+          *(int16x8_t *)&dst[x] = t;\n+#else\n+          *(uint8x8_t *)&dst[x] = vqmovun_s16(t);\n+#endif\n+        }\n+      for (; x < bx; x += 2)\n+      {\n+          dst[x + 0] = x265_clip((src0[x + 0] + src1[x + 0] + offset) >> shiftNum);\n+          dst[x + 1] = x265_clip((src0[x + 1] + src1[x + 1] + offset) >> shiftNum);\n+      }\n+\n+        src0 += src0Stride;\n+        src1 += src1Stride;\n+        dst  += dstStride;\n+    }\n+}\n+\n+template<int lx, int ly>\n+void pixelavg_pp_neon(pixel* dst, intptr_t dstride, const pixel* src0, intptr_t sstride0, const pixel* src1, intptr_t sstride1, int)\n+{\n+    for (int y = 0; y < ly; y++)\n+    {\n+      int x = 0;\n+      for (; (x+8) <= lx; x+=8) {\n+#if HIGH_BIT_DEPTH\n+        int16x8_t in0 = *(int16x8_t *)&src0[x];\n+        int16x8_t in1 = *(int16x8_t *)&src1[x];\n+        int16x8_t t = vaddq_s16(in0,in1);\n+        t = vaddq_s16(t,vdupq_n_s16(1));\n+        t = vshrq_n_s16(t,1);\n+        *(int16x8_t *)&dst[x] = t;\n+#else\n+        int16x8_t in0 = vmovl_u8(*(uint8x8_t *)&src0[x]);\n+        int16x8_t in1 = vmovl_u8(*(uint8x8_t *)&src1[x]);\n+        int16x8_t t = vaddq_s16(in0,in1);\n+        t = vaddq_s16(t,vdupq_n_s16(1));\n+        t = vshrq_n_s16(t,1);\n+        *(uint8x8_t *)&dst[x] = vmovn_u16(t);\n+#endif\n+      }\n+      for (; x < lx; x++)\n+          dst[x] = (src0[x] + src1[x] + 1) >> 1;\n+\n+      src0 += sstride0;\n+      src1 += sstride1;\n+      dst += dstride;\n+    }\n+}\n+\n+\n+template<int size>\n+void cpy1Dto2D_shl_neon(int16_t* dst, const int16_t* src, intptr_t dstStride, int shift)\n+{\n+    X265_CHECK((((intptr_t)dst | (dstStride * sizeof(*dst))) & 15) == 0 || size == 4, \"dst alignment error\\n\");\n+    X265_CHECK(((intptr_t)src & 15) == 0, \"src alignment error\\n\");\n+    X265_CHECK(shift >= 0, \"invalid shift\\n\");\n+\n+    for (int i = 0; i < size; i++)\n+    {\n+        int j = 0;\n+        for (; (j+8) <= size; j+=8)\n+        {\n+          *(int16x8_t *)&dst[j] = vshlq_s16(*(int16x8_t*)&src[j],vdupq_n_s16(shift));\n+        }\n+        for (; j < size; j++)\n+        {\n+            dst[j] = src[j] << shift;\n+        }\n+        src += size;\n+        dst += dstStride;\n+    }\n+}\n+\n+\n+template<int size>\n+uint64_t pixel_var_neon(const uint8_t* pix, intptr_t i_stride)\n+{\n+    uint32_t sum = 0, sqr = 0;\n+\n+    int32x4_t vsqr = vdupq_n_s32(0);\n+    for (int y = 0; y < size; y++)\n+    {\n+      int x = 0;\n+      int16x8_t vsum = vdupq_n_s16(0);\n+      for (; (x + 8) <= size; x+=8)\n+      {\n+        int16x8_t in;\n+        in = vmovl_u8(*(uint8x8_t*)&pix[x]);\n+        vsum = vaddq_u16(vsum,in);\n+        vsqr = vmlal_s16(vsqr,vget_low_s16(in),vget_low_s16(in));\n+        vsqr = vmlal_high_s16(vsqr,in,in);\n+      }\n+      for (; x < size; x++)\n+      {\n+          sum += pix[x];\n+          sqr += pix[x] * pix[x];\n+      }\n+      sum += vaddvq_s16(vsum);\n+\n+      pix += i_stride;\n+    }\n+    sqr += vaddvq_u32(vsqr);\n+    return sum + ((uint64_t)sqr << 32);\n+}\n+\n+template<int blockSize>\n+void getResidual_neon(const pixel* fenc, const pixel* pred, int16_t* residual, intptr_t stride)\n+{\n+    for (int y = 0; y < blockSize; y++)\n+    {\n+      int x = 0;\n+      for (; (x + 8) < blockSize; x+=8) {\n+        int16x8_t vfenc,vpred;\n+#if HIGH_BIT_DEPTH\n+        vfenc = *(int16x8_t *)&fenc[x];\n+        vpred = *(int16x8_t *)&pred[x];\n+#else\n+        vfenc = vmovl_u8(*(uint8x8_t *)&fenc[x]);\n+        vpred = vmovl_u8(*(uint8x8_t *)&pred[x]);\n+#endif\n+        *(int16x8_t*)&residual[x] = vsubq_s16(vfenc,vpred);\n+      }\n+      for (; x < blockSize; x++) {\n+            residual[x] = static_cast<int16_t>(fenc[x]) - static_cast<int16_t>(pred[x]);\n+      }\n+      fenc += stride;\n+      residual += stride;\n+      pred += stride;\n+  }\n+}\n+\n+#if 1//!(HIGH_BIT_DEPTH)\n+template<int size>\n+int psyCost_pp_neon(const pixel* source, intptr_t sstride, const pixel* recon, intptr_t rstride)\n+{\n+    static pixel zeroBuf[8] /* = { 0 } */;\n+\n+    if (size)\n+    {\n+        int dim = 1 << (size + 2);\n+        uint32_t totEnergy = 0;\n+        for (int i = 0; i < dim; i += 8)\n+        {\n+            for (int j = 0; j < dim; j+= 8)\n+            {\n+                /* AC energy, measured by sa8d (AC + DC) minus SAD (DC) */\n+                int sourceEnergy = pixel_sa8d_8x8_neon(source + i * sstride + j, sstride, zeroBuf, 0) -\n+                                   (sad_pp_neon<8, 8>(source + i * sstride + j, sstride, zeroBuf, 0) >> 2);\n+                int reconEnergy =  pixel_sa8d_8x8_neon(recon + i * rstride + j, rstride, zeroBuf, 0) -\n+                                   (sad_pp_neon<8, 8>(recon + i * rstride + j, rstride, zeroBuf, 0) >> 2);\n+\n+                totEnergy += abs(sourceEnergy - reconEnergy);\n+            }\n+        }\n+        return totEnergy;\n+    }\n+    else\n+    {\n+        /* 4x4 is too small for sa8d */\n+        int sourceEnergy = pixel_satd_4x4_neon(source, sstride, zeroBuf, 0) - (sad_pp_neon<4, 4>(source, sstride, zeroBuf, 0) >> 2);\n+        int reconEnergy = pixel_satd_4x4_neon(recon, rstride, zeroBuf, 0) - (sad_pp_neon<4, 4>(recon, rstride, zeroBuf, 0) >> 2);\n+        return abs(sourceEnergy - reconEnergy);\n+    }\n+}\n+\n+\n+template<int w, int h>\n+// Calculate sa8d in blocks of 8x8\n+int sa8d8(const pixel* pix1, intptr_t i_pix1, const pixel* pix2, intptr_t i_pix2)\n+{\n+    int cost = 0;\n+\n+    for (int y = 0; y < h; y += 8)\n+        for (int x = 0; x < w; x += 8)\n+            cost += pixel_sa8d_8x8_neon(pix1 + i_pix1 * y + x, i_pix1, pix2 + i_pix2 * y + x, i_pix2);\n+\n+    return cost;\n+}\n+\n+template<int w, int h>\n+// Calculate sa8d in blocks of 16x16\n+int sa8d16(const pixel* pix1, intptr_t i_pix1, const pixel* pix2, intptr_t i_pix2)\n+{\n+    int cost = 0;\n+\n+    for (int y = 0; y < h; y += 16)\n+        for (int x = 0; x < w; x += 16)\n+            cost += pixel_sa8d_16x16_neon(pix1 + i_pix1 * y + x, i_pix1, pix2 + i_pix2 * y + x, i_pix2);\n+\n+    return cost;\n+}\n+#endif\n+\n+template<int size>\n+void cpy2Dto1D_shl_neon(int16_t* dst, const int16_t* src, intptr_t srcStride, int shift)\n+{\n+    X265_CHECK(((intptr_t)dst & 15) == 0, \"dst alignment error\\n\");\n+    X265_CHECK((((intptr_t)src | (srcStride * sizeof(*src))) & 15) == 0 || size == 4, \"src alignment error\\n\");\n+    X265_CHECK(shift >= 0, \"invalid shift\\n\");\n+\n+    for (int i = 0; i < size; i++)\n+    {\n+        for (int j = 0; j < size; j++)\n+            dst[j] = src[j] << shift;\n+\n+        src += srcStride;\n+        dst += size;\n+    }\n+}\n+\n+\n+#if 1//!(HIGH_BIT_DEPTH)\n+template<int w, int h>\n+// calculate satd in blocks of 4x4\n+int satd4(const pixel* pix1, intptr_t stride_pix1, const pixel* pix2, intptr_t stride_pix2)\n+{\n+    int satd = 0;\n+\n+    for (int row = 0; row < h; row += 4)\n+        for (int col = 0; col < w; col += 4)\n+            satd += pixel_satd_4x4_neon(pix1 + row * stride_pix1 + col, stride_pix1,\n+                             pix2 + row * stride_pix2 + col, stride_pix2);\n+\n+    return satd;\n+}\n+\n+template<int w, int h>\n+// calculate satd in blocks of 8x4\n+int satd8(const pixel* pix1, intptr_t stride_pix1, const pixel* pix2, intptr_t stride_pix2)\n+{\n+    int satd = 0;\n+\n+    if (((w | h) & 15) == 0)\n+    {\n+        for (int row = 0; row < h; row += 16)\n+            for (int col = 0; col < w; col += 16)\n+                satd += pixel_satd_16x16_neon(pix1 + row * stride_pix1 + col, stride_pix1,\n+                                            pix2 + row * stride_pix2 + col, stride_pix2);\n+\n+    }\n+    else\n+    if (((w | h) & 7) == 0)\n+    {\n+        for (int row = 0; row < h; row += 8)\n+            for (int col = 0; col < w; col += 8)\n+                satd += pixel_satd_8x8_neon(pix1 + row * stride_pix1 + col, stride_pix1,\n+                                            pix2 + row * stride_pix2 + col, stride_pix2);\n+\n+    }\n+    else\n+    {\n+        for (int row = 0; row < h; row += 4)\n+            for (int col = 0; col < w; col += 8)\n+                satd += pixel_satd_8x4_neon(pix1 + row * stride_pix1 + col, stride_pix1,\n+                                            pix2 + row * stride_pix2 + col, stride_pix2);\n+    }\n+\n+    return satd;\n+}\n+#endif\n+\n+\n+template<int blockSize>\n+void transpose_neon(pixel* dst, const pixel* src, intptr_t stride)\n+{\n+    for (int k = 0; k < blockSize; k++)\n+        for (int l = 0; l < blockSize; l++)\n+            dst[k * blockSize + l] = src[l * stride + k];\n+}\n+\n+\n+template<>\n+void transpose_neon<8>(pixel* dst, const pixel* src, intptr_t stride)\n+{\n+    transpose8x8(dst,src,8,stride);\n+}\n+\n+template<>\n+void transpose_neon<16>(pixel* dst, const pixel* src, intptr_t stride)\n+{\n+    transpose16x16(dst,src,16,stride);\n+}\n+\n+template<>\n+void transpose_neon<32>(pixel* dst, const pixel* src, intptr_t stride)\n+{\n+    transpose32x32(dst,src,32,stride);\n+}\n+\n+\n+template<>\n+void transpose_neon<64>(pixel* dst, const pixel* src, intptr_t stride)\n+{\n+    transpose32x32(dst,src,64,stride);\n+    transpose32x32(dst+32*64+32,src+32*stride+32,64,stride);\n+    transpose32x32(dst+32*64,src+32,64,stride);\n+    transpose32x32(dst+32,src+32*stride,64,stride);\n+}\n+\n+\n+template<int size>\n+sse_t pixel_ssd_s_neon(const int16_t* a, intptr_t dstride)\n+{\n+    sse_t sum = 0;\n+    \n+    \n+  int32x4_t vsum = vdupq_n_s32(0);\n+\n+    for (int y = 0; y < size; y++)\n+    {\n+      int x = 0;\n+      \n+      for (; (x + 8) <= size; x+=8) {\n+        int16x8_t in = *(int16x8_t*)&a[x];\n+        vsum = vmlal_s16(vsum,vget_low_s16(in),vget_low_s16(in));\n+        vsum = vmlal_high_s16(vsum,(in),(in));\n+      }\n+      for (; x < size; x++) {\n+            sum += a[x] * a[x];\n+      }\n+\n+        a += dstride;\n+    }\n+    return sum + vaddvq_s32(vsum);\n+}\n+\n+\n+};\n+\n+\n+\n+\n+namespace X265_NS {\n+   \n+  \n+void setupPixelPrimitives_neon(EncoderPrimitives &p)\n+{\n+  #define LUMA_PU(W, H) \\\n+      p.pu[LUMA_ ## W ## x ## H].copy_pp = blockcopy_pp_neon<W, H>; \\\n+      p.pu[LUMA_ ## W ## x ## H].addAvg[NONALIGNED] = addAvg_neon<W, H>; \\\n+      p.pu[LUMA_ ## W ## x ## H].addAvg[ALIGNED] = addAvg_neon<W, H>; \\\n+      p.pu[LUMA_ ## W ## x ## H].sad = sad_pp_neon<W, H>; \\\n+      p.pu[LUMA_ ## W ## x ## H].sad_x3 = sad_x3_neon<W, H>; \\\n+      p.pu[LUMA_ ## W ## x ## H].sad_x4 = sad_x4_neon<W, H>; \\\n+      p.pu[LUMA_ ## W ## x ## H].pixelavg_pp[NONALIGNED] = pixelavg_pp_neon<W, H>; \\\n+      p.pu[LUMA_ ## W ## x ## H].pixelavg_pp[ALIGNED] = pixelavg_pp_neon<W, H>;\n+  \n+#if !(HIGH_BIT_DEPTH)\n+\n+#define LUMA_CU(W, H) \\\n+      p.cu[BLOCK_ ## W ## x ## H].sub_ps        = pixel_sub_ps_neon<W, H>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].add_ps[NONALIGNED]    = pixel_add_ps_neon<W, H>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].add_ps[ALIGNED] = pixel_add_ps_neon<W, H>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].copy_ps       = blockcopy_ps_neon<W, H>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].copy_pp       = blockcopy_pp_neon<W, H>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].blockfill_s[NONALIGNED] = blockfill_s_neon<W>;  \\\n+      p.cu[BLOCK_ ## W ## x ## H].blockfill_s[ALIGNED]    = blockfill_s_neon<W>;  \\\n+      p.cu[BLOCK_ ## W ## x ## H].cpy2Dto1D_shl = cpy2Dto1D_shl_neon<W>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].cpy1Dto2D_shl[NONALIGNED] = cpy1Dto2D_shl_neon<W>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].cpy1Dto2D_shl[ALIGNED] = cpy1Dto2D_shl_neon<W>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].psy_cost_pp   = psyCost_pp_neon<BLOCK_ ## W ## x ## H>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].transpose     = transpose_neon<W>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].var           = pixel_var_neon<W>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].calcresidual[NONALIGNED]  = getResidual_neon<W>; \\\n+      p.cu[BLOCK_ ## W ## x ## H].calcresidual[ALIGNED]     = getResidual_neon<W>; \\\n+\n+#else\n+    \n+    #define LUMA_CU(W, H) \\\n+    p.cu[BLOCK_ ## W ## x ## H].sub_ps        = pixel_sub_ps_neon<W, H>; \\\n+    p.cu[BLOCK_ ## W ## x ## H].add_ps[NONALIGNED]    = pixel_add_ps_neon<W, H>; \\\n+    p.cu[BLOCK_ ## W ## x ## H].add_ps[ALIGNED] = pixel_add_ps_neon<W, H>; \\\n+    p.cu[BLOCK_ ## W ## x ## H].copy_pp       = blockcopy_pp_neon<W, H>; \\\n+    p.cu[BLOCK_ ## W ## x ## H].copy_ps       = blockcopy_ps_neon<W, H>; \\\n+    p.cu[BLOCK_ ## W ## x ## H].copy_pp       = blockcopy_pp_neon<W, H>; \\\n+    p.cu[BLOCK_ ## W ## x ## H].blockfill_s[NONALIGNED] = blockfill_s_neon<W>;  \\\n+    p.cu[BLOCK_ ## W ## x ## H].blockfill_s[ALIGNED]    = blockfill_s_neon<W>;  \\\n+    p.cu[BLOCK_ ## W ## x ## H].cpy2Dto1D_shl = cpy2Dto1D_shl_neon<W>; \\\n+    p.cu[BLOCK_ ## W ## x ## H].cpy1Dto2D_shl[NONALIGNED] = cpy1Dto2D_shl_neon<W>; \\\n+    p.cu[BLOCK_ ## W ## x ## H].cpy1Dto2D_shl[ALIGNED] = cpy1Dto2D_shl_neon<W>; \\\n+    p.cu[BLOCK_ ## W ## x ## H].psy_cost_pp   = psyCost_pp_neon<BLOCK_ ## W ## x ## H>; \\\n+    p.cu[BLOCK_ ## W ## x ## H].transpose     = transpose_neon<W>; \\\n+    /*p.cu[BLOCK_ ## W ## x ## H].var           = pixel_var_neon<W>;*/ \\\n+    p.cu[BLOCK_ ## W ## x ## H].calcresidual[NONALIGNED]  = getResidual_neon<W>; \\\n+    p.cu[BLOCK_ ## W ## x ## H].calcresidual[ALIGNED]     = getResidual_neon<W>; \\\n+\n+    \n+    \n+#endif\n+    \n+    \n+      LUMA_PU(4, 4);\n+      LUMA_PU(8, 8);\n+      LUMA_PU(16, 16);\n+      LUMA_PU(32, 32);\n+      LUMA_PU(64, 64);\n+      LUMA_PU(4, 8);\n+      LUMA_PU(8, 4);\n+      LUMA_PU(16,  8);\n+      LUMA_PU(8, 16);\n+      LUMA_PU(16, 12);\n+      LUMA_PU(12, 16);\n+      LUMA_PU(16,  4);\n+      LUMA_PU(4, 16);\n+      LUMA_PU(32, 16);\n+      LUMA_PU(16, 32);\n+      LUMA_PU(32, 24);\n+      LUMA_PU(24, 32);\n+      LUMA_PU(32,  8);\n+      LUMA_PU(8, 32);\n+      LUMA_PU(64, 32);\n+      LUMA_PU(32, 64);\n+      LUMA_PU(64, 48);\n+      LUMA_PU(48, 64);\n+      LUMA_PU(64, 16);\n+      LUMA_PU(16, 64);\n+\n+      p.pu[LUMA_4x4].satd   = pixel_satd_4x4_neon;\n+      p.pu[LUMA_8x8].satd   = satd8<8, 8>;\n+      p.pu[LUMA_8x4].satd   = pixel_satd_8x4_neon;\n+      p.pu[LUMA_4x8].satd   = satd4<4, 8>;\n+      p.pu[LUMA_16x16].satd = satd8<16, 16>;\n+      p.pu[LUMA_16x8].satd  = satd8<16, 8>;\n+      p.pu[LUMA_8x16].satd  = satd8<8, 16>;\n+      p.pu[LUMA_16x12].satd = satd8<16, 12>;\n+      p.pu[LUMA_12x16].satd = satd4<12, 16>;\n+      p.pu[LUMA_16x4].satd  = satd8<16, 4>;\n+      p.pu[LUMA_4x16].satd  = satd4<4, 16>;\n+      p.pu[LUMA_32x32].satd = satd8<32, 32>;\n+      p.pu[LUMA_32x16].satd = satd8<32, 16>;\n+      p.pu[LUMA_16x32].satd = satd8<16, 32>;\n+      p.pu[LUMA_32x24].satd = satd8<32, 24>;\n+      p.pu[LUMA_24x32].satd = satd8<24, 32>;\n+      p.pu[LUMA_32x8].satd  = satd8<32, 8>;\n+      p.pu[LUMA_8x32].satd  = satd8<8, 32>;\n+      p.pu[LUMA_64x64].satd = satd8<64, 64>;\n+      p.pu[LUMA_64x32].satd = satd8<64, 32>;\n+      p.pu[LUMA_32x64].satd = satd8<32, 64>;\n+      p.pu[LUMA_64x48].satd = satd8<64, 48>;\n+      p.pu[LUMA_48x64].satd = satd8<48, 64>;\n+      p.pu[LUMA_64x16].satd = satd8<64, 16>;\n+      p.pu[LUMA_16x64].satd = satd8<16, 64>;\n+\n+    \n+      LUMA_CU(4, 4);\n+      LUMA_CU(8, 8);\n+      LUMA_CU(16, 16);\n+      LUMA_CU(32, 32);\n+      LUMA_CU(64, 64);\n+\n+\n+      p.cu[BLOCK_4x4].sa8d   = pixel_satd_4x4_neon;\n+      p.cu[BLOCK_8x8].sa8d   = pixel_sa8d_8x8_neon;\n+      p.cu[BLOCK_16x16].sa8d = pixel_sa8d_16x16_neon;\n+      p.cu[BLOCK_32x32].sa8d = sa8d16<32, 32>;\n+      p.cu[BLOCK_64x64].sa8d = sa8d16<64, 64>;\n+\n+    \n+  #define CHROMA_PU_420(W, H) \\\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_ ## W ## x ## H].addAvg[NONALIGNED]  = addAvg_neon<W, H>;         \\\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_ ## W ## x ## H].addAvg[ALIGNED]  = addAvg_neon<W, H>;         \\\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_ ## W ## x ## H].copy_pp = blockcopy_pp_neon<W, H>; \\\n+\n+\n+      CHROMA_PU_420(4, 4);\n+      CHROMA_PU_420(8, 8);\n+      CHROMA_PU_420(16, 16);\n+      CHROMA_PU_420(32, 32);\n+      CHROMA_PU_420(4, 2);\n+      CHROMA_PU_420(8, 4);\n+      CHROMA_PU_420(4, 8);\n+      CHROMA_PU_420(8, 6);\n+      CHROMA_PU_420(6, 8);\n+      CHROMA_PU_420(8, 2);\n+      CHROMA_PU_420(2, 8);\n+      CHROMA_PU_420(16, 8);\n+      CHROMA_PU_420(8,  16);\n+      CHROMA_PU_420(16, 12);\n+      CHROMA_PU_420(12, 16);\n+      CHROMA_PU_420(16, 4);\n+      CHROMA_PU_420(4,  16);\n+      CHROMA_PU_420(32, 16);\n+      CHROMA_PU_420(16, 32);\n+      CHROMA_PU_420(32, 24);\n+      CHROMA_PU_420(24, 32);\n+      CHROMA_PU_420(32, 8);\n+      CHROMA_PU_420(8,  32);\n+\n+    \n+\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_2x2].satd   = NULL;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_4x4].satd   = pixel_satd_4x4_neon;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_8x8].satd   = satd8<8, 8>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_16x16].satd = satd8<16, 16>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_32x32].satd = satd8<32, 32>;\n+\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_4x2].satd   = NULL;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_2x4].satd   = NULL;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_8x4].satd   = pixel_satd_8x4_neon;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_4x8].satd   = satd4<4, 8>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_16x8].satd  = satd8<16, 8>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_8x16].satd  = satd8<8, 16>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_32x16].satd = satd8<32, 16>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_16x32].satd = satd8<16, 32>;\n+\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_8x6].satd   = NULL;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_6x8].satd   = NULL;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_8x2].satd   = NULL;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_2x8].satd   = NULL;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_16x12].satd = satd4<16, 12>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_12x16].satd = satd4<12, 16>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_16x4].satd  = satd4<16, 4>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_4x16].satd  = satd4<4, 16>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_32x24].satd = satd8<32, 24>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_24x32].satd = satd8<24, 32>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_32x8].satd  = satd8<32, 8>;\n+      p.chroma[X265_CSP_I420].pu[CHROMA_420_8x32].satd  = satd8<8, 32>;\n+\n+    \n+  #define CHROMA_CU_420(W, H) \\\n+      p.chroma[X265_CSP_I420].cu[BLOCK_420_ ## W ## x ## H].sse_pp  = sse_neon<W, H, pixel, pixel>; \\\n+      p.chroma[X265_CSP_I420].cu[BLOCK_420_ ## W ## x ## H].copy_pp = blockcopy_pp_neon<W, H>; \\\n+      p.chroma[X265_CSP_I420].cu[BLOCK_420_ ## W ## x ## H].copy_ps = blockcopy_ps_neon<W, H>; \\\n+      p.chroma[X265_CSP_I420].cu[BLOCK_420_ ## W ## x ## H].sub_ps = pixel_sub_ps_neon<W, H>;  \\\n+      p.chroma[X265_CSP_I420].cu[BLOCK_420_ ## W ## x ## H].add_ps[NONALIGNED] = pixel_add_ps_neon<W, H>; \\\n+      p.chroma[X265_CSP_I420].cu[BLOCK_420_ ## W ## x ## H].add_ps[ALIGNED] = pixel_add_ps_neon<W, H>;\n+\n+\n+      CHROMA_CU_420(4, 4)\n+      CHROMA_CU_420(8, 8)\n+      CHROMA_CU_420(16, 16)\n+      CHROMA_CU_420(32, 32)\n+\n+\n+      p.chroma[X265_CSP_I420].cu[BLOCK_8x8].sa8d   = p.chroma[X265_CSP_I420].pu[CHROMA_420_4x4].satd;\n+      p.chroma[X265_CSP_I420].cu[BLOCK_16x16].sa8d = sa8d8<8, 8>;\n+      p.chroma[X265_CSP_I420].cu[BLOCK_32x32].sa8d = sa8d16<16, 16>;\n+      p.chroma[X265_CSP_I420].cu[BLOCK_64x64].sa8d = sa8d16<32, 32>;\n+\n+    \n+  #define CHROMA_PU_422(W, H) \\\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_ ## W ## x ## H].addAvg[NONALIGNED]  = addAvg_neon<W, H>;         \\\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_ ## W ## x ## H].addAvg[ALIGNED]  = addAvg_neon<W, H>;         \\\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_ ## W ## x ## H].copy_pp = blockcopy_pp_neon<W, H>; \\\n+\n+\n+      CHROMA_PU_422(4, 8);\n+      CHROMA_PU_422(8, 16);\n+      CHROMA_PU_422(16, 32);\n+      CHROMA_PU_422(32, 64);\n+      CHROMA_PU_422(4, 4);\n+      CHROMA_PU_422(2, 8);\n+      CHROMA_PU_422(8, 8);\n+      CHROMA_PU_422(4, 16);\n+      CHROMA_PU_422(8, 12);\n+      CHROMA_PU_422(6, 16);\n+      CHROMA_PU_422(8, 4);\n+      CHROMA_PU_422(2, 16);\n+      CHROMA_PU_422(16, 16);\n+      CHROMA_PU_422(8, 32);\n+      CHROMA_PU_422(16, 24);\n+      CHROMA_PU_422(12, 32);\n+      CHROMA_PU_422(16, 8);\n+      CHROMA_PU_422(4,  32);\n+      CHROMA_PU_422(32, 32);\n+      CHROMA_PU_422(16, 64);\n+      CHROMA_PU_422(32, 48);\n+      CHROMA_PU_422(24, 64);\n+      CHROMA_PU_422(32, 16);\n+      CHROMA_PU_422(8,  64);\n+\n+\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_2x4].satd   = NULL;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_4x8].satd   = satd4<4, 8>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_8x16].satd  = satd8<8, 16>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_16x32].satd = satd8<16, 32>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_32x64].satd = satd8<32, 64>;\n+\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_4x4].satd   = pixel_satd_4x4_neon;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_2x8].satd   = NULL;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_8x8].satd   = satd8<8, 8>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_4x16].satd  = satd4<4, 16>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_16x16].satd = satd8<16, 16>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_8x32].satd  = satd8<8, 32>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_32x32].satd = satd8<32, 32>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_16x64].satd = satd8<16, 64>;\n+\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_8x12].satd  = satd4<8, 12>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_6x16].satd  = NULL;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_8x4].satd   = satd4<8, 4>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_2x16].satd  = NULL;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_16x24].satd = satd8<16, 24>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_12x32].satd = satd4<12, 32>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_16x8].satd  = satd8<16, 8>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_4x32].satd  = satd4<4, 32>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_32x48].satd = satd8<32, 48>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_24x64].satd = satd8<24, 64>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_32x16].satd = satd8<32, 16>;\n+      p.chroma[X265_CSP_I422].pu[CHROMA_422_8x64].satd  = satd8<8, 64>;\n+\n+    \n+  #define CHROMA_CU_422(W, H) \\\n+      p.chroma[X265_CSP_I422].cu[BLOCK_422_ ## W ## x ## H].sse_pp  = sse_neon<W, H, pixel, pixel>;  \\\n+      p.chroma[X265_CSP_I422].cu[BLOCK_422_ ## W ## x ## H].copy_pp = blockcopy_pp_neon<W, H>; \\\n+      p.chroma[X265_CSP_I422].cu[BLOCK_422_ ## W ## x ## H].copy_ps = blockcopy_ps_neon<W, H>; \\\n+      p.chroma[X265_CSP_I422].cu[BLOCK_422_ ## W ## x ## H].sub_ps = pixel_sub_ps_neon<W, H>; \\\n+      p.chroma[X265_CSP_I422].cu[BLOCK_422_ ## W ## x ## H].add_ps[NONALIGNED] = pixel_add_ps_neon<W, H>; \\\n+      p.chroma[X265_CSP_I422].cu[BLOCK_422_ ## W ## x ## H].add_ps[ALIGNED] = pixel_add_ps_neon<W, H>;\n+\n+\n+      CHROMA_CU_422(4, 8)\n+      CHROMA_CU_422(8, 16)\n+      CHROMA_CU_422(16, 32)\n+      CHROMA_CU_422(32, 64)\n+\n+      p.chroma[X265_CSP_I422].cu[BLOCK_8x8].sa8d   = p.chroma[X265_CSP_I422].pu[CHROMA_422_4x8].satd;\n+      p.chroma[X265_CSP_I422].cu[BLOCK_16x16].sa8d = sa8d8<8, 16>;\n+      p.chroma[X265_CSP_I422].cu[BLOCK_32x32].sa8d = sa8d16<16, 32>;\n+      p.chroma[X265_CSP_I422].cu[BLOCK_64x64].sa8d = sa8d16<32, 64>;\n+\n+    \n+}\n+  \n+  \n+}\n+\n+\n+#endif\n+\ndiff -Naur ./source/common/arm64/pixel-prim.h ../x265_apple_patch/source/common/arm64/pixel-prim.h\n--- ./source/common/arm64/pixel-prim.h\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/pixel-prim.h\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,22 @@\n+#ifndef PIXEL_PRIM_NEON_H__\n+#define PIXEL_PRIM_NEON_H__\n+\n+#include \"common.h\"\n+#include \"slicetype.h\"      // LOWRES_COST_MASK\n+#include \"primitives.h\"\n+#include \"x265.h\"\n+\n+\n+\n+namespace X265_NS {\n+  \n+  \n+  \n+void setupPixelPrimitives_neon(EncoderPrimitives &p);\n+  \n+  \n+}\n+\n+\n+#endif\n+\ndiff -Naur ./source/common/arm64/pixel.h ../x265_apple_patch/source/common/arm64/pixel.h\n--- ./source/common/arm64/pixel.h\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/common/arm64/pixel.h\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,134 @@\n+/*****************************************************************************\n+ * pixel.h: aarch64 pixel metrics\n+ *****************************************************************************\n+ * Copyright (C) 2009-2019 x265 project\n+ *\n+ * Authors: David Conrad <lessen42@gmail.com>\n+ *          Janne Grunau <janne-x265@jannau.net>\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License as published by\n+ * the Free Software Foundation; either version 2 of the License, or\n+ * (at your option) any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU General Public License\n+ * along with this program; if not, write to the Free Software\n+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.\n+ *\n+ * This program is also available under a commercial proprietary license.\n+ * For more information, contact us at licensing@x265.com.\n+ *****************************************************************************/\n+\n+#ifndef x265_AARCH64_PIXEL_H\n+#define x265_AARCH64_PIXEL_H\n+\n+#define x265_pixel_sad_16x16_neon x265_template(pixel_sad_16x16_neon)\n+#define x265_pixel_sad_16x8_neon x265_template(pixel_sad_16x8_neon)\n+#define x265_pixel_sad_4x16_neon x265_template(pixel_sad_4x16_neon)\n+#define x265_pixel_sad_4x4_neon x265_template(pixel_sad_4x4_neon)\n+#define x265_pixel_sad_4x8_neon x265_template(pixel_sad_4x8_neon)\n+#define x265_pixel_sad_8x16_neon x265_template(pixel_sad_8x16_neon)\n+#define x265_pixel_sad_8x4_neon x265_template(pixel_sad_8x4_neon)\n+#define x265_pixel_sad_8x8_neon x265_template(pixel_sad_8x8_neon)\n+#define x265_pixel_sad_x3_16x16_neon x265_template(pixel_sad_x3_16x16_neon)\n+#define x265_pixel_sad_x3_16x8_neon x265_template(pixel_sad_x3_16x8_neon)\n+#define x265_pixel_sad_x3_4x4_neon x265_template(pixel_sad_x3_4x4_neon)\n+#define x265_pixel_sad_x3_4x8_neon x265_template(pixel_sad_x3_4x8_neon)\n+#define x265_pixel_sad_x3_8x16_neon x265_template(pixel_sad_x3_8x16_neon)\n+#define x265_pixel_sad_x3_8x4_neon x265_template(pixel_sad_x3_8x4_neon)\n+#define x265_pixel_sad_x3_8x8_neon x265_template(pixel_sad_x3_8x8_neon)\n+#define x265_pixel_sad_x4_16x16_neon x265_template(pixel_sad_x4_16x16_neon)\n+#define x265_pixel_sad_x4_16x8_neon x265_template(pixel_sad_x4_16x8_neon)\n+#define x265_pixel_sad_x4_4x4_neon x265_template(pixel_sad_x4_4x4_neon)\n+#define x265_pixel_sad_x4_4x8_neon x265_template(pixel_sad_x4_4x8_neon)\n+#define x265_pixel_sad_x4_8x16_neon x265_template(pixel_sad_x4_8x16_neon)\n+#define x265_pixel_sad_x4_8x4_neon x265_template(pixel_sad_x4_8x4_neon)\n+#define x265_pixel_sad_x4_8x8_neon x265_template(pixel_sad_x4_8x8_neon)\n+#define x265_pixel_satd_16x16_neon x265_template(pixel_satd_16x16_neon)\n+#define x265_pixel_satd_16x8_neon x265_template(pixel_satd_16x8_neon)\n+#define x265_pixel_satd_4x16_neon x265_template(pixel_satd_4x16_neon)\n+#define x265_pixel_satd_4x4_neon x265_template(pixel_satd_4x4_neon)\n+#define x265_pixel_satd_4x8_neon x265_template(pixel_satd_4x8_neon)\n+#define x265_pixel_satd_8x16_neon x265_template(pixel_satd_8x16_neon)\n+#define x265_pixel_satd_8x4_neon x265_template(pixel_satd_8x4_neon)\n+#define x265_pixel_satd_8x8_neon x265_template(pixel_satd_8x8_neon)\n+#define x265_pixel_ssd_16x16_neon x265_template(pixel_ssd_16x16_neon)\n+#define x265_pixel_ssd_16x8_neon x265_template(pixel_ssd_16x8_neon)\n+#define x265_pixel_ssd_4x16_neon x265_template(pixel_ssd_4x16_neon)\n+#define x265_pixel_ssd_4x4_neon x265_template(pixel_ssd_4x4_neon)\n+#define x265_pixel_ssd_4x8_neon x265_template(pixel_ssd_4x8_neon)\n+#define x265_pixel_ssd_8x16_neon x265_template(pixel_ssd_8x16_neon)\n+#define x265_pixel_ssd_8x4_neon x265_template(pixel_ssd_8x4_neon)\n+#define x265_pixel_ssd_8x8_neon x265_template(pixel_ssd_8x8_neon)\n+#define DECL_PIXELS( ret, name, suffix, args ) \\\n+    ret x265_pixel_##name##_16x16_##suffix args;\\\n+    ret x265_pixel_##name##_16x8_##suffix args;\\\n+    ret x265_pixel_##name##_8x16_##suffix args;\\\n+    ret x265_pixel_##name##_8x8_##suffix args;\\\n+    ret x265_pixel_##name##_8x4_##suffix args;\\\n+    ret x265_pixel_##name##_4x16_##suffix args;\\\n+    ret x265_pixel_##name##_4x8_##suffix args;\\\n+    ret x265_pixel_##name##_4x4_##suffix args;\\\n+\n+#define DECL_X1( name, suffix ) \\\n+    DECL_PIXELS( int, name, suffix, ( uint8_t *, intptr_t, uint8_t *, intptr_t ) )\n+\n+#define DECL_X4( name, suffix ) \\\n+    DECL_PIXELS( void, name##_x3, suffix, ( uint8_t *, uint8_t *, uint8_t *, uint8_t *, intptr_t, int * ) )\\\n+    DECL_PIXELS( void, name##_x4, suffix, ( uint8_t *, uint8_t *, uint8_t *, uint8_t *, uint8_t *, intptr_t, int * ) )\n+\n+DECL_X1( sad, neon )\n+DECL_X4( sad, neon )\n+DECL_X1( satd, neon )\n+DECL_X1( ssd, neon )\n+\n+\n+#define x265_pixel_ssd_nv12_core_neon x265_template(pixel_ssd_nv12_core_neon)\n+void x265_pixel_ssd_nv12_core_neon( uint8_t *, intptr_t, uint8_t *, intptr_t, int, int, uint64_t *, uint64_t * );\n+\n+#define x265_pixel_vsad_neon x265_template(pixel_vsad_neon)\n+int x265_pixel_vsad_neon( uint8_t *, intptr_t, int );\n+\n+#define x265_pixel_sa8d_8x8_neon x265_template(pixel_sa8d_8x8_neon)\n+int x265_pixel_sa8d_8x8_neon  ( uint8_t *, intptr_t, uint8_t *, intptr_t );\n+#define x265_pixel_sa8d_16x16_neon x265_template(pixel_sa8d_16x16_neon)\n+int x265_pixel_sa8d_16x16_neon( uint8_t *, intptr_t, uint8_t *, intptr_t );\n+#define x265_pixel_sa8d_satd_16x16_neon x265_template(pixel_sa8d_satd_16x16_neon)\n+uint64_t x265_pixel_sa8d_satd_16x16_neon( uint8_t *, intptr_t, uint8_t *, intptr_t );\n+\n+#define x265_pixel_var_8x8_neon x265_template(pixel_var_8x8_neon)\n+uint64_t x265_pixel_var_8x8_neon  ( uint8_t *, intptr_t );\n+#define x265_pixel_var_8x16_neon x265_template(pixel_var_8x16_neon)\n+uint64_t x265_pixel_var_8x16_neon ( uint8_t *, intptr_t );\n+#define x265_pixel_var_16x16_neon x265_template(pixel_var_16x16_neon)\n+uint64_t x265_pixel_var_16x16_neon( uint8_t *, intptr_t );\n+#define x265_pixel_var2_8x8_neon x265_template(pixel_var2_8x8_neon)\n+int x265_pixel_var2_8x8_neon ( uint8_t *, uint8_t *, int * );\n+#define x265_pixel_var2_8x16_neon x265_template(pixel_var2_8x16_neon)\n+int x265_pixel_var2_8x16_neon( uint8_t *, uint8_t *, int * );\n+\n+#define x265_pixel_hadamard_ac_8x8_neon x265_template(pixel_hadamard_ac_8x8_neon)\n+uint64_t x265_pixel_hadamard_ac_8x8_neon  ( uint8_t *, intptr_t );\n+#define x265_pixel_hadamard_ac_8x16_neon x265_template(pixel_hadamard_ac_8x16_neon)\n+uint64_t x265_pixel_hadamard_ac_8x16_neon ( uint8_t *, intptr_t );\n+#define x265_pixel_hadamard_ac_16x8_neon x265_template(pixel_hadamard_ac_16x8_neon)\n+uint64_t x265_pixel_hadamard_ac_16x8_neon ( uint8_t *, intptr_t );\n+#define x265_pixel_hadamard_ac_16x16_neon x265_template(pixel_hadamard_ac_16x16_neon)\n+uint64_t x265_pixel_hadamard_ac_16x16_neon( uint8_t *, intptr_t );\n+\n+#define x265_pixel_ssim_4x4x2_core_neon x265_template(pixel_ssim_4x4x2_core_neon)\n+void x265_pixel_ssim_4x4x2_core_neon( const uint8_t *, intptr_t,\n+                                      const uint8_t *, intptr_t,\n+                                      int sums[2][4] );\n+#define x265_pixel_ssim_end4_neon x265_template(pixel_ssim_end4_neon)\n+float x265_pixel_ssim_end4_neon( int sum0[5][4], int sum1[5][4], int width );\n+\n+#define x265_pixel_asd8_neon x265_template(pixel_asd8_neon)\n+int x265_pixel_asd8_neon( uint8_t *, intptr_t,  uint8_t *, intptr_t, int );\n+\n+#endif\ndiff -Naur ./source/common/cpu.cpp ../x265_apple_patch/source/common/cpu.cpp\n--- ./source/common/cpu.cpp\t2021-05-08 13:06:22.000000000 +0100\n+++ ../x265_apple_patch/source/common/cpu.cpp\t2021-05-08 13:08:01.000000000 +0100\n@@ -104,7 +104,8 @@\n     { \"ARMv6\",           X265_CPU_ARMV6 },\n     { \"NEON\",            X265_CPU_NEON },\n     { \"FastNeonMRC\",     X265_CPU_FAST_NEON_MRC },\n-\n+#elif X265_ARCH_ARM64\n+    { \"NEON\",            X265_CPU_NEON },\n #elif X265_ARCH_POWER8\n     { \"Altivec\",         X265_CPU_ALTIVEC },\n \n@@ -374,6 +375,18 @@\n #endif // if HAVE_ARMV6\n     return flags;\n }\n+#elif X265_ARCH_ARM64\n+\n+uint32_t cpu_detect(bool benableavx512)\n+{\n+    int flags = 0;\n+\n+#if HAVE_NEON\n+    flags |= X265_CPU_NEON;\n+#endif\n+\n+    return flags;\n+}\n \n #elif X265_ARCH_POWER8\n \ndiff -Naur ./source/common/pixel.cpp ../x265_apple_patch/source/common/pixel.cpp\n--- ./source/common/pixel.cpp\t2021-05-08 13:06:22.000000000 +0100\n+++ ../x265_apple_patch/source/common/pixel.cpp\t2021-05-08 13:08:01.000000000 +0100\n@@ -266,7 +266,7 @@\n {\n     int satd = 0;\n \n-#if ENABLE_ASSEMBLY && X265_ARCH_ARM64\n+#if ENABLE_ASSEMBLY && X265_ARCH_ARM64 && 0\n     pixelcmp_t satd_4x4 = x265_pixel_satd_4x4_neon;\n #endif\n \n@@ -284,7 +284,7 @@\n {\n     int satd = 0;\n \n-#if ENABLE_ASSEMBLY && X265_ARCH_ARM64\n+#if ENABLE_ASSEMBLY && X265_ARCH_ARM64 && 0\n     pixelcmp_t satd_8x4 = x265_pixel_satd_8x4_neon;\n #endif\n \ndiff -Naur ./source/common/version.cpp ../x265_apple_patch/source/common/version.cpp\n--- ./source/common/version.cpp\t2021-05-08 13:06:22.000000000 +0100\n+++ ../x265_apple_patch/source/common/version.cpp\t2021-05-08 13:47:38.000000000 +0100\n@@ -31,7 +31,7 @@\n \n #if defined(__clang__)\n #define COMPILEDBY  \"[clang \" XSTR(__clang_major__) \".\" XSTR(__clang_minor__) \".\" XSTR(__clang_patchlevel__) \"]\"\n-#ifdef __IA64__\n+#ifdef __IA64__ || __arm64__ || __aarch64__\n #define ONARCH    \"[on 64-bit] \"\n #else\n #define ONARCH    \"[on 32-bit] \"\n@@ -71,7 +71,7 @@\n #define ONOS    \"[Unk-OS]\"\n #endif\n \n-#if X86_64\n+#if X86_64 || __arm64__ || __aarch64__\n #define BITS    \"[64 bit]\"\n #else\n #define BITS    \"[32 bit]\"\ndiff -Naur ./source/test/testharness.h ../x265_apple_patch/source/test/testharness.h\n--- ./source/test/testharness.h\t2021-05-08 13:06:22.000000000 +0100\n+++ ../x265_apple_patch/source/test/testharness.h\t2021-05-08 13:08:01.000000000 +0100\n@@ -64,7 +64,6 @@\n \n     uint64_t m_rand;\n };\n-\n #ifdef _MSC_VER\n #include <intrin.h>\n #elif HAVE_RDTSC\n@@ -73,7 +72,7 @@\n #include <x86intrin.h>\n #elif ( !defined(__APPLE__) && defined (__GNUC__) && defined(__ARM_NEON__))\n #include <arm_neon.h>\n-#elif defined(__GNUC__) && (!defined(__clang__) || __clang_major__ < 4)\n+#else\n /* fallback for older GCC/MinGW */\n static inline uint32_t __rdtsc(void)\n {\n@@ -90,6 +89,12 @@\n \n     // TO-DO: replace clock() function with appropriate ARM cpu instructions\n     a = clock();\n+#elif X265_ARCH_ARM64\n+    // TOD-DO: verify following inline asm to get cpu Timestamp Counter for ARM arch\n+    // asm volatile(\"mrc p15, 0, %0, c9, c13, 0\" : \"=r\"(a));\n+\n+    // TO-DO: replace clock() function with appropriate ARM cpu instructions\n+    a = clock();\n #endif\n #endif\n     return a;\n@@ -140,7 +145,7 @@\n  * needs an explicit asm check because it only sometimes crashes in normal use. */\n intptr_t PFX(checkasm_call)(intptr_t (*func)(), int *ok, ...);\n float PFX(checkasm_call_float)(float (*func)(), int *ok, ...);\n-#elif X265_ARCH_ARM == 0\n+#elif (X265_ARCH_ARM == 0 && X265_ARCH_ARM64 == 0)\n #define PFX(stack_pagealign)(func, align) func()\n #endif\n \ndiff -Naur ./source/test/testharness.h.orig ../x265_apple_patch/source/test/testharness.h.orig\n--- ./source/test/testharness.h.orig\t1970-01-01 01:00:00.000000000 +0100\n+++ ../x265_apple_patch/source/test/testharness.h.orig\t2021-05-08 13:08:01.000000000 +0100\n@@ -0,0 +1,184 @@\n+/*****************************************************************************\n+ * Copyright (C) 2013-2020 MulticoreWare, Inc\n+ *\n+ * Authors: Steve Borho <steve@borho.org>\n+ *          Min Chen <chenm003@163.com>\n+ *          Yimeng Su <yimeng.su@huawei.com>\n+ *\n+ * This program is free software; you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License as published by\n+ * the Free Software Foundation; either version 2 of the License, or\n+ * (at your option) any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU General Public License\n+ * along with this program; if not, write to the Free Software\n+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.\n+ *\n+ * This program is also available under a commercial proprietary license.\n+ * For more information, contact us at license @ x265.com.\n+ *****************************************************************************/\n+\n+#ifndef _TESTHARNESS_H_\n+#define _TESTHARNESS_H_ 1\n+\n+#include \"common.h\"\n+#include \"primitives.h\"\n+\n+#if _MSC_VER\n+#pragma warning(disable: 4324) // structure was padded due to __declspec(align())\n+#endif\n+\n+#define PIXEL_MIN 0\n+#define SHORT_MAX  32767\n+#define SHORT_MIN -32767\n+#define UNSIGNED_SHORT_MAX 65535\n+\n+using namespace X265_NS;\n+\n+extern const char* lumaPartStr[NUM_PU_SIZES];\n+extern const char* const* chromaPartStr[X265_CSP_COUNT];\n+\n+class TestHarness\n+{\n+public:\n+\n+    TestHarness() {}\n+\n+    virtual ~TestHarness() {}\n+\n+    virtual bool testCorrectness(const EncoderPrimitives& ref, const EncoderPrimitives& opt) = 0;\n+\n+    virtual void measureSpeed(const EncoderPrimitives& ref, const EncoderPrimitives& opt) = 0;\n+\n+    virtual const char *getName() const = 0;\n+\n+protected:\n+\n+    /* Temporary variables for stack checks */\n+    int      m_ok;\n+\n+    uint64_t m_rand;\n+};\n+\n+#ifdef _MSC_VER\n+#include <intrin.h>\n+#elif HAVE_RDTSC\n+#include <intrin.h>\n+#elif (!defined(__APPLE__) && (defined (__GNUC__) && (defined(__x86_64__) || defined(__i386__))))\n+#include <x86intrin.h>\n+#elif ( !defined(__APPLE__) && defined (__GNUC__) && defined(__ARM_NEON__))\n+#include <arm_neon.h>\n+#elif defined(__GNUC__) && (!defined(__clang__) || __clang_major__ < 4)\n+/* fallback for older GCC/MinGW */\n+static inline uint32_t __rdtsc(void)\n+{\n+    uint32_t a = 0;\n+\n+#if X265_ARCH_X86\n+    asm volatile(\"rdtsc\" : \"=a\" (a) ::\"edx\");\n+#elif X265_ARCH_ARM\n+#if X265_ARCH_ARM64\n+    asm volatile(\"mrs %0, cntvct_el0\" : \"=r\"(a));\n+#else\n+    // TOD-DO: verify following inline asm to get cpu Timestamp Counter for ARM arch\n+    // asm volatile(\"mrc p15, 0, %0, c9, c13, 0\" : \"=r\"(a));\n+\n+    // TO-DO: replace clock() function with appropriate ARM cpu instructions\n+    a = clock();\n+#endif\n+#endif\n+    return a;\n+}\n+#endif // ifdef _MSC_VER\n+\n+#define BENCH_RUNS 2000\n+\n+/* Adapted from checkasm.c, runs each optimized primitive four times, measures rdtsc\n+ * and discards invalid times. Repeats BENCH_RUNS times to get a good average.\n+ * Then measures the C reference with BENCH_RUNS / 4 runs and reports X factor and average cycles.*/\n+#define REPORT_SPEEDUP(RUNOPT, RUNREF, ...) \\\n+    { \\\n+        uint32_t cycles = 0; int runs = 0; \\\n+        RUNOPT(__VA_ARGS__); \\\n+        for (int ti = 0; ti < BENCH_RUNS; ti++) { \\\n+            uint32_t t0 = (uint32_t)__rdtsc(); \\\n+            RUNOPT(__VA_ARGS__); \\\n+            RUNOPT(__VA_ARGS__); \\\n+            RUNOPT(__VA_ARGS__); \\\n+            RUNOPT(__VA_ARGS__); \\\n+            uint32_t t1 = (uint32_t)__rdtsc() - t0; \\\n+            if (t1 * runs <= cycles * 4 && ti > 0) { cycles += t1; runs++; } \\\n+        } \\\n+        uint32_t refcycles = 0; int refruns = 0; \\\n+        RUNREF(__VA_ARGS__); \\\n+        for (int ti = 0; ti < BENCH_RUNS / 4; ti++) { \\\n+            uint32_t t0 = (uint32_t)__rdtsc(); \\\n+            RUNREF(__VA_ARGS__); \\\n+            RUNREF(__VA_ARGS__); \\\n+            RUNREF(__VA_ARGS__); \\\n+            RUNREF(__VA_ARGS__); \\\n+            uint32_t t1 = (uint32_t)__rdtsc() - t0; \\\n+            if (t1 * refruns <= refcycles * 4 && ti > 0) { refcycles += t1; refruns++; } \\\n+        } \\\n+        x265_emms(); \\\n+        float optperf = (10.0f * cycles / runs) / 4; \\\n+        float refperf = (10.0f * refcycles / refruns) / 4; \\\n+        printf(\"\\t%3.2fx \", refperf / optperf); \\\n+        printf(\"\\t %-8.2lf \\t %-8.2lf\\n\", optperf, refperf); \\\n+    }\n+\n+extern \"C\" {\n+#if X265_ARCH_X86\n+int PFX(stack_pagealign)(int (*func)(), int align);\n+\n+/* detect when callee-saved regs aren't saved\n+ * needs an explicit asm check because it only sometimes crashes in normal use. */\n+intptr_t PFX(checkasm_call)(intptr_t (*func)(), int *ok, ...);\n+float PFX(checkasm_call_float)(float (*func)(), int *ok, ...);\n+#elif X265_ARCH_ARM == 0\n+#define PFX(stack_pagealign)(func, align) func()\n+#endif\n+\n+#if X86_64\n+\n+/* Evil hack: detect incorrect assumptions that 32-bit ints are zero-extended to 64-bit.\n+ * This is done by clobbering the stack with junk around the stack pointer and calling the\n+ * assembly function through x265_checkasm_call with added dummy arguments which forces all\n+ * real arguments to be passed on the stack and not in registers. For 32-bit argument the\n+ * upper half of the 64-bit register location on the stack will now contain junk. Note that\n+ * this is dependent on compiler behavior and that interrupts etc. at the wrong time may\n+ * overwrite the junk written to the stack so there's no guarantee that it will always\n+ * detect all functions that assumes zero-extension.\n+ */\n+void PFX(checkasm_stack_clobber)(uint64_t clobber, ...);\n+#define checked(func, ...) ( \\\n+        m_ok = 1, m_rand = (rand() & 0xffff) * 0x0001000100010001ULL, \\\n+        PFX(checkasm_stack_clobber)(m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, \\\n+                                    m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, \\\n+                                    m_rand, m_rand, m_rand, m_rand, m_rand), /* max_args+6 */ \\\n+        PFX(checkasm_call)((intptr_t(*)())func, &m_ok, 0, 0, 0, 0, __VA_ARGS__))\n+\n+#define checked_float(func, ...) ( \\\n+        m_ok = 1, m_rand = (rand() & 0xffff) * 0x0001000100010001ULL, \\\n+        PFX(checkasm_stack_clobber)(m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, \\\n+                                    m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, m_rand, \\\n+                                    m_rand, m_rand, m_rand, m_rand, m_rand), /* max_args+6 */ \\\n+        PFX(checkasm_call_float)((float(*)())func, &m_ok, 0, 0, 0, 0, __VA_ARGS__))\n+#define reportfail() if (!m_ok) { fflush(stdout); fprintf(stderr, \"stack clobber check failed at %s:%d\", __FILE__, __LINE__); abort(); }\n+#elif ARCH_X86\n+#define checked(func, ...) PFX(checkasm_call)((intptr_t(*)())func, &m_ok, __VA_ARGS__);\n+#define checked_float(func, ...) PFX(checkasm_call_float)((float(*)())func, &m_ok, __VA_ARGS__);\n+\n+#else // if X86_64\n+#define checked(func, ...) func(__VA_ARGS__)\n+#define checked_float(func, ...) func(__VA_ARGS__)\n+#define reportfail()\n+#endif // if X86_64\n+}\n+\n+#endif // ifndef _TESTHARNESS_H_\n"
  },
  {
    "path": ".ci/apple_libvorbis_cpusubtype.patch",
    "content": "--- configure.orig\t2024-10-09 23:11:57\n+++ configure\t2024-10-09 23:12:43\n@@ -12840,9 +12840,9 @@\n \t\tCFLAGS=\"-O3 -Wall -Wextra -ffast-math -D__NO_MATH_INLINES -fsigned-char $sparc_cpu\"\n \t\tPROFILE=\"-pg -g -O3 -D__NO_MATH_INLINES -fsigned-char $sparc_cpu\" ;;\n \t*-*-darwin*)\n-\t\tDEBUG=\"-DDARWIN -fno-common -force_cpusubtype_ALL -Wall -g -O0 -fsigned-char\"\n-\t\tCFLAGS=\"-DDARWIN -fno-common -force_cpusubtype_ALL -Wall -g -O3 -ffast-math -fsigned-char\"\n-\t\tPROFILE=\"-DDARWIN -fno-common -force_cpusubtype_ALL -Wall -g -pg -O3 -ffast-math -fsigned-char\";;\n+\t\tDEBUG=\"-DDARWIN -fno-common -Wall -g -O0 -fsigned-char\"\n+\t\tCFLAGS=\"-DDARWIN -fno-common -Wall -g -O3 -ffast-math -fsigned-char\"\n+\t\tPROFILE=\"-DDARWIN -fno-common -Wall -g -pg -O3 -ffast-math -fsigned-char\";;\n \t*-*-os2*)\n \t\t# Use -W instead of -Wextra because gcc on OS/2 is an old version.\n \t\tDEBUG=\"-g -Wall -W -D_REENTRANT -D__NO_MATH_INLINES -fsigned-char\""
  },
  {
    "path": ".ci/build-wheels.sh",
    "content": "#!/bin/bash\nset -e -x\n\n# no permissions in that dir\nsource /io/.ci/yum_deps.sh\nsource /io/.ci/dep_versions.sh\n\nBUILD_DIR=\"$HOME/ffmpeg_build\"\nexport LD_LIBRARY_PATH=\"$BUILD_DIR/lib:$LD_LIBRARY_PATH\"\nexport PATH=\"$BUILD_DIR/bin:$PATH\"\nexport PKG_CONFIG_PATH=\"$BUILD_DIR/lib/pkgconfig:$BUILD_DIR/lib64/pkgconfig:/usr/lib/pkgconfig/\"\n\nmkdir ~/ffmpeg_sources\n\n\ncd ~/ffmpeg_sources;\ncurl -sLO \"https://github.com/libsdl-org/SDL/releases/download/release-$SDL_VERSION/SDL2-$SDL_VERSION.tar.gz\"\ntar xzf \"SDL2-$SDL_VERSION.tar.gz\"\ncd \"SDL2-$SDL_VERSION\"\n./configure --prefix=\"$BUILD_DIR\" --bindir=\"$BUILD_DIR/bin\";\nmake;\nmake install;\nmake distclean;\n\ncd ~/ffmpeg_sources;\ncurl -sLO \"https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz\"\ntar xzf \"openssl-$OPENSSL_VERSION.tar.gz\"\ncd \"openssl-$OPENSSL_VERSION\"\n./config -fpic shared --prefix=\"$BUILD_DIR\";\nmake;\nmake install;\n\ncd ~/ffmpeg_sources;\ncurl -sLO \"http://www.tortall.net/projects/yasm/releases/yasm-$YASM_VERSION.tar.gz\"\ntar xzf \"yasm-$YASM_VERSION.tar.gz\"\ncd \"yasm-$YASM_VERSION\"\n./configure --prefix=\"$BUILD_DIR\" --bindir=\"$BUILD_DIR/bin\";\nmake;\nmake install;\nmake distclean;\n\ncd ~/ffmpeg_sources;\ncurl -sLO \"http://www.nasm.us/pub/nasm/releasebuilds/$NASM_VERSION/nasm-$NASM_VERSION.tar.gz\"\ntar -xvzf \"nasm-$NASM_VERSION.tar.gz\"\ncd \"nasm-$NASM_VERSION\"\n./configure --prefix=\"$BUILD_DIR\" --bindir=\"$BUILD_DIR/bin\";\nmake;\nmake install;\nmake distclean;\n\ncd ~/ffmpeg_sources;\ngit clone --depth 1 --branch stable https://code.videolan.org/videolan/x264.git\ncd x264\n./configure --prefix=\"$BUILD_DIR\" --bindir=\"$BUILD_DIR/bin\" --enable-shared --extra-cflags=\"-fPIC\";\nmake;\nmake install;\nmake distclean;\n\ncd ~/ffmpeg_sources;\ncurl -kLO \"https://cfhcable.dl.sourceforge.net/project/lame/lame/$LAME_VERSION/lame-$LAME_VERSION.tar.gz\"\ntar xzf \"lame-$LAME_VERSION.tar.gz\"\ncd \"lame-$LAME_VERSION\"\n./configure --prefix=\"$BUILD_DIR\" --enable-nasm --enable-shared;\nmake;\nmake install;\nmake distclean;\n\ncd ~/ffmpeg_sources\ncurl -sLO \"https://github.com/fribidi/fribidi/releases/download/v$FRIBIDI_VERSION/fribidi-$FRIBIDI_VERSION.tar.xz\"\ntar xf \"fribidi-$FRIBIDI_VERSION.tar.xz\"\ncd \"fribidi-$FRIBIDI_VERSION\"\n./configure --prefix=\"$BUILD_DIR\" --enable-shared;\nmake\nmake install\n\ncd ~/ffmpeg_sources\ncurl -sLO \"https://github.com/libass/libass/releases/download/$LIBASS_VERSION/libass-$LIBASS_VERSION.tar.gz\"\ntar xzf \"libass-$LIBASS_VERSION.tar.gz\"\ncd \"libass-$LIBASS_VERSION\"\n./configure --prefix=\"$BUILD_DIR\" --enable-shared --disable-require-system-font-provider;\nmake\nmake install\n\ncd ~/ffmpeg_sources\ncurl -sLO \"https://bitbucket.org/multicoreware/x265_git/downloads/x265_$X265_VERSION.tar.gz\"\ntar xzf \"x265_$X265_VERSION.tar.gz\"\ncd x265_*/\n# Backport patches to fix build on cmake >4.0.0\npatch -p1 < /io/.ci/x265_b354c009a60bcd6d7fc04014e200a1ee9c45c167.patch\npatch -p1 < /io/.ci/x265_51ae8e922bcc4586ad4710812072289af91492a8.patch\ncd build/linux\ncmake -G \"Unix Makefiles\" -DCMAKE_INSTALL_PREFIX=\"$BUILD_DIR\" -DENABLE_SHARED:bool=on ../../source\nmake\nmake install\n\ncd ~/ffmpeg_sources\ngit clone --depth 1 --branch \"v$FDK_VERSION\" https://github.com/mstorsjo/fdk-aac.git\ncd fdk-aac\ngit apply /io/.ci/fdk.patch\nautoreconf -fiv\n./configure --prefix=\"$BUILD_DIR\" --enable-shared\nmake\nmake install\n\ncd ~/ffmpeg_sources\ncurl -LO \"https://archive.mozilla.org/pub/opus/opus-$OPUS_VERSION.tar.gz\"\ntar xzvf \"opus-$OPUS_VERSION.tar.gz\"\ncd \"opus-$OPUS_VERSION\"\n./configure --prefix=\"$BUILD_DIR\" --enable-shared\nmake\nmake install\n\ncd ~/ffmpeg_sources\ncurl -LO \"http://downloads.xiph.org/releases/ogg/libogg-$LIBOGG_VERSION.tar.gz\"\ntar xzvf \"libogg-$LIBOGG_VERSION.tar.gz\"\ncd \"libogg-$LIBOGG_VERSION\"\n./configure --prefix=\"$BUILD_DIR\" --enable-shared\nmake\nmake install\n\ncd ~/ffmpeg_sources;\ncurl -LO \"http://downloads.xiph.org/releases/theora/libtheora-$LIBTHEORA_VERSION.tar.gz\"\ntar xzvf \"libtheora-$LIBTHEORA_VERSION.tar.gz\"\ncd \"libtheora-$LIBTHEORA_VERSION\"\n./configure --prefix=\"$BUILD_DIR\" --enable-shared;\nmake;\nmake install\n\ncd ~/ffmpeg_sources\ncurl -LO \"http://downloads.xiph.org/releases/vorbis/libvorbis-$LIBVORBIS_VERSION.tar.gz\"\ntar xzvf \"libvorbis-$LIBVORBIS_VERSION.tar.gz\"\ncd \"libvorbis-$LIBVORBIS_VERSION\"\n./configure --prefix=\"$BUILD_DIR\" --with-ogg=\"$BUILD_DIR\" --enable-shared\nmake\nmake install\n\ncd ~/ffmpeg_sources\ngit clone --depth 1 --branch \"v$LIBVPX_VERSION\" https://chromium.googlesource.com/webm/libvpx.git\ncd libvpx\n./configure --prefix=\"$BUILD_DIR\" --disable-examples  --as=yasm --enable-shared --disable-unit-tests\nmake\nmake install\n\ncd ~/ffmpeg_sources;\ncurl -sLO http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2;\ntar xjf ffmpeg-$FFMPEG_VERSION.tar.bz2;\ncd ffmpeg-$FFMPEG_VERSION;\n./configure --prefix=\"$BUILD_DIR\" --extra-cflags=\"-I$BUILD_DIR/include -fPIC\" --extra-ldflags=\"-L$BUILD_DIR/lib\" --bindir=\"$BUILD_DIR/bin\" --enable-gpl --enable-version3 --enable-libmp3lame --enable-libx264 --enable-libx265 --enable-libfdk_aac --enable-nonfree --enable-libass --enable-libvorbis --enable-libtheora --enable-libfreetype --enable-libopus --enable-libvpx --enable-openssl --enable-shared\nmake;\nmake install;\n\ncp -r \"$BUILD_DIR\" \"/io/ffmpeg_build\"\n"
  },
  {
    "path": ".ci/build_wheels_osx.sh",
    "content": "#!/bin/bash\nset -e -x\n\n# can be either arm64 or x86_64\nARCH=\"$1\"\nSRC_PATH=\"$HOME/ffmpeg_sources_$ARCH\"\nBUILD_PATH=\"$HOME/${FFMPEG_BUILD_PATH}_$ARCH\"\nbase_dir=\"$(pwd)\"\n\nsource \"$base_dir/.ci/dep_versions.sh\"\n\nexport LD_LIBRARY_PATH=\"$BUILD_PATH/lib:$LD_LIBRARY_PATH\"\nexport PATH=\"$BUILD_PATH/bin:/usr/local/bin/:$PATH\"\nexport PKG_CONFIG_PATH=\"$BUILD_PATH/lib/pkgconfig:/usr/lib/pkgconfig/:$PKG_CONFIG_PATH\"\nexport CC=\"/usr/bin/clang\"\nexport CXX=\"/usr/bin/clang\"\nexport MACOSX_DEPLOYMENT_TARGET=10.13\n\nif [ \"$ARCH\" = \"x86_64\" ]; then\n  ARCH2=x86_64\nelse\n  ARCH2=aarch64\n  export CFLAGS=\"-arch arm64\"\n  export CXXFLAGS=\"-arch arm64\"\nfi\n\n\nbrew install automake meson pkg-config cmake\nbrew install --cask xquartz\nmkdir \"$SRC_PATH\"\n\n\ncd \"$SRC_PATH\"\ncurl -sLO \"https://tukaani.org/xz/xz-$XZ_VERSION.tar.gz\"\ntar xzf \"xz-$XZ_VERSION.tar.gz\"\ncd \"xz-$XZ_VERSION\"\n./configure --prefix=\"$BUILD_PATH\" --host=$ARCH2-darwin\nmake\nmake install\n\n\ncd \"$SRC_PATH\"\ncurl -sLO \"https://zlib.net/fossils/zlib-$ZLIB_VERSION.tar.gz\"\ntar xzf \"zlib-$ZLIB_VERSION.tar.gz\"\ncd \"zlib-$ZLIB_VERSION\"\n./configure --prefix=\"$BUILD_PATH\"\nmake\nmake install\n\n\ncd \"$SRC_PATH\";\ncurl -sLO \"https://github.com/libsdl-org/SDL/releases/download/release-$SDL_VERSION/SDL2-$SDL_VERSION.tar.gz\"\ntar xzf \"SDL2-$SDL_VERSION.tar.gz\"\ncd \"SDL2-$SDL_VERSION\"\nCPPFLAGS=\"$CXXFLAGS\" LDFLAGS=\"$CFLAGS\" ./configure --prefix=\"$BUILD_PATH\" --bindir=\"$BUILD_PATH/bin\" --host=$ARCH2-darwin\nmake\nmake install\nmake distclean\n\n\ncd \"$SRC_PATH\"\ncurl -sLO \"https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz\"\ntar xzf \"openssl-$OPENSSL_VERSION.tar.gz\"\ncd \"openssl-$OPENSSL_VERSION\"\n./configure darwin64-$ARCH-cc -fPIC shared --prefix=\"$BUILD_PATH\"\nmake\nmake install\n\n\ncd \"$SRC_PATH\"\ncurl -sLO \"https://github.com/glennrp/libpng/archive/refs/tags/v$LIBPNG_VERSION.tar.gz\"\ntar xzf \"v$LIBPNG_VERSION.tar.gz\"\ncd \"libpng-$LIBPNG_VERSION\"\n./configure --prefix=\"$BUILD_PATH\" --bindir=\"$BUILD_PATH/bin\" --host=$ARCH2-darwin\nmake\nmake install\n\n\ncd \"$SRC_PATH\"\ncurl -sLO \"https://github.com/google/brotli/archive/refs/tags/v$BROTLI_VERSION.tar.gz\"\ntar xzf \"v$BROTLI_VERSION.tar.gz\"\ncd \"brotli-$BROTLI_VERSION\"\nmkdir out\ncd out\ncmake -DCMAKE_INSTALL_PREFIX=\"$BUILD_PATH\" -DCMAKE_OSX_ARCHITECTURES=\"$ARCH\" -DCMAKE_BUILD_TYPE=Release -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ..\ncmake --build . --config Release --target install\n\n\nif [ \"$ARCH\" = \"x86_64\" ]; then\n cd \"$SRC_PATH\"\n curl -sLO \"http://www.tortall.net/projects/yasm/releases/yasm-$YASM_VERSION.tar.gz\"\n tar xzf \"yasm-$YASM_VERSION.tar.gz\"\n cd \"yasm-$YASM_VERSION\"\n ./configure --prefix=\"$BUILD_PATH\" --bindir=\"$BUILD_PATH/bin\"\n make\n make install\n make distclean\n\n cd \"$SRC_PATH\"\n curl -sLO \"http://www.nasm.us/pub/nasm/releasebuilds/$NASM_VERSION/nasm-$NASM_VERSION.tar.gz\"\n tar -xvzf \"nasm-$NASM_VERSION.tar.gz\"\n cd \"nasm-$NASM_VERSION\"\n ./configure --prefix=\"$BUILD_PATH\" --bindir=\"$BUILD_PATH/bin\"\n make\n make install\n make distclean\n\nfi\n\n\narg=()\nif [ \"$ARCH\" = \"arm64\" ]; then\n    arg=(\"--disable-asm\")\nfi\ncd \"$SRC_PATH\"\ngit clone --depth 1 --branch stable https://code.videolan.org/videolan/x264.git\ncd x264\n./configure --prefix=\"$BUILD_PATH\" --bindir=\"$BUILD_PATH/bin\" --enable-shared --extra-cflags=\"-fPIC\" \\\n  \"${arg[@]}\" --host=$ARCH2-darwin\nmake\nmake install\nmake distclean\n\n\narg=()\nif [ \"$ARCH\" = \"x86_64\" ]; then\n  arg=(\"--enable-nasm\")\nfi\ncd \"$SRC_PATH\";\ncurl -kLO \"https://cfhcable.dl.sourceforge.net/project/lame/lame/$LAME_VERSION/lame-$LAME_VERSION.tar.gz\"\ntar xzf \"lame-$LAME_VERSION.tar.gz\"\ncd \"lame-$LAME_VERSION\"\ngit apply \"$base_dir/.ci/libmp3lame-symbols.patch\"\n./configure --prefix=\"$BUILD_PATH\" --enable-shared \"${arg[@]}\" --host=$ARCH2-darwin\nmake\nmake install\nmake distclean\n\n\ncd \"$SRC_PATH\"\ncurl -sLO \"https://github.com/fribidi/fribidi/releases/download/v$FRIBIDI_VERSION/fribidi-$FRIBIDI_VERSION.tar.xz\"\ntar xf \"fribidi-$FRIBIDI_VERSION.tar.xz\"\ncd \"fribidi-$FRIBIDI_VERSION\"\n./configure --prefix=\"$BUILD_PATH\" --enable-shared --host=$ARCH2-darwin\nmake\nmake install\n\n\ncd \"$SRC_PATH\"\ncurl -sLO \"https://download.savannah.gnu.org/releases/freetype/freetype-$FREETYPE_VERSION.tar.xz\"\ntar xf \"freetype-$FREETYPE_VERSION.tar.xz\"\ncd \"freetype-$FREETYPE_VERSION\"\n./configure --prefix=\"$BUILD_PATH\" --enable-shared --host=$ARCH2-darwin --with-harfbuzz=no\nmake\nmake install\n\n\ncd \"$SRC_PATH\"\ncurl -sLO \"https://github.com/harfbuzz/harfbuzz/releases/download/$HARFBUZZ_VERSION/harfbuzz-$HARFBUZZ_VERSION.tar.xz\"\ntar xf \"harfbuzz-$HARFBUZZ_VERSION.tar.xz\"\ncd \"harfbuzz-$HARFBUZZ_VERSION\"\n\n\nif [ \"$ARCH\" = \"arm64\" ]; then\n  cat <<EOT > cross_file.txt\n[host_machine]\nsystem = 'darwin'\ncpu_family = 'aarch64'\ncpu = 'arm64'\nendian = 'little'\n[binaries]\npkgconfig = '/usr/local/bin/pkg-config'\nEOT\n\n  LDFLAGS=\"-arch arm64\" meson build --prefix=\"$BUILD_PATH\" -Dglib=disabled -Dgobject=disabled -Dcairo=disabled \\\n    -Dfreetype=enabled -Ddocs=disabled -Dtests=disabled -Dintrospection=disabled -Dbenchmark=disabled \\\n    --cross-file cross_file.txt -Dc_args=\"-arch arm64\" -Dc_link_args=\"-arch arm64\" -Dcpp_args=\"-arch arm64\" \\\n    -Dcpp_link_args=\"-arch arm64\"\n\tLDFLAGS=\"-arch arm64\" meson compile -C build\nelse\n  meson build --prefix=\"$BUILD_PATH\" -Dglib=disabled -Dgobject=disabled -Dcairo=disabled -Dfreetype=enabled \\\n    -Ddocs=disabled -Dtests=disabled -Dintrospection=disabled -Dbenchmark=disabled\n\tmeson compile -C build\nfi\nmeson install -C build\n\n\ncd \"$SRC_PATH\"\ncurl -sLO \"https://github.com/libass/libass/releases/download/$LIBASS_VERSION/libass-$LIBASS_VERSION.tar.gz\"\ntar xzf \"libass-$LIBASS_VERSION.tar.gz\"\ncd \"libass-$LIBASS_VERSION\"\n./configure --prefix=\"$BUILD_PATH\" --enable-shared --disable-fontconfig --host=$ARCH2-darwin\nmake\nmake install\n\n\ncd \"$SRC_PATH\"\ngit clone https://bitbucket.org/multicoreware/x265_git.git --depth 1 --branch \"Release_$X265_VERSION\"\ncd x265_git\n# Backport patches to fix build on cmake >4.0.0\npatch -p1 < \"$base_dir/.ci/x265_b354c009a60bcd6d7fc04014e200a1ee9c45c167.patch\"\npatch -p1 < \"$base_dir/.ci/x265_51ae8e922bcc4586ad4710812072289af91492a8.patch\"\nif [ \"$ARCH\" = \"arm64\" ]; then\n  patch -p1 < \"$base_dir/.ci/apple_arm64_x265.patch\"\n  cd source\n  sed -i \"\" \"s/^if(X265_LATEST_TAG)$/if(1)/g\" CMakeLists.txt\n  CXX= LDFLAGS=\"-arch arm64\" cmake -G \"Unix Makefiles\" -DCMAKE_INSTALL_PREFIX=\"$BUILD_PATH\" -DENABLE_SHARED:bool=on \\\n    -DCMAKE_OSX_ARCHITECTURES=arm64 -DCROSS_COMPILE_ARM64:bool=on -DCMAKE_HOST_SYSTEM_PROCESSOR=aarch64 \\\n    -DCMAKE_APPLE_SILICON_PROCESSOR=aarch64 .\n  CXX= LDFLAGS=\"-arch arm64\" make\nelse\n  cd source\n  sed -i \"\" \"s/^if(X265_LATEST_TAG)$/if(1)/g\" CMakeLists.txt\n  CXX= cmake -G \"Unix Makefiles\" -DCMAKE_INSTALL_PREFIX=\"$BUILD_PATH\" -DENABLE_SHARED:bool=on .\n  CXX= make\nfi\nmake install\n\n\ncd \"$SRC_PATH\"\ngit clone --depth 1 --branch \"v$FDK_VERSION\" https://github.com/mstorsjo/fdk-aac.git\ncd fdk-aac\ngit apply \"$base_dir/.ci/fdk.patch\"\ncmake -DCMAKE_INSTALL_PREFIX=\"$BUILD_PATH\" -DENABLE_SHARED:bool=on -DCMAKE_OSX_ARCHITECTURES=\"$ARCH\" .\nmake\nmake install\n\n\ncd \"$SRC_PATH\"\ncurl -LO \"https://archive.mozilla.org/pub/opus/opus-$OPUS_VERSION.tar.gz\"\ntar xzvf \"opus-$OPUS_VERSION.tar.gz\"\ncd \"opus-$OPUS_VERSION\"\n./configure --prefix=\"$BUILD_PATH\" --enable-shared --host=$ARCH2-darwin\nmake\nmake install\n\n\ncd \"$SRC_PATH\"\ncurl -LO \"http://downloads.xiph.org/releases/ogg/libogg-$LIBOGG_VERSION.tar.gz\"\ntar xzvf \"libogg-$LIBOGG_VERSION.tar.gz\"\ncd \"libogg-$LIBOGG_VERSION\"\n./configure --prefix=\"$BUILD_PATH\" --enable-shared --host=$ARCH2-darwin\nmake\nmake install\n\n\ncd \"$SRC_PATH\"\ncurl -LO \"http://downloads.xiph.org/releases/vorbis/libvorbis-$LIBVORBIS_VERSION.tar.gz\"\ntar xzvf \"libvorbis-$LIBVORBIS_VERSION.tar.gz\"\ncd \"libvorbis-$LIBVORBIS_VERSION\"\npatch -p1 < \"$base_dir/.ci/apple_libvorbis_cpusubtype.patch\"\n./configure --prefix=\"$BUILD_PATH\" --with-ogg=\"$BUILD_PATH\" --enable-shared --host=$ARCH2-darwin\nmake\nmake install\n\n\ncd \"$SRC_PATH\";\ncurl -LO \"http://downloads.xiph.org/releases/theora/libtheora-$LIBTHEORA_VERSION.tar.gz\"\ntar xzvf \"libtheora-$LIBTHEORA_VERSION.tar.gz\"\ncd \"libtheora-$LIBTHEORA_VERSION\"\n# https://bugs.gentoo.org/465450\nsed -i \"\" 's/png_\\(sizeof\\)/\\1/g' examples/png2theora.c\nTHEORA_ARCH=$ARCH2\n./configure --prefix=\"$BUILD_PATH\" --enable-shared --host=$THEORA_ARCH-apple-darwin\nmake\nmake install\n\n\ncd \"$SRC_PATH\"\ngit clone --depth 1 --branch \"v$LIBVPX_VERSION\" https://chromium.googlesource.com/webm/libvpx.git\ncd libvpx\nsed -i.original -e 's/-march=armv8-a//g' build/make/configure.sh\n\nif [ \"$ARCH\" = \"x86_64\" ]; then\n    arg=(\"--as=yasm\")\n    LDFLAGS_VPX=\"$LDFLAGS\"\nelse\n    arg=(\"--target=$ARCH-darwin20-gcc\")\n    LDFLAGS_VPX=\"$LDFLAGS -arch arm64\"\nfi\nCXX= CC= LDFLAGS=\"$LDFLAGS_VPX\" ./configure --prefix=\"$BUILD_PATH\" --disable-examples --enable-vp9-highbitdepth --enable-vp8 --enable-vp9 --enable-pic \\\n  --enable-postproc --enable-multithread \"${arg[@]}\" --enable-shared --disable-unit-tests\nCXX= CC= make\nmake install\n\n\ncd \"$SRC_PATH\"\ncurl -sLO \"http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2\"\ntar xjf \"ffmpeg-$FFMPEG_VERSION.tar.bz2\"\ncd \"ffmpeg-$FFMPEG_VERSION\"\n\nif [ \"$ARCH\" = \"x86_64\" ]; then\n    arg=(\"--extra-ldflags=-L$BUILD_PATH/lib\")\nelse\n    arg=(\"--enable-cross-compile\" \"--arch=arm64\" \"--target-os=darwin\" \"--extra-ldflags=-L$BUILD_PATH/lib -arch arm64\" \\\n      \"--extra-objcflags=-arch arm64\")\nfi\n\n./configure --prefix=\"$BUILD_PATH\" --extra-cflags=\"$CFLAGS\" --extra-cxxflags=\"$CXXFLAGS\" --bindir=\"$BUILD_PATH/bin\" \\\n  --enable-gpl --enable-libmp3lame --enable-libx264 --enable-libx265 --enable-libfdk_aac --enable-nonfree \\\n  --enable-libass --enable-libvorbis --enable-libtheora --enable-libfreetype --enable-libopus --enable-libvpx \\\n  --enable-openssl --enable-shared --pkg-config-flags=\"--static\" --disable-libxcb --disable-libxcb-shm \\\n  --disable-libxcb-xfixes --disable-libxcb-shape --disable-xlib \"${arg[@]}\"\nmake\nmake install\nmake distclean\n\n\nfile \"$BUILD_PATH\"/lib/*\nfile \"$BUILD_PATH\"/bin/*\nfind \"$BUILD_PATH\"\n"
  },
  {
    "path": ".ci/dep_versions.sh",
    "content": "# FFMPEG_VERSION and SDL_VERSION are also set in the actions yaml\n\nexport FFMPEG_VERSION=6.0  # https://ffmpeg.org/releases/\nexport SDL_VERSION=2.26.4  # https://github.com/libsdl-org/SDL/releases\nexport SDL_MIXER_VERSION=2.6.3  # https://github.com/libsdl-org/SDL_mixer/releases\nexport OPENSSL_VERSION=3.0.8  # https://www.openssl.org/source\nexport YASM_VERSION=1.3.0  # http://www.tortall.net/projects/yasm/releases\nexport NASM_VERSION=2.16.01  # https://www.nasm.us/pub/nasm/releasebuilds/\nexport LAME_VERSION=3.100  # https://sourceforge.net/projects/lame/files/lame/\nexport FRIBIDI_VERSION=1.0.12  # https://github.com/fribidi/fribidi/releases\nexport LIBASS_VERSION=0.17.0  # https://github.com/libass/libass/releases\nexport X265_VERSION=3.5  # https://bitbucket.org/multicoreware/x265_git/downloads\nexport FDK_VERSION=2.0.2  # https://github.com/mstorsjo/fdk-aac\nexport OPUS_VERSION=1.3.1  # https://archive.mozilla.org/pub/opus/\nexport LIBOGG_VERSION=1.3.5  # http://downloads.xiph.org/releases/ogg/\nexport LIBTHEORA_VERSION=1.2.0  # https://ftp.osuosl.org/pub/xiph/releases/theora/\nexport LIBVORBIS_VERSION=1.3.7  # http://downloads.xiph.org/releases/vorbis\nexport LIBVPX_VERSION=1.14.1  # https://chromium.googlesource.com/webm/libvpx\nexport XZ_VERSION=5.4.1  # https://tukaani.org/xz/\nexport ZLIB_VERSION=1.2.13  # https://zlib.net/\nexport LIBPNG_VERSION=1.6.39  # https://github.com/glennrp/libpng/tags\nexport BROTLI_VERSION=1.0.9  # https://github.com/google/brotli/tags\nexport FREETYPE_VERSION=2.12.1  # https://download.savannah.gnu.org/releases/freetype/\nexport HARFBUZZ_VERSION=6.0.0  # https://github.com/harfbuzz/harfbuzz/releases\n"
  },
  {
    "path": ".ci/fdk.patch",
    "content": "diff --git a/Makefile.am b/Makefile.am\nindex 5b2c65b..728c72a 100644\n--- a/Makefile.am\n+++ b/Makefile.am\n@@ -13,7 +13,7 @@ AM_CPPFLAGS = \\\n     -I$(top_srcdir)/libPCMutils/include\n \n AM_CXXFLAGS = -fno-exceptions -fno-rtti\n-libfdk_aac_la_LINK = $(LINK) $(libfdk_aac_la_LDFLAGS)\n+#libfdk_aac_la_LINK = $(LINK) $(libfdk_aac_la_LDFLAGS)\n # Mention a dummy pure C file to trigger generation of the $(LINK) variable\n nodist_EXTRA_libfdk_aac_la_SOURCES = dummy.c\n \ndiff --git a/configure.ac b/configure.ac\nindex 1485ff7..4bec7a7 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -19,7 +19,11 @@ AM_CONDITIONAL(EXAMPLE, test x$example = xyes)\n dnl Checks for programs.\n AC_PROG_CC\n AC_PROG_CXX\n-LT_INIT\n+\n+AM_PROG_CC_C_O\n+\n+AC_PROG_LIBTOOL\n+AC_SUBST(LIBTOOL_DEPS)\n \n AC_SEARCH_LIBS([sin], [m])\n \n"
  },
  {
    "path": ".ci/libmp3lame-symbols.patch",
    "content": "--- lame-3.100/include/libmp3lame.sym\t2017-09-06 14:33:35.000000000 -0500\n+++ lame-3.100/include/libmp3lame.sym\t2017-10-22 16:18:44.708436200 -0500\n@@ -1,5 +1,4 @@\n lame_init\n-lame_init_old\n lame_set_num_samples\n lame_get_num_samples\n lame_set_in_samplerate\n@@ -188,6 +187,7 @@ hip_decode_exit\n hip_set_errorf\n hip_set_debugf\n hip_set_msgf\n+hip_set_pinfo\n hip_decode\n hip_decode_headers\n hip_decode1\n"
  },
  {
    "path": ".ci/merge_osx_deps.sh",
    "content": "#!/bin/bash\n\nset -e -x\n\npy_osx_ver=$(echo ${MACOSX_DEPLOYMENT_TARGET} | sed \"s/\\./_/g\")\npy_osx_ver_arm=$(echo ${MACOSX_DEPLOYMENT_TARGET_ARM} | sed \"s/\\./_/g\")\nfor whl in *.whl; do\n   if [[ \"$whl\" == *macosx_${py_osx_ver}_x86_64.whl ]]; then\n       whl_base=$(echo \"$whl\" | rev | cut -c 24- | rev)\n       if [[ -f \"${whl_base}macosx_${py_osx_ver_arm}_arm64.whl\" ]]; then\n           delocate-merge \"$whl\" \"${whl_base}macosx_${py_osx_ver_arm}_arm64.whl\"\n       fi\n   fi\ndone\n"
  },
  {
    "path": ".ci/x265_51ae8e922bcc4586ad4710812072289af91492a8.patch",
    "content": "From 51ae8e922bcc4586ad4710812072289af91492a8 Mon Sep 17 00:00:00 2001\nFrom: yaswanthsastry <yaswanth.sastry@multicorewareinc.com>\nDate: Mon, 7 Apr 2025 11:27:36 +0530\nSubject: [PATCH] Fix for CMake Build Errors in MacOS\n\n---\n source/CMakeLists.txt | 15 +++++++--------\n 1 file changed, 7 insertions(+), 8 deletions(-)\n\ndiff --git a/source/CMakeLists.txt b/source/CMakeLists.txt\nindex 4f5b3ed82..7183fd3ce 100755\n--- a/source/CMakeLists.txt\n+++ b/source/CMakeLists.txt\n@@ -6,18 +6,14 @@ if(NOT CMAKE_BUILD_TYPE)\n         FORCE)\n endif()\n message(STATUS \"cmake version ${CMAKE_VERSION}\")\n-if(POLICY CMP0025)\n-    cmake_policy(SET CMP0025 NEW) # report Apple's Clang as just Clang\n-endif()\n+\n if(POLICY CMP0042)\n     cmake_policy(SET CMP0042 NEW) # MACOSX_RPATH\n endif()\n-if(POLICY CMP0054)\n-    cmake_policy(SET CMP0054 NEW) # Only interpret if() arguments as variables or keywords when unquoted\n-endif()\n+\n \n project (x265)\n-cmake_minimum_required (VERSION 2.8.8) # OBJECT libraries require 2.8.8\n+cmake_minimum_required (VERSION 2.8.8...3.10) # OBJECT libraries require 2.8.8\n include(CheckIncludeFiles)\n include(CheckFunctionExists)\n include(CheckSymbolExists)\n@@ -168,7 +164,7 @@ if(APPLE)\n   add_definitions(-DMACOS=1)\n endif()\n \n-if(${CMAKE_CXX_COMPILER_ID} STREQUAL \"Clang\")\n+if(${CMAKE_CXX_COMPILER_ID} STREQUAL \"Clang\" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL \"AppleClang\")\n     set(CLANG 1)\n endif()\n if(${CMAKE_CXX_COMPILER_ID} STREQUAL \"Intel\")\n@@ -740,6 +736,9 @@ if((MSVC_IDE OR XCODE OR GCC) AND ENABLE_ASSEMBLY)\n     if(ARM OR CROSS_COMPILE_ARM)\n     # compile ARM arch asm files here\n         enable_language(ASM)\n+        if(APPLE)\n+            set(ARM_ARGS ${ARM_ARGS} -arch ${CMAKE_OSX_ARCHITECTURES})\n+        endif()\n         foreach(ASM ${ARM_ASMS})\n \t\t\tset(ASM_SRC ${CMAKE_CURRENT_SOURCE_DIR}/common/arm/${ASM})\n             list(APPEND ASM_SRCS ${ASM_SRC})\n-- \n2.49.0\n\n"
  },
  {
    "path": ".ci/x265_b354c009a60bcd6d7fc04014e200a1ee9c45c167.patch",
    "content": "From b354c009a60bcd6d7fc04014e200a1ee9c45c167 Mon Sep 17 00:00:00 2001\nFrom: yaswanthsastry <yaswanth.sastry@multicorewareinc.com>\nDate: Mon, 24 Feb 2025 17:07:03 +0530\nSubject: [PATCH] Fix CMake build error with latest CMake 4.0 release\n\n---\n source/CMakeLists.txt | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/source/CMakeLists.txt b/source/CMakeLists.txt\nindex 37dbe1a87..4f5b3ed82 100755\n--- a/source/CMakeLists.txt\n+++ b/source/CMakeLists.txt\n@@ -7,13 +7,13 @@ if(NOT CMAKE_BUILD_TYPE)\n endif()\n message(STATUS \"cmake version ${CMAKE_VERSION}\")\n if(POLICY CMP0025)\n-    cmake_policy(SET CMP0025 OLD) # report Apple's Clang as just Clang\n+    cmake_policy(SET CMP0025 NEW) # report Apple's Clang as just Clang\n endif()\n if(POLICY CMP0042)\n     cmake_policy(SET CMP0042 NEW) # MACOSX_RPATH\n endif()\n if(POLICY CMP0054)\n-    cmake_policy(SET CMP0054 OLD) # Only interpret if() arguments as variables or keywords when unquoted\n+    cmake_policy(SET CMP0054 NEW) # Only interpret if() arguments as variables or keywords when unquoted\n endif()\n \n project (x265)\n-- \n2.49.0\n\n"
  },
  {
    "path": ".ci/yum_deps.sh",
    "content": "#!/bin/bash\nset -e -x\n\nyum -y update\nyum install -y epel-release\nyum -y install libass libass-devel autoconf automake bzip2 cmake freetype-devel gcc gcc-c++ git libtool make mercurial \\\npkgconfig zlib-devel enca-devel fontconfig-devel openssl openssl-devel wget openjpeg openjpeg-devel \\\nlibpng libpng-devel libtiff libtiff-devel libwebp libwebp-devel dbus-devel dbus ibus-devel ibus libsamplerate-devel \\\nlibsamplerate libmodplug-devel libmodplug flac-devel flac \\\nlibjpeg-turbo-devel libjpeg-turbo pulseaudio pulseaudio-libs-devel alsa-lib alsa-lib-devel ca-certificates perl-devel \\\nperl perl-IPC-Cmd patch\n"
  },
  {
    "path": ".github/workflows/pythonapp.yml",
    "content": "name: Python application\n\non: [push, pull_request]\n\nenv:\n  FFMPEG_VERSION: \"6.0\"  # https://ffmpeg.org/releases/\n  SDL_VERSION: \"2.26.4\"  # https://github.com/libsdl-org/SDL/releases\n  SDL_MIXER_VERSION: \"2.6.3\"  # https://github.com/libsdl-org/SDL_mixer/releases\n  USE_SDL2_MIXER: \"1\"\n  MACOSX_DEPLOYMENT_TARGET: \"10.13\"\n  MACOSX_DEPLOYMENT_TARGET_ARM: \"11.0\"\n\njobs:\n  windows_wheels_tests:\n    runs-on: windows-latest\n    env:\n      FF_BUILD_DIR: ~/ff_deps\n      SDL_ROOT: ~/ff_deps/SDL2\n      FFMPEG_ROOT: ~/ff_deps/ffmpeg\n    strategy:\n      matrix:\n        python: [ '3.9', '3.10', '3.11', '3.12', '3.13']\n    steps:\n    - uses: actions/checkout@v4.2.2\n    - name: Set up Python ${{ matrix.python }}\n      uses: actions/setup-python@v5.4.0\n      with:\n        python-version: ${{ matrix.python }}\n    - name: Get dependencies\n      run: |\n        mkdir \"$env:FF_BUILD_DIR\"\n        cd \"$env:FF_BUILD_DIR\"\n\n        curl -sLO \"https://github.com/GyanD/codexffmpeg/releases/download/$env:FFMPEG_VERSION/ffmpeg-$env:FFMPEG_VERSION-full_build-shared.zip\"\n        7z x \"ffmpeg-$env:FFMPEG_VERSION-full_build-shared.zip\"\n        ren \"ffmpeg-$env:FFMPEG_VERSION-full_build-shared\" ffmpeg\n\n        curl -sLO \"https://github.com/libsdl-org/SDL/releases/download/release-$env:SDL_VERSION/SDL2-devel-$env:SDL_VERSION-VC.zip\"\n        7z x \"SDL2-devel-$env:SDL_VERSION-VC.zip\"\n        ren \"SDL2-$env:SDL_VERSION\" SDL2\n        curl -sLO \"https://github.com/libsdl-org/SDL_mixer/releases/download/release-$env:SDL_MIXER_VERSION/SDL2_mixer-devel-$env:SDL_MIXER_VERSION-VC.zip\"\n        7z x \"SDL2_mixer-devel-$env:SDL_MIXER_VERSION-VC.zip\"\n\n        mkdir \"SDL2\\bin\"\n        mkdir \"SDL2\\include\\SDL2\"\n\n        Copy-Item \"SDL2\\COPYING.txt\" -destination \"SDL2\\bin\"\n        Copy-Item \"SDL2\\README-SDL.txt\" -destination \"SDL2\\bin\"\n\n        Copy-Item \"SDL2\\lib\\x64\\*.dll\" -destination \"SDL2\\bin\" -Recurse -Force\n        Copy-Item \"SDL2\\lib\\x64\\*.lib\" -destination \"SDL2\\lib\" -Recurse -Force\n\n        Copy-Item \"SDL2_mixer-$env:SDL_MIXER_VERSION\\lib\\x64\\*.dll\" -destination \"SDL2\\bin\" -Recurse -Force\n        Copy-Item \"SDL2_mixer-$env:SDL_MIXER_VERSION\\lib\\x64\\*.lib\" -destination \"SDL2\\lib\" -Recurse -Force\n        Copy-Item \"SDL2_mixer-$env:SDL_MIXER_VERSION\\include\\*\" -destination \"SDL2\\include\" -Recurse -Force\n\n        Copy-Item \"SDL2\\include\\*.h\" -destination \"SDL2\\include\\SDL2\" -Recurse -Force\n\n        echo \"Dependency paths are:\"\n        ls $env:SDL_ROOT\n        ls $env:FFMPEG_ROOT\n    - name: Install pip deps\n      run: |\n        python -m pip install --upgrade pip virtualenv wheel setuptools cython~=3.0.11 pytest\n    - name: Make sdist\n      if: matrix.python == '3.13'\n      run: python setup.py sdist --formats=gztar\n    - name: Make wheel\n      run: |\n        $env:SDL_ROOT=(get-item $env:SDL_ROOT).FullName\n        $env:FFMPEG_ROOT=(get-item $env:FFMPEG_ROOT).FullName\n        python setup.py bdist_wheel\n    - name: Upload wheel\n      uses: actions/upload-artifact@v4.6.2\n      with:\n        name: py_wheel-win-${{ matrix.python }}\n        path: dist\n    - name: Upload to GitHub Release\n      uses: softprops/action-gh-release@v2.2.1\n      if: startsWith(github.ref, 'refs/tags/')\n      env:\n        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      with:\n        files: dist/*\n    - name: Publish to PyPI\n      if: startsWith(github.ref, 'refs/tags/')\n      env:\n        TWINE_USERNAME: \"__token__\"\n        TWINE_PASSWORD: ${{ secrets.pypi_password }}\n      run: |\n        python -m pip install twine\n        twine upload dist/*\n    - name: Test\n      run: |\n        # see https://social.msdn.microsoft.com/Forums/security/en-US/0c13bd1a-388f-48cf-a190-7259d39a080f/ffmpeg-doesnt-work-from-inside-a-container-but-works-on-the-host?forum=windowscontainers\n        # https://trac.ffmpeg.org/ticket/6875, https://stackoverflow.com/questions/46147012/opencv-import-failed-in-windows-container-on-windows-server-2016\n        # and https://social.msdn.microsoft.com/Forums/en-US/a95032d2-c469-494a-b3f9-521b1389a6c9/cant-use-opencvpython-package-in-windows-container-windows-server-2016-standard?forum=windowscontainers\n        # for the reason we need to manually copy some missing dlls to the PATH\n        Invoke-WebRequest  \"https://github.com/matham/ffpyplayer/releases/download/v4.1.0/ffmpeg_win_dll_container_deps.zip\"  -OutFile \"ffmpeg_win_dll_container_deps.zip\"\n        7z x \"ffmpeg_win_dll_container_deps.zip\"\n        $env:PATH=\"$env:PATH;$env:GITHUB_WORKSPACE\\ffmpeg_win_dll_container_deps\\x64\"\n        ls \"$env:GITHUB_WORKSPACE\\ffmpeg_win_dll_container_deps\\x64\"\n\n        $dist_path=(get-item dist).FullName\n        $root=(get-item .).FullName\n        $env:FFPYPLAYER_TEST_DIRS=\"$root\\ffpyplayer\\tests;$root\\examples\"\n        cd ~/\n\n        python -m pip install --no-index --find-links=$dist_path ffpyplayer\n        $name = python -c \"import ffpyplayer, os.path;print(os.path.dirname(ffpyplayer.__file__))\"\n        echo $name\n        # powershell interprets writing to stderr as an error, so only raise error if the return code is none-zero\n        try {\n          pytest \"$name\\tests\"\n        } catch {\n          if ($LastExitCode -ne 0) {\n            throw $_\n          } else {\n            echo $_\n          }\n        }\n\n  linux_test_src:\n    strategy:\n      matrix:\n        include:\n          - os: ubuntu-latest\n          - os: ubuntu-24.04-arm\n    runs-on: ${{ matrix.os }}\n    needs: windows_wheels_tests\n    steps:\n      - uses: actions/checkout@v4.2.2\n      - name: Set up Python 3.x\n        uses: actions/setup-python@v5.4.0\n        with:\n          python-version: 3.x\n      - uses: actions/download-artifact@v4.2.1\n        with:\n          pattern: py_wheel-*\n          merge-multiple: true\n          path: dist\n      - name: Install\n        run: |\n          sudo apt update\n          sudo apt install -y ffmpeg libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev\n          sudo apt install -y libavutil-dev libswscale-dev libswresample-dev libpostproc-dev libsdl2-dev libsdl2-2.0-0\n          sudo apt install -y libsdl2-mixer-2.0-0 libsdl2-mixer-dev python3-dev python3\n          python3 -m pip install pytest\n\n          root=`pwd`\n          cd ~/\n          python3 -m pip install `ls $root/dist/ffpyplayer*.tar.gz`\n      - name: Test\n        run: |\n          root=`pwd`\n          export FFPYPLAYER_TEST_DIRS=\"$root/ffpyplayer/tests:$root/examples\"\n          cd ~/\n\n          name=`python3 -c \"import ffpyplayer, os.path;print(os.path.dirname(ffpyplayer.__file__))\"`\n          echo $name\n          pytest \"$name/tests\"\n\n  linux_test_wheel:\n    strategy:\n      matrix:\n        include:\n          - os: ubuntu-latest\n          - os: ubuntu-24.04-arm\n    runs-on: ${{ matrix.os }}\n    needs: linux_wheels\n    steps:\n      - uses: actions/checkout@v4.2.2\n      - name: Set up Python 3.x\n        uses: actions/setup-python@v5.4.0\n        with:\n          python-version: 3.x\n      - uses: actions/download-artifact@v4.2.1\n        with:\n          pattern: py_wheel-*\n          merge-multiple: true\n          path: dist\n      - name: Install\n        run: |\n          python3 -m pip install --upgrade pip pytest\n          root=`pwd`\n          cd ~/\n          python3 -m pip install --no-index --find-links=$root/dist ffpyplayer\n      - name: Test\n        run: |\n          root=`pwd`\n          export FFPYPLAYER_TEST_DIRS=\"$root/ffpyplayer/tests:$root/examples\"\n          cd ~/\n\n          name=`python3 -c \"import ffpyplayer, os.path;print(os.path.dirname(ffpyplayer.__file__))\"`\n          echo $name\n          pytest \"$name/tests\"\n\n  linux_wheels:\n    env:\n      CIBW_ENVIRONMENT_LINUX: \"USE_SDL2_MIXER=0 PKG_CONFIG_PATH=$HOME/ffmpeg_build/lib/pkgconfig:$HOME/ffmpeg_build/lib64/pkgconfig LD_LIBRARY_PATH=$HOME/ffmpeg_build/lib:$HOME/ffmpeg_build/lib64:$LD_LIBRARY_PATH\"\n      CIBW_BUILD_VERBOSITY: 3\n      CIBW_BUILD: ${{ matrix.cibw_build }}\n      CIBW_ARCHS: ${{ matrix.cibw_archs }}\n      CIBW_BEFORE_ALL_LINUX: >\n        cp -r `pwd`/ffmpeg_build $HOME/ffmpeg_build &&\n        source .ci/yum_deps.sh\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        include:\n          - os: ubuntu-latest\n            cibw_archs: 'x86_64'\n            cibw_build: 'cp39-manylinux_x86_64 cp310-manylinux_x86_64 cp311-manylinux_x86_64 cp312-manylinux_x86_64 cp313-manylinux_x86_64'\n          - os: ubuntu-24.04-arm\n            cibw_archs: 'aarch64'\n            cibw_build: 'cp39-manylinux_aarch64 cp310-manylinux_aarch64 cp311-manylinux_aarch64 cp312-manylinux_aarch64 cp313-manylinux_aarch64'\n    steps:\n      - uses: actions/checkout@v4.2.2\n      - name: Set up Python 3.x\n        uses: actions/setup-python@v5.4.0\n        with:\n          python-version: 3.x\n      - uses: actions/cache@v4.2.3\n        id: deps-cache\n        with:\n          path: ffmpeg_build\n          key: ${{ runner.os }}-${{ matrix.cibw_archs }}-deps-cache-${{ hashFiles('**/build-wheels.sh') }}-${{ hashFiles('**/yum_deps.sh') }}\n      - name: Build dependencies\n        if: ${{ steps.deps-cache.outputs.cache-hit != 'true' }}\n        run: |\n          mkdir dist\n          docker run --rm -v `pwd`:/io:rw quay.io/pypa/manylinux2014_${{ matrix.cibw_archs }} /io/.ci/build-wheels.sh\n      - name: Install cibuildwheel\n        run: |\n          python -m pip install cibuildwheel~=2.23.3\n      - name: Make wheels\n        run: |\n          python -m cibuildwheel --output-dir dist\n      - name: Upload wheel\n        uses: actions/upload-artifact@v4.6.2\n        with:\n          name: py_wheel-linux-${{ matrix.os }}-${{ matrix.cibw_archs }}\n          path: dist\n      - name: Upload to GitHub Release\n        uses: softprops/action-gh-release@v2.2.1\n        if: startsWith(github.ref, 'refs/tags/')\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        with:\n          files: dist/*\n      - name: Publish to PyPI\n        if: startsWith(github.ref, 'refs/tags/')\n        env:\n          TWINE_USERNAME: \"__token__\"\n          TWINE_PASSWORD: ${{ secrets.pypi_password }}\n        run: |\n          python -m pip install twine\n          twine upload dist/*\n\n  osx_wheels_create:\n    runs-on: macos-13\n    env:\n      USE_SDL2_MIXER: 0\n      FFMPEG_BUILD_PATH: \"ffmpeg_build\"\n      CIBW_BUILD_VERBOSITY: 3\n      CIBW_BUILD: \"cp39-* cp310-* cp311-* cp312-* cp313-*\"\n      CIBW_ARCHS_MACOS: ${{ matrix.arch }}\n      CIBW_REPAIR_WHEEL_COMMAND_MACOS: >\n        DYLD_FALLBACK_LIBRARY_PATH=$REPAIR_LIBRARY_PATH delocate-listdeps {wheel} &&\n        DYLD_FALLBACK_LIBRARY_PATH=$REPAIR_LIBRARY_PATH delocate-wheel --require-archs {delocate_archs} -w {dest_dir} {wheel}\n    strategy:\n      matrix:\n        arch: [ \"x86_64\", \"arm64\" ]\n    steps:\n      - uses: actions/checkout@v4.2.2\n      - name: Set up Python\n        uses: actions/setup-python@v5.4.0\n        with:\n          python-version: 3.x\n\n      - name: Cache ffmpeg\n        id: cache-ffmpeg\n        uses: actions/cache@v4.2.3\n        with:\n          path: ~/${{ env.FFMPEG_BUILD_PATH }}_${{ matrix.arch }}\n          key: ${{ runner.os }}-ffmpeg-${{ matrix.arch }}-${{ env.MACOSX_DEPLOYMENT_TARGET }}-${{ env.MACOSX_DEPLOYMENT_TARGET_ARM }}-${{ hashFiles('.ci/build_wheels_osx.sh') }}\n      - name: Build FFmpeg\n        if: steps.cache-ffmpeg.outputs.cache-hit != 'true'\n        run: bash .ci/build_wheels_osx.sh \"${{ matrix.arch }}\"\n\n      - name: Install cibuildwheel\n        run: |\n          python -m pip install cibuildwheel~=2.23.3\n      - name: Build wheels\n        run: |\n          export REPAIR_LIBRARY_PATH=\"$HOME/${{ env.FFMPEG_BUILD_PATH }}_${{ matrix.arch }}/lib\"\n          export PKG_CONFIG_PATH=\"$HOME/${{ env.FFMPEG_BUILD_PATH }}_${{ matrix.arch }}/lib/pkgconfig:$PKG_CONFIG_PATH\"\n          python -m cibuildwheel --output-dir dist\n\n      - name: Upload wheel\n        uses: actions/upload-artifact@v4.6.2\n        with:\n          name: py_wheel-osx-${{ matrix.arch }}\n          path: dist\n\n  osx_wheels_fuse_test_upload:\n    runs-on: macos-13\n    needs: osx_wheels_create\n    steps:\n      - uses: actions/checkout@v4.2.2\n      - name: Set up Python\n        uses: actions/setup-python@v5.4.0\n        with:\n          python-version: 3.x\n\n      - uses: actions/download-artifact@v4.2.1\n        with:\n          pattern: py_wheel-*\n          merge-multiple: true\n          path: dist\n\n      - name: Fuse FFmpeg arm64/x86\n        run: |\n          pip install delocate\n          cd dist\n          bash ../.ci/merge_osx_deps.sh\n\n      - name: Upload wheel\n        uses: actions/upload-artifact@v4.6.2\n        with:\n          name: py_wheel-osx-fused\n          path: dist\n\n      - name: Upload to GitHub Release\n        uses: softprops/action-gh-release@v2.2.1\n        if: startsWith(github.ref, 'refs/tags/')\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        with:\n          files: dist/*\n      - name: Publish to PyPI\n        if: startsWith(github.ref, 'refs/tags/')\n        env:\n          TWINE_USERNAME: \"__token__\"\n          TWINE_PASSWORD: ${{ secrets.pypi_password }}\n        run: |\n          python -m pip install twine\n          twine upload dist/*\n      - name: Test\n        run: |\n          root=`pwd`\n          export FFPYPLAYER_TEST_DIRS=\"$root/ffpyplayer/tests:$root/examples\"\n          cd ~/\n\n          python -m pip install --upgrade pip virtualenv wheel setuptools pytest\n          python -m pip install --no-index --find-links=$root/dist ffpyplayer\n          name=`python -c \"import ffpyplayer, os.path;print(os.path.dirname(ffpyplayer.__file__))\"`\n          echo $name\n          pytest \"$name/tests\"\n\n  docs:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4.2.2\n      - name: Set up Python 3.x\n        uses: actions/setup-python@v5.4.0\n        with:\n          python-version: 3.x\n      - name: Install\n        run: |\n          sudo apt update\n          sudo apt install ffmpeg libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev\n          sudo apt install libavutil-dev libswscale-dev libswresample-dev libpostproc-dev libsdl2-dev libsdl2-2.0-0\n          sudo apt install libsdl2-mixer-2.0-0 libsdl2-mixer-dev python3-dev\n\n          python -m pip install --upgrade pip virtualenv wheel setuptools sphinx sphinx_rtd_theme\n          python -m pip install -e .\n      - name: Generate docs\n        run: |\n          cd doc\n          make html\n      - name: gh-pages upload\n        if: github.event_name == 'push' && github.ref == 'refs/heads/master'\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          cp -r doc/build/html ~/docs_temp\n\n          git config --global user.email \"moiein2000@gmail.com\"\n          git config --global user.name \"Matthew Einhorn\"\n          git remote rm origin || true\n          git remote add origin \"https://x-access-token:${GITHUB_TOKEN}@github.com/matham/ffpyplayer.git\"\n\n          git checkout --orphan gh-pages\n          cp -r .git ~/docs_git\n          cd ..\n          rm -rf ffpyplayer\n          mkdir ffpyplayer\n          cd ffpyplayer\n          cp -r ~/docs_git .git\n          cp -r ~/docs_temp/* .\n          touch .nojekyll\n\n          git add .\n          git commit -a -m \"Docs for git-$GITHUB_SHA\"\n          git push origin gh-pages -f\n"
  },
  {
    "path": ".gitignore",
    "content": "build/\n*.pyd\n*.pyc\nffpyplayer/*.c\nffpyplayer/*.html\nffpyplayer/player/*.c\nffpyplayer/includes/ffconfig.h\nffpyplayer/includes/ffconfig.pxi\n*egg-info\n"
  },
  {
    "path": "COPYING",
    "content": "                   GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\n  This version of the GNU Lesser General Public License incorporates\nthe terms and conditions of version 3 of the GNU General Public\nLicense, supplemented by the additional permissions listed below.\n\n  0. Additional Definitions.\n\n  As used herein, \"this License\" refers to version 3 of the GNU Lesser\nGeneral Public License, and the \"GNU GPL\" refers to version 3 of the GNU\nGeneral Public License.\n\n  \"The Library\" refers to a covered work governed by this License,\nother than an Application or a Combined Work as defined below.\n\n  An \"Application\" is any work that makes use of an interface provided\nby the Library, but which is not otherwise based on the Library.\nDefining a subclass of a class defined by the Library is deemed a mode\nof using an interface provided by the Library.\n\n  A \"Combined Work\" is a work produced by combining or linking an\nApplication with the Library.  The particular version of the Library\nwith which the Combined Work was made is also called the \"Linked\nVersion\".\n\n  The \"Minimal Corresponding Source\" for a Combined Work means the\nCorresponding Source for the Combined Work, excluding any source code\nfor portions of the Combined Work that, considered in isolation, are\nbased on the Application, and not on the Linked Version.\n\n  The \"Corresponding Application Code\" for a Combined Work means the\nobject code and/or source code for the Application, including any data\nand utility programs needed for reproducing the Combined Work from the\nApplication, but excluding the System Libraries of the Combined Work.\n\n  1. Exception to Section 3 of the GNU GPL.\n\n  You may convey a covered work under sections 3 and 4 of this License\nwithout being bound by section 3 of the GNU GPL.\n\n  2. Conveying Modified Versions.\n\n  If you modify a copy of the Library, and, in your modifications, a\nfacility refers to a function or data to be supplied by an Application\nthat uses the facility (other than as an argument passed when the\nfacility is invoked), then you may convey a copy of the modified\nversion:\n\n   a) under this License, provided that you make a good faith effort to\n   ensure that, in the event an Application does not supply the\n   function or data, the facility still operates, and performs\n   whatever part of its purpose remains meaningful, or\n\n   b) under the GNU GPL, with none of the additional permissions of\n   this License applicable to that copy.\n\n  3. Object Code Incorporating Material from Library Header Files.\n\n  The object code form of an Application may incorporate material from\na header file that is part of the Library.  You may convey such object\ncode under terms of your choice, provided that, if the incorporated\nmaterial is not limited to numerical parameters, data structure\nlayouts and accessors, or small macros, inline functions and templates\n(ten or fewer lines in length), you do both of the following:\n\n   a) Give prominent notice with each copy of the object code that the\n   Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the object code with a copy of the GNU GPL and this license\n   document.\n\n  4. Combined Works.\n\n  You may convey a Combined Work under terms of your choice that,\ntaken together, effectively do not restrict modification of the\nportions of the Library contained in the Combined Work and reverse\nengineering for debugging such modifications, if you also do each of\nthe following:\n\n   a) Give prominent notice with each copy of the Combined Work that\n   the Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the Combined Work with a copy of the GNU GPL and this license\n   document.\n\n   c) For a Combined Work that displays copyright notices during\n   execution, include the copyright notice for the Library among\n   these notices, as well as a reference directing the user to the\n   copies of the GNU GPL and this license document.\n\n   d) Do one of the following:\n\n       0) Convey the Minimal Corresponding Source under the terms of this\n       License, and the Corresponding Application Code in a form\n       suitable for, and under terms that permit, the user to\n       recombine or relink the Application with a modified version of\n       the Linked Version to produce a modified Combined Work, in the\n       manner specified by section 6 of the GNU GPL for conveying\n       Corresponding Source.\n\n       1) Use a suitable shared library mechanism for linking with the\n       Library.  A suitable mechanism is one that (a) uses at run time\n       a copy of the Library already present on the user's computer\n       system, and (b) will operate properly with a modified version\n       of the Library that is interface-compatible with the Linked\n       Version.\n\n   e) Provide Installation Information, but only if you would otherwise\n   be required to provide such information under section 6 of the\n   GNU GPL, and only to the extent that such information is\n   necessary to install and execute a modified version of the\n   Combined Work produced by recombining or relinking the\n   Application with a modified version of the Linked Version. (If\n   you use option 4d0, the Installation Information must accompany\n   the Minimal Corresponding Source and Corresponding Application\n   Code. If you use option 4d1, you must provide the Installation\n   Information in the manner specified by section 6 of the GNU GPL\n   for conveying Corresponding Source.)\n\n  5. Combined Libraries.\n\n  You may place library facilities that are a work based on the\nLibrary side by side in a single library together with other library\nfacilities that are not Applications and are not covered by this\nLicense, and convey such a combined library under terms of your\nchoice, if you do both of the following:\n\n   a) Accompany the combined library with a copy of the same work based\n   on the Library, uncombined with any other library facilities,\n   conveyed under the terms of this License.\n\n   b) Give prominent notice with the combined library that part of it\n   is a work based on the Library, and explaining where to find the\n   accompanying uncombined form of the same work.\n\n  6. Revised Versions of the GNU Lesser General Public License.\n\n  The Free Software Foundation may publish revised and/or new versions\nof the GNU Lesser General Public License from time to time. Such new\nversions will be similar in spirit to the present version, but may\ndiffer in detail to address new problems or concerns.\n\n  Each version is given a distinguishing version number. If the\nLibrary as you received it specifies that a certain numbered version\nof the GNU Lesser General Public License \"or any later version\"\napplies to it, you have the option of following the terms and\nconditions either of that published version or of any later version\npublished by the Free Software Foundation. If the Library as you\nreceived it does not specify a version number of the GNU Lesser\nGeneral Public License, you may choose any version of the GNU Lesser\nGeneral Public License ever published by the Free Software Foundation.\n\n  If the Library as you received it specifies that a proxy can decide\nwhether future versions of the GNU Lesser General Public License shall\napply, that proxy's public statement of acceptance of any version is\npermanent authorization for you to choose that version for the\nLibrary.\n"
  },
  {
    "path": "Makefile",
    "content": "PYTHON = python\n\n.PHONY: build force test html\n\nbuild:\n\t$(PYTHON) setup.py build_ext --inplace\n\nforce:\n\t$(PYTHON) setup.py build_ext --inplace -f\n\ntest:\n\t$(PYTHON) -m pytest ffpyplayer/tests\n\nhtml:\n\t@cd doc && make html\n"
  },
  {
    "path": "README.rst",
    "content": "FFPyPlayer is a python binding for the FFmpeg library for playing and writing\nmedia files.\n\nFor more information: https://matham.github.io/ffpyplayer/index.html\n\nTo install: https://matham.github.io/ffpyplayer/installation.html\n\n.. image:: https://travis-ci.org/matham/ffpyplayer.svg?branch=master\n    :target: https://travis-ci.org/matham/ffpyplayer\n    :alt: TravisCI status\n\n.. image:: https://ci.appveyor.com/api/projects/status/nfl6tyiwks26ngyu/branch/master?svg=true\n    :target: https://ci.appveyor.com/project/matham/ffpyplayer/branch/master\n    :alt: Appveyor status\n\n.. image:: https://img.shields.io/pypi/pyversions/ffpyplayer.svg\n    :target: https://pypi.python.org/pypi/ffpyplayer/\n    :alt: Supported Python versions\n\n.. image:: https://img.shields.io/pypi/v/ffpyplayer.svg\n    :target: https://pypi.python.org/pypi/ffpyplayer/\n    :alt: Latest Version on PyPI\n\n.. warning::\n\n    Although the ffpyplayer source code is licensed under the LGPL, the ffpyplayer wheels\n    for Windows and linux on PYPI are distributed under the GPL because the included FFmpeg binaries\n    were compiled with GPL options.\n\n    If you want to use it under the LGPL you need to compile FFmpeg yourself with the correct options.\n\n    Similarly, the wheels bundle openssl for online camera support. However, releases are not made\n    for every openssl release, so it is recommended that you compile ffpyplayer yourself if security\n    is a issue.\n\nUsage example\n-------------\n\nPlaying a file:\n\n.. code-block:: python\n\n    >>> from ffpyplayer.player import MediaPlayer\n    >>> import time\n\n    >>> player = MediaPlayer(filename)\n    >>> val = ''\n    >>> while val != 'eof':\n    ...     frame, val = player.get_frame()\n    ...     if val != 'eof' and frame is not None:\n    ...         img, t = frame\n    ...         # display img\n\nWriting a video file:\n\n.. code-block:: python\n\n    >>> from ffpyplayer.writer import MediaWriter\n    >>> from ffpyplayer.pic import Image\n\n    >>> w, h = 640, 480\n    >>> # write at 5 fps.\n    >>> out_opts = {'pix_fmt_in':'rgb24', 'width_in':w, 'height_in':h,\n    ...     'codec':'rawvideo', 'frame_rate':(5, 1)}\n    >>> writer = MediaWriter('output.avi', [out_opts])\n\n    >>> # Construct image\n    >>> size = w * h * 3\n    >>> buf = bytearray([int(x * 255 / size) for x in range(size)])\n    >>> img = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\n\n    >>> for i in range(20):\n    ...     writer.write_frame(img=img, pts=i / 5., stream=0)\n\nConverting images:\n\n.. code-block:: python\n\n    >>> from ffpyplayer.pic import Image, SWScale\n    >>> w, h = 500, 100\n    >>> size = w * h * 3\n    >>> buf = bytearray([int(x * 255 / size) for x in range(size)])\n\n    >>> img = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\n    >>> sws = SWScale(w, h, img.get_pixel_format(), ofmt='yuv420p')\n\n    >>> img2 = sws.scale(img)\n    >>> img2.get_pixel_format()\n    'yuv420p'\n    >>> planes = img2.to_bytearray()\n    >>> [len(plane) for plane in planes]\n    [50000, 12500, 12500, 0]\n"
  },
  {
    "path": "doc/Makefile",
    "content": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nPAPER         =\nBUILDDIR      = build\n\n# User-friendly check for sphinx-build\nifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)\n$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)\nendif\n\n# Internal variables.\nPAPEROPT_a4     = -D latex_paper_size=a4\nPAPEROPT_letter = -D latex_paper_size=letter\nALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source\n# the i18n builder cannot share the environment and doctrees with the others\nI18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source\n\n.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext\n\nhelp:\n\t@echo \"Please use \\`make <target>' where <target> is one of\"\n\t@echo \"  html       to make standalone HTML files\"\n\t@echo \"  dirhtml    to make HTML files named index.html in directories\"\n\t@echo \"  singlehtml to make a single large HTML file\"\n\t@echo \"  pickle     to make pickle files\"\n\t@echo \"  json       to make JSON files\"\n\t@echo \"  htmlhelp   to make HTML files and a HTML help project\"\n\t@echo \"  qthelp     to make HTML files and a qthelp project\"\n\t@echo \"  devhelp    to make HTML files and a Devhelp project\"\n\t@echo \"  epub       to make an epub\"\n\t@echo \"  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\"\n\t@echo \"  latexpdf   to make LaTeX files and run them through pdflatex\"\n\t@echo \"  latexpdfja to make LaTeX files and run them through platex/dvipdfmx\"\n\t@echo \"  text       to make text files\"\n\t@echo \"  man        to make manual pages\"\n\t@echo \"  texinfo    to make Texinfo files\"\n\t@echo \"  info       to make Texinfo files and run them through makeinfo\"\n\t@echo \"  gettext    to make PO message catalogs\"\n\t@echo \"  changes    to make an overview of all changed/added/deprecated items\"\n\t@echo \"  xml        to make Docutils-native XML files\"\n\t@echo \"  pseudoxml  to make pseudoxml-XML files for display purposes\"\n\t@echo \"  linkcheck  to check all external links for integrity\"\n\t@echo \"  doctest    to run all doctests embedded in the documentation (if enabled)\"\n\nclean:\n\trm -rf $(BUILDDIR)/*\n\nhtml:\n\t@cd .. && python setup.py build_ext --inplace && cd doc\n\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/html.\"\n\ndirhtml:\n\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/dirhtml.\"\n\nsinglehtml:\n\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml\n\t@echo\n\t@echo \"Build finished. The HTML page is in $(BUILDDIR)/singlehtml.\"\n\npickle:\n\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle\n\t@echo\n\t@echo \"Build finished; now you can process the pickle files.\"\n\njson:\n\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json\n\t@echo\n\t@echo \"Build finished; now you can process the JSON files.\"\n\nhtmlhelp:\n\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp\n\t@echo\n\t@echo \"Build finished; now you can run HTML Help Workshop with the\" \\\n\t      \".hhp project file in $(BUILDDIR)/htmlhelp.\"\n\nqthelp:\n\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp\n\t@echo\n\t@echo \"Build finished; now you can run \"qcollectiongenerator\" with the\" \\\n\t      \".qhcp project file in $(BUILDDIR)/qthelp, like this:\"\n\t@echo \"# qcollectiongenerator $(BUILDDIR)/qthelp/FFPyPlayer.qhcp\"\n\t@echo \"To view the help file:\"\n\t@echo \"# assistant -collectionFile $(BUILDDIR)/qthelp/FFPyPlayer.qhc\"\n\ndevhelp:\n\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp\n\t@echo\n\t@echo \"Build finished.\"\n\t@echo \"To view the help file:\"\n\t@echo \"# mkdir -p $$HOME/.local/share/devhelp/FFPyPlayer\"\n\t@echo \"# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/FFPyPlayer\"\n\t@echo \"# devhelp\"\n\nepub:\n\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub\n\t@echo\n\t@echo \"Build finished. The epub file is in $(BUILDDIR)/epub.\"\n\nlatex:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo\n\t@echo \"Build finished; the LaTeX files are in $(BUILDDIR)/latex.\"\n\t@echo \"Run \\`make' in that directory to run these through (pdf)latex\" \\\n\t      \"(use \\`make latexpdf' here to do that automatically).\"\n\nlatexpdf:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through pdflatex...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\nlatexpdfja:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through platex and dvipdfmx...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\ntext:\n\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text\n\t@echo\n\t@echo \"Build finished. The text files are in $(BUILDDIR)/text.\"\n\nman:\n\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man\n\t@echo\n\t@echo \"Build finished. The manual pages are in $(BUILDDIR)/man.\"\n\ntexinfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo\n\t@echo \"Build finished. The Texinfo files are in $(BUILDDIR)/texinfo.\"\n\t@echo \"Run \\`make' in that directory to run these through makeinfo\" \\\n\t      \"(use \\`make info' here to do that automatically).\"\n\ninfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo \"Running Texinfo files through makeinfo...\"\n\tmake -C $(BUILDDIR)/texinfo info\n\t@echo \"makeinfo finished; the Info files are in $(BUILDDIR)/texinfo.\"\n\ngettext:\n\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale\n\t@echo\n\t@echo \"Build finished. The message catalogs are in $(BUILDDIR)/locale.\"\n\nchanges:\n\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes\n\t@echo\n\t@echo \"The overview file is in $(BUILDDIR)/changes.\"\n\nlinkcheck:\n\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\ndoctest:\n\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest\n\t@echo \"Testing of doctests in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/doctest/output.txt.\"\n\nxml:\n\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml\n\t@echo\n\t@echo \"Build finished. The XML files are in $(BUILDDIR)/xml.\"\n\npseudoxml:\n\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml\n\t@echo\n\t@echo \"Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml.\"\n"
  },
  {
    "path": "doc/make.bat",
    "content": "@ECHO OFF\n\nREM Command file for Sphinx documentation\n\nif \"%SPHINXBUILD%\" == \"\" (\n\tset SPHINXBUILD=sphinx-build\n)\nset BUILDDIR=build\nset ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source\nset I18NSPHINXOPTS=%SPHINXOPTS% source\nif NOT \"%PAPER%\" == \"\" (\n\tset ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%\n\tset I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%\n)\n\nif \"%1\" == \"\" goto help\n\nif \"%1\" == \"help\" (\n\t:help\n\techo.Please use `make ^<target^>` where ^<target^> is one of\n\techo.  html       to make standalone HTML files\n\techo.  dirhtml    to make HTML files named index.html in directories\n\techo.  singlehtml to make a single large HTML file\n\techo.  pickle     to make pickle files\n\techo.  json       to make JSON files\n\techo.  htmlhelp   to make HTML files and a HTML help project\n\techo.  qthelp     to make HTML files and a qthelp project\n\techo.  devhelp    to make HTML files and a Devhelp project\n\techo.  epub       to make an epub\n\techo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\n\techo.  text       to make text files\n\techo.  man        to make manual pages\n\techo.  texinfo    to make Texinfo files\n\techo.  gettext    to make PO message catalogs\n\techo.  changes    to make an overview over all changed/added/deprecated items\n\techo.  xml        to make Docutils-native XML files\n\techo.  pseudoxml  to make pseudoxml-XML files for display purposes\n\techo.  linkcheck  to check all external links for integrity\n\techo.  doctest    to run all doctests embedded in the documentation if enabled\n\tgoto end\n)\n\nif \"%1\" == \"clean\" (\n\tfor /d %%i in (%BUILDDIR%\\*) do rmdir /q /s %%i\n\tdel /q /s %BUILDDIR%\\*\n\tgoto end\n)\n\n\n%SPHINXBUILD% 2> nul\nif errorlevel 9009 (\n\techo.\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\n\techo.installed, then set the SPHINXBUILD environment variable to point\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\n\techo.may add the Sphinx directory to PATH.\n\techo.\n\techo.If you don't have Sphinx installed, grab it from\n\techo.http://sphinx-doc.org/\n\texit /b 1\n)\n\nif \"%1\" == \"html\" (\n\tcd .. & python setup.py build_ext --inplace & cd doc\n\t%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The HTML pages are in %BUILDDIR%/html.\n\tgoto end\n)\n\nif \"%1\" == \"dirhtml\" (\n\t%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.\n\tgoto end\n)\n\nif \"%1\" == \"singlehtml\" (\n\t%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.\n\tgoto end\n)\n\nif \"%1\" == \"pickle\" (\n\t%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished; now you can process the pickle files.\n\tgoto end\n)\n\nif \"%1\" == \"json\" (\n\t%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished; now you can process the JSON files.\n\tgoto end\n)\n\nif \"%1\" == \"htmlhelp\" (\n\t%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished; now you can run HTML Help Workshop with the ^\n.hhp project file in %BUILDDIR%/htmlhelp.\n\tgoto end\n)\n\nif \"%1\" == \"qthelp\" (\n\t%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished; now you can run \"qcollectiongenerator\" with the ^\n.qhcp project file in %BUILDDIR%/qthelp, like this:\n\techo.^> qcollectiongenerator %BUILDDIR%\\qthelp\\FFPyPlayer.qhcp\n\techo.To view the help file:\n\techo.^> assistant -collectionFile %BUILDDIR%\\qthelp\\FFPyPlayer.ghc\n\tgoto end\n)\n\nif \"%1\" == \"devhelp\" (\n\t%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished.\n\tgoto end\n)\n\nif \"%1\" == \"epub\" (\n\t%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The epub file is in %BUILDDIR%/epub.\n\tgoto end\n)\n\nif \"%1\" == \"latex\" (\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished; the LaTeX files are in %BUILDDIR%/latex.\n\tgoto end\n)\n\nif \"%1\" == \"latexpdf\" (\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\n\tcd %BUILDDIR%/latex\n\tmake all-pdf\n\tcd %BUILDDIR%/..\n\techo.\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\n\tgoto end\n)\n\nif \"%1\" == \"latexpdfja\" (\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\n\tcd %BUILDDIR%/latex\n\tmake all-pdf-ja\n\tcd %BUILDDIR%/..\n\techo.\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\n\tgoto end\n)\n\nif \"%1\" == \"text\" (\n\t%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The text files are in %BUILDDIR%/text.\n\tgoto end\n)\n\nif \"%1\" == \"man\" (\n\t%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The manual pages are in %BUILDDIR%/man.\n\tgoto end\n)\n\nif \"%1\" == \"texinfo\" (\n\t%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.\n\tgoto end\n)\n\nif \"%1\" == \"gettext\" (\n\t%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The message catalogs are in %BUILDDIR%/locale.\n\tgoto end\n)\n\nif \"%1\" == \"changes\" (\n\t%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.The overview file is in %BUILDDIR%/changes.\n\tgoto end\n)\n\nif \"%1\" == \"linkcheck\" (\n\t%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Link check complete; look for any errors in the above output ^\nor in %BUILDDIR%/linkcheck/output.txt.\n\tgoto end\n)\n\nif \"%1\" == \"doctest\" (\n\t%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Testing of doctests in the sources finished, look at the ^\nresults in %BUILDDIR%/doctest/output.txt.\n\tgoto end\n)\n\nif \"%1\" == \"xml\" (\n\t%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The XML files are in %BUILDDIR%/xml.\n\tgoto end\n)\n\nif \"%1\" == \"pseudoxml\" (\n\t%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml\n\tif errorlevel 1 exit /b 1\n\techo.\n\techo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.\n\tgoto end\n)\n\n:end\n"
  },
  {
    "path": "doc/source/api.rst",
    "content": "\n####################\n  The FFPyPlayer API\n####################\n\n.. toctree::\n   :maxdepth: 1\n\n   player.rst\n   writer.rst\n   pic.rst\n   tools.rst\n"
  },
  {
    "path": "doc/source/conf.py",
    "content": "# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common options. For a full\n# list see the documentation:\n# http://www.sphinx-doc.org/en/master/config\n\n# -- Path setup --------------------------------------------------------------\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#\nimport os\nimport sphinx_rtd_theme\n\n\n# -- Project information -----------------------------------------------------\n\nproject = 'FFPyPlayer'\ncopyright = '2013, Matthew Einhorn'\nauthor = 'Matthew Einhorn'\n\n\n# -- General configuration ---------------------------------------------------\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.autodoc',\n    'sphinx.ext.todo',\n    'sphinx.ext.coverage',\n    \"sphinx_rtd_theme\",\n]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This pattern also affects html_static_path and html_extra_path.\nexclude_patterns = []\n\n\n# -- Options for HTML output -------------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\n#\nhtml_theme = 'sphinx_rtd_theme'\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['_static']\n"
  },
  {
    "path": "doc/source/examples.rst",
    "content": ".. _examples:\n\n********\nExamples\n********\n\n\nConverting Image formats\n------------------------\n\n.. code-block:: python\n\n    from ffpyplayer.pic import Image, SWScale\n    w, h = 500, 100\n    size = w * h * 3\n    buf = bytearray([int(x * 255 / size) for x in range(size)])\n\n    img = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\n    sws = SWScale(w, h, img.get_pixel_format(), ofmt='yuv420p')\n\n    img2 = sws.scale(img)\n    img2.get_pixel_format()\n    'yuv420p'\n    planes = img2.to_bytearray()\n    map(len, planes)\n    [50000, 12500, 12500, 0]\n\n.. _dshow-example:\n\nPlaying a webcam with DirectShow on windows\n-------------------------------------------\n\nOne can use :meth:`~ffpyplayer.tools.list_dshow_devices` to get a list of the\ndevices and their option for playing. For example:\n\n.. code-block:: python\n\n    # see http://ffmpeg.org/ffmpeg-formats.html#Format-Options for rtbufsize\n    # lets use the yuv420p, 320x240, 30fps\n    # 27648000 = 320*240*3 at 30fps, for 4 seconds.\n    # see http://ffmpeg.org/ffmpeg-devices.html#dshow for video_size, and framerate\n    lib_opts = {'framerate':'30', 'video_size':'320x240',\n    'pixel_format': 'yuv420p', 'rtbufsize':'27648000'}\n    ff_opts = {'f':'dshow'}\n    player = MediaPlayer('video=Logitech HD Webcam C525:audio=Microphone (HD Webcam C525)',\n                         ff_opts=ff_opts, lib_opts=lib_opts)\n\n    while 1:\n        frame, val = player.get_frame()\n        if val == 'eof':\n            break\n        elif frame is None:\n            time.sleep(0.01)\n        else:\n            img, t = frame\n            print val, t, img.get_pixel_format(), img.get_buffer_size()\n            time.sleep(val)\n    0.0 264107.429 rgb24 (230400, 0, 0, 0)\n    0.0 264108.364 rgb24 (230400, 0, 0, 0)\n    0.0790016651154 264108.628 rgb24 (230400, 0, 0, 0)\n    0.135997533798 264108.764 rgb24 (230400, 0, 0, 0)\n    0.274529457092 264108.897 rgb24 (230400, 0, 0, 0)\n    0.272421836853 264109.028 rgb24 (230400, 0, 0, 0)\n    0.132406949997 264109.164 rgb24 (230400, 0, 0, 0)\n    ...\n\n    # NOTE, by default the output was rgb24. To keep the output format the\n    # same as the input, do ff_opts['out_fmt'] = 'yuv420p'\n\n\nSaving an image to disk\n-----------------------\n\n.. code-block:: python\n\n    from ffpyplayer.pic import Image, SWScale\n    from ffpyplayer.tools import get_supported_pixfmts\n\n    # create image\n    w, h = 500, 100\n    fmt = 'rgb24'\n    size = w * h * 3\n    buf = bytearray([int(x * 255 / size) for x in range(size)])\n    img = Image(plane_buffers=[buf], pix_fmt=fmt, size=(w, h))\n    codec = 'tiff'  # we'll encode it using the tiff codec\n\n    # make sure the output codec supports the input pixel format type\n    # otherwise, convert it to the best pixel format\n    ofmt = get_supported_pixfmts(codec, fmt)[0]\n    if ofmt != fmt:\n        sws = SWScale(w, h, fmt, ofmt=ofmt)\n        img = sws.scale(img)\n        fmt = ofmt\n\n    out_opts = {'pix_fmt_in': fmt, 'width_in': w, 'height_in': h,\n                'frame_rate': (30, 1), 'codec': codec}\n    writer = MediaWriter('myfile.tiff', [out_opts])\n    writer.write_frame(img=img, pts=0, stream=0)\n    writer.close()\n\n    # to save the file as a compressed tiff using lzw\n    writer = MediaWriter('myfile.tiff', [out_opts], lib_opts={'compression_algo': 'lzw'})\n    writer.write_frame(img=img, pts=0, stream=0)\n    writer.close()\n\nSimple transcoding example\n--------------------------\n\n.. code-block:: python\n\n    from ffpyplayer.player import MediaPlayer\n    from ffpyplayer.writer import MediaWriter\n    import time, weakref\n\n    # only video\n    ff_opts={'an':True, 'sync':'video'}\n    player = MediaPlayer(filename, ff_opts=ff_opts)\n    # wait for size to be initialized (todo: add timeout and check for quitting)\n    while player.get_metadata()['src_vid_size'] == (0, 0):\n        time.sleep(0.01)\n\n    frame_size = player.get_metadata()['src_vid_size']\n    # use the same size as the inputs\n    out_opts = {'pix_fmt_in':'rgb24', 'width_in':frame_size[0],\n                'height_in':frame_size[1], 'codec':'rawvideo',\n                'frame_rate':(30, 1)}\n\n    writer = MediaWriter(filename_out, [out_opts])\n    while 1:\n        frame, val = player.get_frame()\n        if val == 'eof':\n            break\n        elif frame is None:\n            time.sleep(0.01)\n        else:\n            img, t = frame\n            writer.write_frame(img=img, pts=t, stream=0)\n\nMore complex transcoding example\n--------------------------------\n\n.. code-block:: python\n\n    from ffpyplayer.player import MediaPlayer\n    from ffpyplayer.tools import free_frame_ref\n    from ffpyplayer.writer import MediaWriter\n    import time, weakref\n\n    # only video, output yuv420p frames\n    ff_opts={'an':True, 'sync':'video', 'out_fmt':'yuv420p'}\n    player = MediaPlayer(filename, ff_opts=ff_opts)\n    # wait for size to be initialized\n    while player.get_metadata()['src_vid_size'] == (0, 0):\n        time.sleep(0.01)\n\n    frame_size = player.get_metadata()['src_vid_size']\n    # use the half the size for the output as the input\n    out_opts = {'pix_fmt_in':'yuv420p', 'width_in':frame_size[0],\n                'height_in':frame_size[1], 'codec':'rawvideo',\n                'frame_rate':(30, 1), 'width_out':frame_size[0] / 2,\n                'height_out':frame_size[1] / 2}\n\n    writer = MediaWriter(filename_out, [out_opts])\n    while 1:\n        frame, val = player.get_frame()\n        if val == 'eof':\n            break\n        elif frame is None:\n            time.sleep(0.01)\n        else:\n            img, t = frame\n            writer.write_frame(img=img, pts=t, stream=0)\n\n.. _write-simple:\n\nWriting video to file\n---------------------\n\n.. code-block:: python\n\n    from ffpyplayer.writer import MediaWriter\n    from ffpyplayer.pic import Image\n\n    w, h = 640, 480\n    # write at 5 fps.\n    out_opts = {'pix_fmt_in':'rgb24', 'width_in':w, 'height_in':h, 'codec':'rawvideo',\n                'frame_rate':(5, 1)}\n    # write using rgb24 frames into a two stream rawvideo file where the output\n    # is half the input size for both streams. Avi format will be used.\n    writer = MediaWriter('output.avi', [out_opts] * 2, width_out=w/2,\n                         height_out=h/2)\n\n    # Construct images\n    size = w * h * 3\n    buf = bytearray([int(x * 255 / size) for x in range(size)])\n    img = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\n\n    buf = bytearray([int((size - x) * 255 / size) for x in range(size)])\n    img2 = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\n\n    for i in range(20):\n        writer.write_frame(img=img, pts=i / 5., stream=0)  # stream 1\n        writer.write_frame(img=img2, pts=i / 5., stream=1)  # stream 2\n\nOr force an output format of avi, even though the filename is .mp4.:\n\n.. code-block:: python\n\n    writer = MediaWriter('output.mp4', [out_opts] * 2, fmt='avi',\n                          width_out=w/2, height_out=h/2)\n\n.. _write-h264:\n\nCompressing video to h264\n-------------------------\n\nOr writing compressed h264 files (notice the file is now only 5KB, while\nthe above results in a 10MB file):\n\n.. code-block:: python\n\n    from ffpyplayer.writer import MediaWriter\n    from ffpyplayer.tools import get_supported_pixfmts, get_supported_framerates\n    from ffpyplayer.pic import Image\n\n    # make sure the pixel format and rate are supported.\n    print get_supported_pixfmts('libx264', 'rgb24')\n    #['yuv420p', 'yuvj420p', 'yuv422p', 'yuvj422p', 'yuv444p', 'yuvj444p', 'nv12', 'nv16']\n    print get_supported_framerates('libx264', (5, 1))\n    #[]\n    w, h = 640, 480\n    out_opts = {'pix_fmt_in':'rgb24', 'width_in':w, 'height_in':h, 'codec':'libx264',\n                'frame_rate':(5, 1)}\n\n    # use the following libx264 compression options\n    lib_opts = {'preset':'slow', 'crf':'22'}\n    # set the following metadata (ffmpeg doesn't always support writing metadata)\n    metadata = {'title':'Singing in the sun', 'author':'Rat', 'genre':'Animal sounds'}\n\n    # write using yuv420p frames into a two stream h264 codec, mp4 file where the output\n    # is half the input size for both streams.\n    writer = MediaWriter('output.avi', [out_opts] * 2, fmt='mp4',\n                         width_out=w/2, height_out=h/2, pix_fmt_out='yuv420p',\n                         lib_opts=lib_opts, metadata=metadata)\n\n    # Construct images\n    size = w * h * 3\n    buf = bytearray([int(x * 255 / size) for x in range(size)])\n    img = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\n\n    buf = bytearray([int((size - x) * 255 / size) for x in range(size)])\n    img2 = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\n\n    for i in range(20):\n        writer.write_frame(img=img, pts=i / 5., stream=0)  # stream 1\n        writer.write_frame(img=img2, pts=i / 5., stream=1)  # stream 2\n"
  },
  {
    "path": "doc/source/getting_started.rst",
    "content": ".. _started:\n\n####################\n  Getting Started\n####################\n\n.. toctree::\n   :maxdepth: 2\n\n   installation.rst\n   examples.rst\r\n"
  },
  {
    "path": "doc/source/index.rst",
    "content": ".. FFPyPlayer documentation master file, created by\n   sphinx-quickstart on Mon Dec 23 18:07:03 2013.\n   You can adapt this file completely to your liking, but it should at least\n   contain the root `toctree` directive.\n\nWelcome to FFPyPlayer's documentation!\n======================================\n\nContents:\n\n.. toctree::\n   :maxdepth: 2\n\n   getting_started.rst\n   api.rst\n\n*  :ref:`genindex`\n*  :ref:`modindex`\n*  :ref:`search`\n"
  },
  {
    "path": "doc/source/installation.rst",
    "content": ".. _install:\n\n************\nInstallation\n************\n\nUsing binary wheels\n-------------------\n\nOn windows 7+ (64 or 32 bit) and linux (64 bit), ffpyplayer wheels can be installed for\npython 3.5+ using::\n\n    pip install ffpyplayer\n\n.. warning::\n\n    Although the ffpyplayer source code is licensed under the LGPL, the ffpyplayer wheels\n    on PYPI are distributed under the GPL because the  FFmpeg binaries\n    are GPL'd. For LGPL builds you can compile FFmpeg yourself using LGPL options.\n\nFor other OSs or to compile with master see below.\n\nCompiling\n---------\n\nRequirements\n============\n\nTo compile ffpyplayer we need:\n\n    * Cython (``pip install --upgrade cython~=3.0.11``).\n    * A c compiler e.g. gcc or MSVC.\n    * SDL2 or SDL1.2 (SDL1.2 is not recommended). See :ref:`compille` for how to get it.\n    * SDL2_mixer If wanting to play multiple audio files simultaneously (``USE_SDL2_MIXER`` must be set). See :ref:`compille` for how to get it.\n    * A recent (2.x+, has been tested with 2.8) FFmpeg compiled with ``--enable-shared``.\n      See :ref:`compille` for how to get it.\n\nCompiling ffpyplayer\n====================\n\n* Download or compile FFMpeg and SDL2 as shown below and set the appropriate environment variables as needed.\n* Install Cython with e.g.::\n\n      pip install --upgrade cython~=3.0.11\n\n* You can select the FFmpeg libraries to be used by defining values for CONFIG_XXX.\n  For example, CONFIG_AVFILTER=0 will disable inclusion of the FFmpeg avfilter libraries.\n  See setup.py for all the available flags.\n* To use SDL2_mixer, which is required when multiple audio files are to be played\n  simultaneously (or even when they are open at the same time) environment variable ``USE_SDL2_MIXER``\n  must be set to 1 when compiling. SDL2_mixer binaries and headers must also be available.\n* Finally, run::\n\n      pip install ffpyplayer\n\n  Or to install master, do::\n\n      pip install https://github.com/matham/ffpyplayer/archive/master.zip\n\n  If you have a local directory with the ffpyplayer source code. To compile, you can run within that directory\n  * ``make`` on linux, or\n  * ``python setup.py build_ext --inplace``, or\n  * ``pip install -e .`` to also properly install it.\n\nYou should now be able to import ffpyplayer with ``import ffpyplayer``.\n\n.. _compille\n\nSDL and Compiling FFmpeg\n------------------------\n\nTo use ffpyplayer, the compiled FFmpeg and SDL shared libraries must be available. Following are\ninstructions for the various OSs.\n\nWindows\n=======\n\nYou can get pre-compiled FFmpeg libaries from http://ffmpeg.zeranoe.com/builds/. You need\nboth the shared (which contains the .a files and headers) and the dev (which contains the dlls)\ndownloads.\n\nYou can download SDL2 from https://www.libsdl.org/release/. 2.0.4 is the most recent\n`version <https://www.libsdl.org/release/SDL2-devel-2.0.4-mingw.tar.gz>`_.\n\nYou can download SDL2_mixer from https://www.libsdl.org/projects/SDL_mixer/. 2.0.1 is the most recent\n`version <https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-devel-2.0.1-mingw.tar.gz>`_.\n\n* If there's a root directory containing a ``include`` and ``lib`` directory, each containing the header\n  and compiled binaries, respectively, then ``FFMPEG_ROOT`` and ``SDL_ROOT`` can be set to these\n  root directories for ffmpeg and sdl, respectively. Otherwise,\n* ``SDL_LIB_DIR`` and ``FFMPEG_LIB_DIR`` should point to a folder which contains the\n  SDL and FFmpeg compiled shared libraries (*.dll), respectively.\n* ``FFMPEG_INCLUDE_DIR`` should point to a directory which contains the FFmpeg header files.\n* ``SDL_INCLUDE_DIR`` should point to a directory containg the SDL headers. For SDL2,\n  this directory contains a SDL2 named directory with all the headers.\n\nIn addition, directories containing the SDL and FFmpeg shared libraries (*.dll) need to be added to the PATH.\n\nOSX\n===\n\nYou can get both FFmpeg and SDL2 using brew. You can install them using::\n\n    brew update\n    brew install sdl2 sdl2_mixer ffmpeg\n\nOtherwise, follow the Linux instructions.\n\nLinux\n======\n\nUbuntu 18.04\n~~~~~~~~~~~~\n\nOn Ubuntu 18.04, the following command will install the python, ffmpeg, and sdl2 dependencies::\n\n    sudo apt install ffmpeg libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev \\\n    libavutil-dev libswscale-dev libswresample-dev libpostproc-dev libsdl2-dev libsdl2-2.0-0 \\\n    libsdl2-mixer-2.0-0 libsdl2-mixer-dev python3-dev\n\nOther Linux platforms\n~~~~~~~~~~~~~~~~~~~~~~\n\nFFMpeg\n^^^^^^^\n\nFollow the instructions at https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu to compile FFMpeg.\nHowever, those instructions detail how to build the static version. We need the shared\nversion. This means that ``--enable-shared`` and ``--extra-cflags=\"-fPIC\"`` need to be added\nwhen compiling FFmpeg **AND** its dependencies. And if present, ``--disable-shared`` or\n``--enable-static`` must be removed.\n\nFollowing that guide, ``export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/ffmpeg_build/lib`` also needs\nto be executed for the compiled binaries to be found.\n\nSDL2\n^^^^^\n\nSDL2 can usually be gotten from the package manager, e.g. in Ubuntu 16.04 you can do the following::\n\n    sudo apt-get update\n    sudo apt-get -y install libsdl2-dev libsdl2-mixer-dev\n\nPython Headers\n^^^^^^^^^^^^^^^\n\nThe Python headers are required for compilation, on Ubuntu you can get it with::\n\n    sudo apt-get install python3-dev\n\nFor either ffmpeg or sdl2 if manually compiled, ``PKG_CONFIG_PATH`` will need to be set to the path\ncontaining the generated `*.pc` files and ``pkg-config`` will need to be available. *Otherwise,* if\ninstalled to a non-standard location, the paths to the compiled shared libraries and headers will need to be set with\n\n* If there's a root directory containing a ``include`` and ``lib`` directory, each containing the header\n  and compiled binaries, respectively, then ``FFMPEG_ROOT`` and ``SDL_ROOT`` can be set to these\n  root directories for ffmpeg and sdl, respectively. Otherwise,\n* ``SDL_LIB_DIR`` and ``FFMPEG_LIB_DIR`` should point to a folder which contains the\n  SDL and FFmpeg compiled shared libraries (*.so), respectively.\n* ``FFMPEG_INCLUDE_DIR`` should point to a directory which contains the FFmpeg header files.\n* ``SDL_INCLUDE_DIR`` should point to a directory containg the SDL headers. For SDL2,\n  this directory contains a SDL2 named directory with all the headers.\n\nIn addition, directories containing the SDL and FFmpeg shared libraries (*.so) need to be added to the PATH.\n\nYou can find a complete minimal example of compiling ffpyplayer on Ubuntu\n`here <https://github.com/matham/ffpyplayer/blob/master/.travis.yml#L20>`_.\nA more complete example used to build the wheels is\n`here <https://github.com/matham/ffpyplayer/blob/master/.travis/build-wheels.sh>`_.\n\n"
  },
  {
    "path": "doc/source/pic.rst",
    "content": ".. _pic-api:\n\n******\nImages\n******\n\n:mod:`ffpyplayer.pic`\n=============================\n\n.. automodule:: ffpyplayer.pic\n   :members:\n   :undoc-members:\n   :show-inheritance:\r\n"
  },
  {
    "path": "doc/source/player.rst",
    "content": ".. _player-api:\n\n******\nPlayer\n******\n\n:mod:`ffpyplayer.player`\n=============================\n\n.. automodule:: ffpyplayer.player\n   :members:\n   :undoc-members:\n   :show-inheritance:\r\n"
  },
  {
    "path": "doc/source/tools.rst",
    "content": ".. _tools-api:\n\n*****\nTools\n*****\n\n:mod:`ffpyplayer.tools`\n=============================\n\n.. automodule:: ffpyplayer.tools\n   :members:\n   :undoc-members:\n   :show-inheritance:\n\n.. autoattribute:: ffpyplayer.tools.loglevels\n\n    A dictionary with all the available ffmpeg log levels. The keys are the loglevels\n    and the values are their ffmpeg values. The lower the value, the more important\n    the log. Note, this is ooposite python where the higher the level the more important\n    the log.\n\n.. autoattribute:: ffpyplayer.tools.codecs_enc\n\n    A list of all the codecs available for encoding video.\n\n.. autoattribute:: ffpyplayer.tools.codecs_dec\n\n    A list of all the codecs available for decoding video and audio.\n\n.. autoattribute:: ffpyplayer.tools.pix_fmts\n\n    A list of all the pixel formats available to ffmpeg.\n\n.. autoattribute:: ffpyplayer.tools.formats_in\n\n    A list of all the formats (e.g. file formats) available for reading.\n\n.. autoattribute:: ffpyplayer.tools.formats_out\n\n    A list of all the formats (e.g. file formats) available for writing.\n"
  },
  {
    "path": "doc/source/writer.rst",
    "content": ".. _writer-api:\n\n******\nWriter\n******\n\n:mod:`ffpyplayer.writer`\n=============================\n\n.. automodule:: ffpyplayer.writer\n   :members:\n   :undoc-members:\n   :show-inheritance:\n"
  },
  {
    "path": "examples/test.py",
    "content": "'''\nTo run, please provide a filename on the command line when running the file.\n'''\n\n\nimport kivy\nfrom kivy.base import EventLoop\nEventLoop.ensure_window()\nfrom ffpyplayer.player import MediaPlayer\nfrom ffpyplayer.tools import set_log_callback, loglevels\nfrom kivy.clock import Clock\nfrom kivy.graphics.texture import Texture\nfrom kivy.app import App\nfrom kivy.core.window import Window\nfrom kivy.lang import Builder\nfrom kivy.uix.relativelayout import RelativeLayout\nfrom kivy.weakmethod import WeakMethod\nimport sys\nimport time\nfrom threading import RLock, Thread\nimport logging\nlogging.root.setLevel(logging.DEBUG)\n\n\nBuilder.load_string('''\n<Root>:\n    id: rt\n    image: img\n    volume: volume\n    seek: seek\n    Image:\n        id: img\n        size_hint: 0.95, 0.95\n        pos: 0.05 * rt.width, 0.05 * rt.height\n        allow_stretch: False\n        on_size: app.resize()\n    ProgressBar:\n        id: seek\n        size_hint: 0.95, 0.05\n        pos: 0.05 * rt.width, 0\n        on_touch_down: app.touch_down(args[1])\n        value: 0\n    Slider:\n        id: volume\n        orientation: 'vertical'\n        size_hint: 0.05, 1.\n        pos: 0.0, 0.0\n        step: 0.01\n        value: 1.\n        range: 0., 1.\n        on_value: app.ffplayer and app.ffplayer.set_volume(self.value)\n''')\n\nclass Root(RelativeLayout):\n    pass\n\nlog_level = 'debug'\nlogger_func = {'quiet': logging.critical, 'panic': logging.critical,\n               'fatal': logging.critical, 'error': logging.error,\n               'warning': logging.warning, 'info': logging.info,\n               'verbose': logging.debug, 'debug': logging.debug}\n\n\ndef log_callback(message, level):\n    message = message.strip()\n    if message:\n        logger_func[level]('ffpyplayer: {}'.format(message))\n\n\nclass PlayerApp(App):\n\n    def __init__(self, **kwargs):\n        super(PlayerApp, self).__init__(**kwargs)\n        self.texture = None\n        self.size = (0, 0)\n        self.next_frame = None\n        self._done = False\n        self._lock = RLock()\n        self._thread = Thread(target=self._next_frame, name='Next frame')\n        self._trigger = Clock.create_trigger(self.redraw)\n        self._force_refresh = False\n\n    def build(self):\n        self.root = Root()\n        return self.root\n\n    def on_start(self):\n        self.callback_ref = WeakMethod(self.callback)\n        filename = sys.argv[1]\n        logging.info('ffpyplayer: Playing file \"{}\"'.format(filename))\n        # try ff_opts = {'vf':'edgedetect'} http://ffmpeg.org/ffmpeg-filters.html\n        ff_opts = {}\n        self.ffplayer = MediaPlayer(filename, callback=self.callback_ref,\n                                    loglevel=log_level, ff_opts=ff_opts)\n        self._thread.start()\n        self.keyboard = Window.request_keyboard(None, self.root)\n        self.keyboard.bind(on_key_down=self.on_keyboard_down)\n\n    def resize(self):\n        if self.ffplayer:\n            w, h = self.ffplayer.get_metadata()['src_vid_size']\n            if not h:\n                return\n            lock = self._lock\n            lock.acquire()\n            if self.root.image.width < self.root.image.height * w / float(h):\n                self.ffplayer.set_size(-1, self.root.image.height)\n            else:\n                self.ffplayer.set_size(self.root.image.width, -1)\n            lock.release()\n            logging.debug('ffpyplayer: Resized video.')\n\n    def update_pts(self, *args):\n        if self.ffplayer:\n            self.root.seek.value = self.ffplayer.get_pts()\n\n    def on_keyboard_down(self, keyboard, keycode, text, modifiers):\n        if not self.ffplayer:\n            return False\n        lock = self._lock\n        ctrl = 'ctrl' in modifiers\n        if keycode[1] == 'p' or keycode[1] == 'spacebar':\n            logging.info('Toggled pause.')\n            self.ffplayer.toggle_pause()\n        elif keycode[1] == 'r':\n            logging.debug('ffpyplayer: Forcing a refresh.')\n            self._force_refresh = True\n        elif keycode[1] == 'v':\n            logging.debug('ffpyplayer: Changing video stream.')\n            lock.acquire()\n            self.ffplayer.request_channel('video',\n                                          'close' if ctrl else 'cycle')\n            lock.release()\n            Clock.unschedule(self.update_pts)\n            if ctrl:    # need to continue updating pts, since video is disabled.\n                Clock.schedule_interval(self.update_pts, 0.05)\n        elif keycode[1] == 'a':\n            logging.debug('ffpyplayer: Changing audio stream.')\n            lock.acquire()\n            self.ffplayer.request_channel('audio',\n                                          'close' if ctrl else 'cycle')\n            lock.release()\n        elif keycode[1] == 't':\n            logging.debug('ffpyplayer: Changing subtitle stream.')\n            lock.acquire()\n            self.ffplayer.request_channel('subtitle',\n                                          'close' if ctrl else 'cycle')\n            lock.release()\n        elif keycode[1] == 'right':\n            logging.debug('ffpyplayer: Seeking forward by 10s.')\n            self.ffplayer.seek(10.)\n        elif keycode[1] == 'left':\n            logging.debug('ffpyplayer: Seeking back by 10s.')\n            self.ffplayer.seek(-10.)\n        elif keycode[1] == 'up':\n            logging.debug('ffpyplayer: Increasing volume.')\n            self.ffplayer.set_volume(self.ffplayer.get_volume() + 0.01)\n            self.root.volume.value = self.ffplayer.get_volume()\n        elif keycode[1] == 'down':\n            logging.debug('ffpyplayer: Decreasing volume.')\n            self.ffplayer.set_volume(self.ffplayer.get_volume() - 0.01)\n            self.root.volume.value = self.ffplayer.get_volume()\n        return True\n\n    def touch_down(self, touch):\n        if self.root.seek.collide_point(*touch.pos) and self.ffplayer:\n            pts = ((touch.pos[0] - self.root.volume.width) /\n            self.root.seek.width * self.ffplayer.get_metadata()['duration'])\n            logging.debug('ffpyplayer: Seeking to {}.'.format(pts))\n            self.ffplayer.seek(pts, relative=False)\n            self._force_refresh = True\n            return True\n        return False\n\n    def callback(self, selector, value):\n        if self.ffplayer is None:\n            return\n        if selector == 'quit':\n            logging.debug('ffpyplayer: Quitting.')\n            def close(*args):\n                self._done = True\n                self.ffplayer = None\n            Clock.schedule_once(close, 0)\n        # called from internal thread, it typically reads forward\n        elif selector == 'display_sub':\n            self.display_subtitle(*value)\n\n    def _next_frame(self):\n        ffplayer = self.ffplayer\n        sleep = time.sleep\n        trigger = self._trigger\n        while not self._done:\n            force = self._force_refresh\n            if force:\n                self._force_refresh = False\n            frame, val = ffplayer.get_frame(force_refresh=force)\n\n            if val == 'eof':\n                logging.debug('ffpyplayer: Got eof.')\n                sleep(1 / 30.)\n            elif val == 'paused':\n                logging.debug('ffpyplayer: Got paused.')\n                sleep(1 / 30.)\n            else:\n                if frame:\n                    logging.debug('ffpyplayer: Next frame: {}.'.format(val))\n                    sleep(val)\n                    self.next_frame = frame\n                    trigger()\n                else:\n                    val = val if val else (1 / 30.)\n                    logging.debug('ffpyplayer: Schedule next frame check: {}.'\n                                  .format(val))\n                    sleep(val)\n\n    def redraw(self, dt=0, force_refresh=False):\n        if not self.ffplayer:\n            return\n        if self.next_frame:\n            img, pts = self.next_frame\n            if img.get_size() != self.size or self.texture is None:\n                self.root.image.canvas.remove_group(str(self)+'_display')\n                self.texture = Texture.create(size=img.get_size(),\n                                              colorfmt='rgb')\n                # by adding 'vf':'vflip' to the player initialization ffmpeg\n                # will do the flipping\n                self.texture.flip_vertical()\n                self.texture.add_reload_observer(self.reload_buffer)\n                self.size = img.get_size()\n                logging.debug('ffpyplayer: Creating new image texture of '\n                              'size: {}.'.format(self.size))\n            self.texture.blit_buffer(img.to_memoryview()[0])\n            self.root.image.texture = None\n            self.root.image.texture = self.texture\n            self.root.seek.value = pts\n            logging.debug('ffpyplayer: Blitted new frame with time: {}.'\n                          .format(pts))\n\n        if self.root.seek.value:\n            self.root.seek.max = self.ffplayer.get_metadata()['duration']\n\n    def display_subtitle(self, text, fmt, pts, t_start, t_end):\n        pass # fmt is text (unformatted), or ass (formatted subs)\n\n    def reload_buffer(self, *args):\n        logging.debug('ffpyplayer: Reloading buffer.')\n        frame = self.next_frame\n        if not frame:\n            return\n        self.texture.blit_buffer(frame[0].to_memoryview()[0], colorfmt='rgb',\n                                 bufferfmt='ubyte')\n\nif __name__ == '__main__':\n    set_log_callback(log_callback)\n    a = PlayerApp()\n    a.run()\n    # because MediaPlayer runs non-daemon threads, when the main thread exists\n    # it'll get stuck waiting for those threads to close, so we manually\n    # have to delete these threads by deleting the MediaPlayer object.\n    a._done = True\n    a.ffplayer = None\n    set_log_callback(None)\n"
  },
  {
    "path": "ffpyplayer/__init__.py",
    "content": "'''\nFFPyPlayer library\n==================\n'''\nimport sys\nimport site\nimport os\nfrom os.path import join\nimport platform\n\n__all__ = ('dep_bins', )\n\n__version__ = '4.5.4.dev0'\nversion = __version__\n\n# the ffmpeg src git version tested and upto date with,\n# and including this commit\n_ffmpeg_git = 'c926140558c60786dc577b121df6b3c6b430bd98'\n# excludes commits bdf9ed41fe4bdf4e254615b7333ab0feb1977e98,\n# 1be3d8a0cb77f8d34c1f39b47bf5328fe10c82d7,\n# f1907faab4023517af7d10d746b5684cccc5cfcc, and\n# 0995e1f1b31f6e937a1b527407ed3e850f138098 because they require ffmpeg 5.1/5.2\n# which is too new as of now\n\n# also skipped all show modes and subtitle display related functionality commits\n\n# TODO:\n# * Implement CONFIG_SDL to be able to compile without needing SDL at all.\n# * Currently, it only supports text subtitles - bitmap subtitles are ignored.\n#   Unless one uses a filter to overlay the subtitle.\n# * We can not yet visualize audio to video. Provide a filter chain link between\n#   audio to video filters to acomplish this.\n\ndep_bins = []\n'''A list of paths to the binaries used by the library. It can be used during\npackaging for including required binaries.\n\nIt is read only.\n'''\n\nfor d in [sys.prefix, site.USER_BASE]:\n    if d is None:\n        continue\n    for lib in ('ffmpeg', 'sdl'):\n        p = join(d, 'share', 'ffpyplayer', lib, 'bin')\n        if os.path.isdir(p):\n            os.environ[\"PATH\"] = p + os.pathsep + os.environ[\"PATH\"]\n            if hasattr(os, 'add_dll_directory'):\n                os.add_dll_directory(p)\n            dep_bins.append(p)\n\nif 'SDL_AUDIODRIVER' not in os.environ and platform.system() == 'Windows':\n    os.environ['SDL_AUDIODRIVER'] = 'DirectSound'\n"
  },
  {
    "path": "ffpyplayer/clib/misc.c",
    "content": "\n#include \"misc.h\"\n\n#define FLAGS (o->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0\nvoid print_all_libs_info(int flags, int level)\n{\n#if CONFIG_AVUTIL\n    PRINT_LIB_INFO(avutil,   AVUTIL,   flags, level);\n#endif\n#if CONFIG_AVCODEC\n    PRINT_LIB_INFO(avcodec,  AVCODEC,  flags, level);\n#endif\n#if CONFIG_AVFORMAT\n    PRINT_LIB_INFO(avformat, AVFORMAT, flags, level);\n#endif\n#if CONFIG_AVDEVICE\n    PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level);\n#endif\n#if CONFIG_AVFILTER\n    PRINT_LIB_INFO(avfilter, AVFILTER, flags, level);\n#endif\n#if CONFIG_SWSCALE\n    PRINT_LIB_INFO(swscale,  SWSCALE,  flags, level);\n#endif\n#if CONFIG_SWRESAMPLE\n    PRINT_LIB_INFO(swresample,SWRESAMPLE,  flags, level);\n#endif\n#if CONFIG_POSTPROC\n    PRINT_LIB_INFO(postproc, POSTPROC, flags, level);\n#endif\n}\n\nconst AVOption *opt_find(const void * obj, const char *name, const char *unit,\n    int opt_flags, int search_flags)\n{\n    const AVOption *o = av_opt_find(obj, name, unit, opt_flags, search_flags);\n    if(o && !o->flags)\n        return NULL;\n    return o;\n}\n\n#define FLAGS (o->type == AV_OPT_TYPE_FLAGS) ? AV_DICT_APPEND : 0\nint opt_default(const char *opt, const char *arg,\n    struct SwsContext *sws_opts, AVDictionary **sws_dict, AVDictionary **swr_opts,\n    AVDictionary **resample_opts, AVDictionary **format_opts, AVDictionary **codec_opts)\n{\n    const AVOption *o;\n    int consumed = 0;\n    char opt_stripped[128];\n    const char *p;\n    const AVClass *cc = avcodec_get_class();\n    const AVClass *fc = avformat_get_class();\n#if CONFIG_AVRESAMPLE\n    const AVClass *rc = avresample_get_class();\n#endif\n#if CONFIG_SWRESAMPLE\n    struct SwrContext *swr;\n#endif\n    const AVClass *sc;\n    const AVClass *swr_class;\n    int ret;\n#if CONFIG_SWSCALE\n    struct SwsContext *sws;\n#endif\n\n\n    if (!strcmp(opt, \"debug\") || !strcmp(opt, \"fdebug\"))\n        av_log_set_level(AV_LOG_DEBUG);\n\n    if (!(p = strchr(opt, ':')))\n        p = opt + strlen(opt);\n    av_strlcpy(opt_stripped, opt, FFMIN(sizeof(opt_stripped), p - opt + 1));\n\n    if ((o = opt_find(&cc, opt_stripped, NULL, 0,\n                         AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) ||\n        ((opt[0] == 'v' || opt[0] == 'a' || opt[0] == 's') &&\n         (o = opt_find(&cc, opt + 1, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)))) {\n        av_dict_set(codec_opts, opt, arg, FLAGS);\n        consumed = 1;\n    }\n    if ((o = opt_find(&fc, opt, NULL, 0,\n                         AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {\n        av_dict_set(format_opts, opt, arg, FLAGS);\n        if (consumed)\n            av_log(NULL, AV_LOG_VERBOSE, \"Routing option %s to both codec and muxer layer\\n\", opt);\n        consumed = 1;\n    }\n#if CONFIG_SWSCALE\n    sc = sws_get_class();\n    if (sws_dict && !consumed && (o = opt_find(&sc, opt, NULL, 0,\n                         AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {\n        sws = sws_alloc_context();\n        ret = av_opt_set(sws, opt, arg, 0);\n        sws_freeContext(sws);\n        if (ret < 0) {\n            av_log(NULL, AV_LOG_ERROR, \"Error setting option %s.\\n\", opt);\n            return ret;\n        }\n        if (sws_opts){\n            ret = av_opt_set(sws_opts, opt, arg, 0);\n            if (ret < 0) {\n                av_log(NULL, AV_LOG_ERROR, \"Error setting option %s for sws_opts.\\n\", opt);\n                return ret;\n            }\n        }\n\n        av_dict_set(sws_dict, opt, arg, FLAGS);\n\n        consumed = 1;\n    }\n#else\n    if (!consumed && !strcmp(opt, \"sws_flags\")) {\n        av_log(NULL, AV_LOG_WARNING, \"Ignoring %s %s, due to disabled swscale\\n\", opt, arg);\n        consumed = 1;\n    }\n#endif\n#if CONFIG_SWRESAMPLE\n    swr_class = swr_get_class();\n    if (swr_opts && !consumed && (o=opt_find(&swr_class, opt, NULL, 0,\n                                    AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {\n        swr = swr_alloc();\n        ret = av_opt_set(swr, opt, arg, 0);\n        swr_free(&swr);\n        if (ret < 0) {\n            av_log(NULL, AV_LOG_ERROR, \"Error setting option %s.\\n\", opt);\n            return ret;\n        }\n        av_dict_set(swr_opts, opt, arg, FLAGS);\n        consumed = 1;\n    }\n#endif\n#if CONFIG_AVRESAMPLE\n    if (resample_opts && (o=opt_find(&rc, opt, NULL, 0,\n                       AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) {\n        av_dict_set(resample_opts, opt, arg, FLAGS);\n        consumed = 1;\n    }\n#endif\n\n    if (consumed)\n        return 0;\n    return AVERROR_OPTION_NOT_FOUND;\n}\n\nint get_plane_sizes(int size[4], int required_plane[4], enum AVPixelFormat pix_fmt,\n    int height, const int linesizes[4])\n{\n    int i, total_size;\n    memset(required_plane, 0, sizeof(required_plane[0])*4);\n\n    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);\n    memset(size, 0, sizeof(size[0])*4);\n\n    if (!height)\n        return AVERROR(EINVAL);\n\n    if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)\n        return AVERROR(EINVAL);\n\n    if (linesizes[0] > (INT_MAX - 1024) / height)\n        return AVERROR(EINVAL);\n    size[0] = linesizes[0] * height;\n\n    if (desc->flags & AV_PIX_FMT_FLAG_PAL) {\n        size[1] = 256 * 4;\n        required_plane[0] = 1;\n        return size[0] + size[1];\n    }\n\n    for (i = 0; i < 4; i++)\n        required_plane[desc->comp[i].plane] = 1;\n\n    total_size = size[0];\n    for (i = 1; i < 4 && required_plane[i]; i++) {\n        int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;\n        h = (height + (1 << s) - 1) >> s;\n        if (linesizes[i] > INT_MAX / h)\n            return AVERROR(EINVAL);\n        size[i] = h * linesizes[i];\n        if (total_size > INT_MAX - size[i])\n            return AVERROR(EINVAL);\n        total_size += size[i];\n    }\n\n    return total_size;\n}\n"
  },
  {
    "path": "ffpyplayer/clib/misc.h",
    "content": "\n#ifndef _FFINFO_H\n#define _FFINFO_H\n\n#include \"../includes/ffconfig.h\"\n#include \"libavcodec/avcodec.h\"\n#include \"libavfilter/avfilter.h\"\n#include \"libavformat/avformat.h\"\n#include \"libavdevice/avdevice.h\"\n#include \"libswscale/swscale.h\"\n#include \"libswresample/swresample.h\"\n#include \"libavutil/opt.h\"\n#include \"libavutil/avstring.h\"\n#include \"libavutil/pixdesc.h\"\n\n\n#if CONFIG_POSTPROC\n#include \"libpostproc/postprocess.h\"\n#endif\n\n#ifndef AV_LOG_TRACE\n#define AV_LOG_TRACE    56\n#endif\n\n\n#define INDENT        1\n#define SHOW_VERSION  2\n#define SHOW_CONFIG   4\n\n#define PRINT_LIB_INFO(libname, LIBNAME, flags, level)                  \\\n    if (CONFIG_##LIBNAME) {                                             \\\n        const char *indent = flags & INDENT? \"  \" : \"\";                 \\\n        if (flags & SHOW_VERSION) {                                     \\\n            unsigned int version = libname##_version();                 \\\n            av_log(NULL, level,                                         \\\n                   \"%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\\n\",            \\\n                   indent, #libname,                                    \\\n                   LIB##LIBNAME##_VERSION_MAJOR,                        \\\n                   LIB##LIBNAME##_VERSION_MINOR,                        \\\n                   LIB##LIBNAME##_VERSION_MICRO,                        \\\n                   version >> 16, version >> 8 & 0xff, version & 0xff); \\\n        }                                                               \\\n        if (flags & SHOW_CONFIG) {                                      \\\n            const char *cfg = libname##_configuration();                \\\n            av_log(NULL, level, \"%s%-11s configuration: %s\\n\",   \t   \t\\\n                    indent, #libname, cfg);                         \t\\\n        }                                                               \\\n    }\n\nvoid print_all_libs_info(int flags, int level);\n\nconst AVOption *opt_find(const void * obj, const char *name, const char *unit,\n                            int opt_flags, int search_flags);\n\nint opt_default(const char *opt, const char *arg,\n    struct SwsContext *sws_opts, AVDictionary **sws_dict, AVDictionary **swr_opts,\n    AVDictionary **resample_opts, AVDictionary **format_opts, AVDictionary **codec_opts);\n\nint get_plane_sizes(int size[4], int required_plane[4], enum AVPixelFormat pix_fmt,\n    int height, const int linesizes[4]);\n\n#endif\n"
  },
  {
    "path": "ffpyplayer/includes/ff_consts.pxi",
    "content": "include \"ffconfig.pxi\"\n\n\n''' Minimum SDL audio buffer size, in samples.. '''\nDEF SDL_AUDIO_MIN_BUFFER_SIZE = 512\nDEF AUDIO_MIN_BUFFER_SIZE = SDL_AUDIO_MIN_BUFFER_SIZE\n' Calculate actual buffer size keeping in mind not cause too frequent audio callbacks. '\nDEF AUDIO_MAX_CALLBACKS_PER_SEC = 30\n\nDEF MAX_QUEUE_SIZE = (15 * 1024 * 1024)\nDEF MIN_FRAMES = 25\nDEF EXTERNAL_CLOCK_MIN_FRAMES = 2\nDEF EXTERNAL_CLOCK_MAX_FRAMES = 10\n\n'no AV sync correction is done if below the minimum AV sync threshold '\nDEF AV_SYNC_THRESHOLD_MIN = 0.04\n'AV sync correction is done if above the maximum AV sync threshold '\nDEF AV_SYNC_THRESHOLD_MAX = 0.1\n'If a frame duration is longer than this, it will not be duplicated to compensate AV sync'\nDEF AV_SYNC_FRAMEDUP_THRESHOLD = 0.1\n'no AV correction is done if too big error'\nDEF AV_NOSYNC_THRESHOLD = 10.0\n\n'maximum audio speed change to get correct sync'\nDEF SAMPLE_CORRECTION_PERCENT_MAX = 10\n\n'external clock speed adjustment constants for realtime sources based on buffer fullness'\nDEF EXTERNAL_CLOCK_SPEED_MIN = 0.900\nDEF EXTERNAL_CLOCK_SPEED_MAX = 1.010\nDEF EXTERNAL_CLOCK_SPEED_STEP = 0.001\n\n'we use about AUDIO_DIFF_AVG_NB A-V differences to make the average'\nDEF AUDIO_DIFF_AVG_NB = 20\n\n'polls for possible required screen refresh at least this often, should be less than 1/fps'\nDEF REFRESH_RATE = 0.0167\n\n'''NOTE: the size must be big enough to compensate the hardware audio buffersize size\nTODO: We assume that a decoded and resampled frame fits into this buffer'''\nDEF SAMPLE_ARRAY_SIZE = (8 * 65536)\n\nDEF VIDEO_PICTURE_QUEUE_SIZE = 3\nDEF SUBPICTURE_QUEUE_SIZE = 16\nDEF SAMPLE_QUEUE_SIZE = 9\nDEF FRAME_QUEUE_SIZE = max(SAMPLE_QUEUE_SIZE, max(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE))\n\n\nDEF FF_LOCK_CREATE = 0\nDEF FF_LOCK_OBTAIN = 1\nDEF FF_LOCK_RELEASE = 2\nDEF FF_LOCK_DESTROY = 3\n"
  },
  {
    "path": "ffpyplayer/includes/ffmpeg.pxi",
    "content": "\nfrom libc.stdint cimport int64_t, uint64_t, int32_t, uint32_t, uint16_t,\\\nint16_t, uint8_t, int8_t, uintptr_t\n\ncdef extern from \"stdarg.h\":\n    ctypedef struct va_list:\n        pass\n\nctypedef int (*lockmgr_func)(void **, int)\nctypedef int (*int_void_func)(void *) except? 1\n\nctypedef float FFTSample\n\ninclude \"ff_consts.pxi\"\ninclude \"sdl.pxi\"\n\n\ncdef:\n    extern from * nogil:\n        struct AVPacket:\n            uint8_t *data\n            int64_t pos\n            int64_t pts\n            int64_t dts\n            int size\n            int stream_index\n            int flags\n            int64_t duration\n        enum AVMediaType:\n            AVMEDIA_TYPE_UNKNOWN = -1,  #///< Usually treated as AVMEDIA_TYPE_DATA\n            AVMEDIA_TYPE_VIDEO,\n            AVMEDIA_TYPE_AUDIO,\n            AVMEDIA_TYPE_DATA,          #///< Opaque data information usually continuous\n            AVMEDIA_TYPE_SUBTITLE,\n            AVMEDIA_TYPE_ATTACHMENT,    #///< Opaque data information usually sparse\n            AVMEDIA_TYPE_NB,\n        struct AVBufferRef:\n            pass\n        int av_compare_ts(int64_t, AVRational, int64_t, AVRational)\n        const char* av_get_media_type_string(AVMediaType)\n        const int av_log2(unsigned int)\n\n    extern from \"libavformat/avio.h\" nogil:\n        int AVIO_FLAG_WRITE\n        int avio_check(const char *, int)\n        int avio_open2(AVIOContext **, const char *, int, const AVIOInterruptCB *,\n                       AVDictionary **)\n        int avio_close(AVIOContext *)\n        struct AVIOContext:\n            int error\n            int eof_reached\n        struct AVIOInterruptCB:\n            int (*callback)(void*)\n            void *opaque\n        int avio_feof(AVIOContext *)\n        int64_t avio_tell(AVIOContext *)\n\n    extern from \"libavutil/fifo.h\" nogil:\n        struct AVFifoBuffer:\n            uint8_t *buffer\n        int av_fifo_space(const AVFifoBuffer *)\n        int av_fifo_grow(AVFifoBuffer *, unsigned int)\n        int av_fifo_generic_write(AVFifoBuffer *, void *, int, int (*)(void*, void*, int))\n        AVFifoBuffer *av_fifo_alloc(unsigned int)\n        int av_fifo_size(const AVFifoBuffer *)\n        int av_fifo_generic_read(AVFifoBuffer *, void *, int, void (*)(void*, void*, int))\n        void av_fifo_freep(AVFifoBuffer **)\n\n    extern from \"libavutil/eval.h\" nogil:\n        double av_strtod(const char *, char **)\n\n    extern from \"libavutil/avstring.h\" nogil:\n         size_t av_strlcpy(char *, const char *, size_t)\n         size_t av_strlcatf(char *, size_t, const char *, ...)\n         char *av_asprintf(const char *, ...)\n\n    extern from \"libavutil/display.h\" nogil:\n        double av_display_rotation_get (const int32_t [])\n\n    extern from \"libavutil/mathematics.h\" nogil:\n        int64_t av_rescale_q(int64_t, AVRational, AVRational)\n\n    extern from \"libavutil/pixdesc.h\" nogil:\n        struct AVPixFmtDescriptor:\n            const char *name\n            uint8_t nb_components\n        const char *av_get_pix_fmt_name(AVPixelFormat)\n        AVPixelFormat av_get_pix_fmt(const char *)\n        const AVPixFmtDescriptor *av_pix_fmt_desc_next(const AVPixFmtDescriptor *)\n        AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *)\n        const AVPixFmtDescriptor *av_pix_fmt_desc_get(AVPixelFormat)\n\n    extern from \"libavutil/imgutils.h\" nogil:\n        int av_image_alloc(uint8_t **, int *, int, int, AVPixelFormat, int)\n        int av_image_fill_linesizes(int *, AVPixelFormat, int)\n        void av_image_copy(uint8_t **, int *, const uint8_t **, const int *,\n                           AVPixelFormat, int, int)\n        int av_image_fill_pointers(uint8_t **, AVPixelFormat, int, uint8_t *,\n                                   const int *linesizes)\n        int av_image_fill_arrays(uint8_t **, int *, const uint8_t *,\n                                 AVPixelFormat, int, int, int)\n\n    extern from \"libavutil/dict.h\" nogil:\n        int AV_DICT_MATCH_CASE\n        int AV_DICT_DONT_OVERWRITE\n        int AV_DICT_IGNORE_SUFFIX\n        int AV_DICT_DONT_STRDUP_VAL\n        struct AVDictionaryEntry:\n            char *key\n            char *value\n        void av_dict_free(AVDictionary **)\n        AVDictionaryEntry * av_dict_get(AVDictionary *, const char *,\n                                        const AVDictionaryEntry *, int)\n\n    extern from \"libavutil/samplefmt.h\" nogil:\n        enum AVSampleFormat:\n            AV_SAMPLE_FMT_S16,\n            AV_SAMPLE_FMT_NONE,\n        AVSampleFormat av_get_packed_sample_fmt(AVSampleFormat)\n        const char *av_get_sample_fmt_name(AVSampleFormat)\n        int av_samples_get_buffer_size(int *, int, int, AVSampleFormat, int)\n        int av_get_bytes_per_sample(AVSampleFormat)\n\n    extern from \"libavutil/time.h\" nogil:\n        int av_usleep(unsigned)\n        int64_t av_gettime_relative()\n\n    extern from \"libavutil/cpu.h\" nogil:\n        int av_get_cpu_flags()\n        int av_parse_cpu_caps(unsigned *, const char *)\n        void av_force_cpu_flags(int)\n\n    extern from * nogil:\n        void av_free(void *)\n        void av_freep(void *)\n        void *av_malloc(size_t)\n        void *av_realloc_array(void *, size_t, size_t)\n        char *av_strdup(const char *)\n        int av_get_channel_layout_nb_channels(uint64_t)\n        void av_get_channel_layout_string(char *, int, int, uint64_t)\n        int64_t av_get_default_channel_layout(int)\n        int av_clip(int a, int amin, int amax)\n        int64_t AV_CH_LAYOUT_STEREO_DOWNMIX\n\n        struct AVRational:\n            int num #///< numerator\n            int den #///< denominator\n        double av_q2d(AVRational)\n        int av_find_nearest_q_idx(AVRational, const AVRational*)\n\n        int AV_LOG_QUIET\n        int AV_LOG_PANIC\n        int AV_LOG_FATAL\n        int AV_LOG_ERROR\n        int AV_LOG_WARNING\n        int AV_LOG_INFO\n        int AV_LOG_VERBOSE\n        int AV_LOG_DEBUG\n        int AV_LOG_TRACE\n        int AV_LOG_SKIP_REPEATED\n        void av_log(void *, int, const char *, ...)\n        void av_log_set_flags(int)\n        void av_log_set_level(int)\n        void av_log_set_callback(void (*)(void*, int, const char*, va_list))\n        void av_log_default_callback(void*, int, const char*, va_list)\n        void av_log_format_line(void *, int, const char *, va_list, char *, int, int *)\n\n        enum AVPixelFormat:\n            AV_PIX_FMT_YUV420P,\n            AV_PIX_FMT_RGB24,\n            AV_PIX_FMT_NONE,\n\n        int64_t AV_NOPTS_VALUE\n\n        struct AVDictionary:\n            pass\n        int av_dict_set(AVDictionary **, const char *, const char *, int)\n        int av_dict_set_int(AVDictionary **, const char *, int64_t, int)\n\n        void av_max_alloc(size_t)\n\n        void *av_mallocz(size_t)\n\n        int AVERROR(int)\n        int AVUNERROR(int)\n\n        enum AVPictureType:\n            AV_PICTURE_TYPE_NONE\n        char av_get_picture_type_char(AVPictureType)\n        void av_frame_unref(AVFrame *)\n        void av_frame_free(AVFrame **)\n        void av_frame_move_ref(AVFrame *, AVFrame *)\n        AVFrame* av_frame_clone(const AVFrame *)\n        int av_frame_copy_props(AVFrame *, const AVFrame *)\n        int av_frame_get_buffer(AVFrame *, int)\n        unsigned av_int_list_length_for_size(unsigned, const void *, uint64_t)\n        int av_opt_set_bin(void *, const char *, const uint8_t *, int, int)\n\n        AVFrame *av_frame_alloc()\n        int64_t av_frame_get_pkt_pos(const AVFrame *)\n        int av_frame_get_channels(const AVFrame *)\n\n        int AVERROR_EOF\n        int AVERROR_OPTION_NOT_FOUND\n        int av_strerror(int, char *, size_t)\n\n        void *av_x_if_null(const void *p, const void *x)\n\n        int64_t AV_TIME_BASE\n        AVRational AV_TIME_BASE_Q\n\n        struct AVClass:\n            pass\n\n    extern from \"libavformat/avformat.h\" nogil:\n        int AVSEEK_FLAG_BYTE\n        int AVFMT_NOBINSEARCH\n        int AVFMT_NOGENSEARCH\n        int AVFMT_NO_BYTE_SEEK\n        int AVFMT_FLAG_GENPTS\n        int AVFMT_TS_DISCONT\n        int AV_DISPOSITION_ATTACHED_PIC\n        int AVFMT_GLOBALHEADER\n        int AVFMT_VARIABLE_FPS\n        int AVFMT_NOTIMESTAMPS\n        int AVFMT_NOFILE\n        int AVFMT_RAWPICTURE\n        struct AVChapter:\n            int id\n            AVRational time_base\n            int64_t start\n            int64_t end\n            AVDictionary *metadata\n        struct AVInputFormat:\n            int (*read_seek)(AVFormatContext *, int, int64_t, int)\n            int (*get_device_list)(AVFormatContext *, AVDeviceInfoList *)\n            int (*create_device_capabilities)(AVFormatContext *, AVDeviceCapabilitiesQuery *)\n            int flags\n            const char *name\n            const char *long_name\n            const char *extensions\n        struct AVCodecTag:\n            pass\n        struct AVOutputFormat:\n            const char *name\n            const char *long_name\n            const char *extensions\n            int flags\n            AVCodecID video_codec\n            const AVCodecTag* const* codec_tag\n        struct AVFormatContext:\n            AVInputFormat *iformat\n            AVOutputFormat *oformat\n            AVStream **streams\n            AVProgram **programs\n            unsigned int nb_streams\n            unsigned int nb_programs\n            AVIOContext *pb\n            AVDictionary *metadata\n            AVIOInterruptCB interrupt_callback\n            int flags\n            int64_t start_time\n            int bit_rate\n            int64_t duration\n            unsigned int nb_chapters\n            AVChapter **chapters\n            char *url\n        struct AVStream:\n            int index\n            AVRational time_base\n            int64_t start_time\n            AVDiscard discard\n            AVPacket attached_pic\n            int disposition\n            AVRational avg_frame_rate\n            AVRational r_frame_rate\n            AVDictionary *metadata\n            AVCodecParameters *codecpar\n        struct AVProgram:\n            int id\n            unsigned int nb_stream_indexes\n            unsigned int *stream_index\n        enum  AVPacketSideDataType:\n            AV_PKT_DATA_DISPLAYMATRIX\n        void av_format_inject_global_side_data(AVFormatContext *)\n        int avformat_network_init()\n        int avformat_network_deinit()\n        AVInputFormat *av_find_input_format(const char *)\n        AVRational av_guess_sample_aspect_ratio(AVFormatContext *, AVStream *, AVFrame *)\n        AVRational av_guess_frame_rate(AVFormatContext *, AVStream *, AVFrame *)\n        int avformat_match_stream_specifier(AVFormatContext *, AVStream *,\n                                            const char *)\n        AVFormatContext *avformat_alloc_context()\n        int avformat_open_input(AVFormatContext **, const char *, AVInputFormat *, AVDictionary **)\n        void avformat_close_input(AVFormatContext **)\n        int avformat_find_stream_info(AVFormatContext *, AVDictionary **)\n        int avformat_seek_file(AVFormatContext *, int, int64_t, int64_t, int64_t, int)\n        int av_find_best_stream(AVFormatContext *, AVMediaType, int, int, AVCodec **, int)\n        void av_dump_format(AVFormatContext *, int, const char *, int)\n        int av_read_pause(AVFormatContext *)\n        int av_read_play(AVFormatContext *)\n        int av_read_frame(AVFormatContext *, AVPacket *)\n        AVProgram *av_find_program_from_stream(AVFormatContext *, AVProgram *, int)\n        int avformat_write_header(AVFormatContext *, AVDictionary **)\n        int av_write_trailer(AVFormatContext *)\n        int avformat_alloc_output_context2(AVFormatContext **, AVOutputFormat *,\n                                           const char *, const char *)\n        AVStream *avformat_new_stream(AVFormatContext *, const AVCodec *)\n        int av_interleaved_write_frame(AVFormatContext *, AVPacket *)\n        void avformat_free_context(AVFormatContext *)\n        uint8_t *av_stream_get_side_data (AVStream *, AVPacketSideDataType, int *)\n        const AVOutputFormat *av_muxer_iterate(void **)\n        const AVInputFormat *av_demuxer_iterate(void **)\n\n    extern from \"libavdevice/avdevice.h\" nogil:\n        void avdevice_register_all()\n        struct AVDeviceInfo:\n            char *device_name\n            char *device_description\n        struct AVDeviceInfoList:\n            AVDeviceInfo **devices\n            int nb_devices\n            int default_device\n        struct AVDeviceCapabilitiesQuery:\n            pass\n\n    extern from \"libswscale/swscale.h\" nogil:\n        int SWS_BICUBIC\n        struct SwsContext:\n            pass\n        struct SwsFilter:\n            pass\n        const AVClass *sws_get_class()\n        SwsContext *sws_getContext(int, int, AVPixelFormat, int, int, AVPixelFormat,\n                                   int, SwsFilter *, SwsFilter *, const double *)\n        SwsContext *sws_getCachedContext(SwsContext *, int, int, AVPixelFormat,\n                                        int, int, AVPixelFormat, int, SwsFilter *,\n                                        SwsFilter *, const double *)\n        int sws_scale(SwsContext *, const uint8_t *const [], const int[], int, int,\n                      uint8_t *const [], const int[])\n        void sws_freeContext(SwsContext *)\n\n    extern from \"libavutil/frame.h\" nogil:\n        enum AVFrameSideDataType:\n            AV_FRAME_DATA_DISPLAYMATRIX,\n        struct AVFrameSideData:\n            uint8_t *data\n        AVFrameSideData *av_frame_get_side_data(const AVFrame *, AVFrameSideDataType)\n\n    extern from \"libavutil/opt.h\" nogil:\n        int AV_OPT_SEARCH_CHILDREN\n        int AV_OPT_FLAG_ENCODING_PARAM\n        int AV_OPT_FLAG_DECODING_PARAM\n        int AV_OPT_FLAG_VIDEO_PARAM\n        int AV_OPT_FLAG_AUDIO_PARAM\n        int AV_OPT_FLAG_SUBTITLE_PARAM\n        int AV_OPT_SEARCH_FAKE_OBJ\n        struct AVOption:\n            pass\n        int av_opt_eval_flags(void *, const AVOption *, const char *, int *)\n        int av_opt_get_int(void *, const char *, int, int64_t *)\n        int av_opt_set_int(void *, const char *, int64_t, int)\n        int av_opt_set_image_size(void *, const char *, int, int, int)\n        int av_opt_set(void *, const char *, const char *, int)\n        const AVOption *av_opt_find(void *, const char *, const char *, int, int)\n\n    extern from \"libavcodec/packet.h\" nogil:\n        int av_packet_ref(AVPacket *, const AVPacket *)\n        void av_packet_unref(AVPacket *)\n        void av_packet_move_ref(AVPacket *, AVPacket *)\n        AVPacket *av_packet_alloc()\n        void av_packet_free(AVPacket **)\n\n    extern from \"libavcodec/avfft.h\" nogil:\n        enum RDFTransformType:\n            DFT_R2C,\n            IDFT_C2R,\n            IDFT_R2C,\n            DFT_C2R,\n        struct RDFTContext:\n            pass\n        void av_rdft_end(RDFTContext *)\n        RDFTContext *av_rdft_init(int, RDFTransformType)\n        void av_rdft_calc(RDFTContext *, FFTSample *)\n\n    extern from \"libavcodec/version.h\" nogil:\n        pass\n\n    extern from \"libswresample/swresample.h\" nogil:\n        struct SwrContext:\n            pass\n        void swr_free(SwrContext **)\n        SwrContext *swr_alloc_set_opts(SwrContext *, int64_t, AVSampleFormat,\n                                       int, int64_t, AVSampleFormat, int, int, void *)\n        int swr_init(SwrContext *)\n        int swr_set_compensation(SwrContext *, int, int)\n        int swr_convert(SwrContext *, uint8_t **, int, const uint8_t ** , int)\n\n    extern from \"libavcodec/avcodec.h\" nogil:\n        int AV_CODEC_FLAG2_FAST\n        int AV_CODEC_CAP_DR1\n        int AV_CODEC_FLAG_GLOBAL_HEADER\n        int AV_PKT_FLAG_KEY\n        int AV_CODEC_CAP_DELAY\n        struct AVCodec:\n            const char *name\n            int capabilities\n            const AVClass *priv_class\n            AVCodecID id\n            uint8_t max_lowres\n            const AVRational *supported_framerates\n            const AVPixelFormat *pix_fmts\n            AVMediaType type\n        struct AVCodecContext:\n            int width\n            int height\n            int64_t pts_correction_num_faulty_pts  # Number of incorrect PTS values so far\n            int64_t pts_correction_num_faulty_dts  # Number of incorrect DTS values so far\n            AVRational sample_aspect_ratio\n            AVRational time_base\n            const AVCodec *codec\n            AVCodecID codec_id\n            AVMediaType codec_type\n            int workaround_bugs\n            int lowres\n            int error_concealment\n            int flags\n            int flags2\n            int sample_rate\n            int channels\n            uint64_t channel_layout\n            AVSampleFormat sample_fmt\n            AVPixelFormat pix_fmt\n            AVFrame *coded_frame\n            AVRational pkt_timebase\n        struct AVCodecParameters:\n            AVCodecID codec_id\n            AVMediaType codec_type\n            AVRational sample_aspect_ratio\n            int sample_rate\n            int channels\n        struct AVSubtitle:\n            uint16_t format\n            uint32_t start_display_time # relative to packet pts, in ms\n            uint32_t end_display_time   # relative to packet pts, in ms\n            unsigned num_rects\n            AVSubtitleRect **rects\n            int64_t pts\n        struct AVFrame:\n            int top_field_first\n            int interlaced_frame\n            AVPictureType pict_type\n            AVRational sample_aspect_ratio\n            int width, height\n            int format\n            int key_frame\n            int64_t pts\n            int64_t pkt_pts\n            int64_t pkt_dts\n            int sample_rate\n            int nb_samples\n            uint64_t channel_layout\n            uint8_t **extended_data\n            int64_t best_effort_timestamp\n            uint8_t **data\n            int *linesize\n            int channels\n            int64_t pkt_pos\n            AVBufferRef **buf\n        struct AVPicture:\n            uint8_t **data\n            int *linesize\n        struct AVSubtitleRect:\n            int x         #///< top left corner  of pict, undefined when pict is not set\n            int y         #///< top left corner  of pict, undefined when pict is not set\n            int w         #///< width            of pict, undefined when pict is not set\n            int h         #///< height           of pict, undefined when pict is not set\n            AVPicture pict\n            int nb_colors\n            char *text\n            char *ass\n            AVSubtitleType type\n        enum AVSubtitleType:\n            SUBTITLE_NONE\n            SUBTITLE_BITMAP\n            SUBTITLE_TEXT\n            SUBTITLE_ASS\n        AVRational av_codec_get_pkt_timebase(const AVCodecContext *)\n        int64_t av_frame_get_best_effort_timestamp(const AVFrame *)\n        int av_codec_get_max_lowres(const AVCodec *)\n        void av_codec_set_lowres(AVCodecContext *, int)\n        int avcodec_parameters_from_context(AVCodecParameters *, const AVCodecContext *)\n        int av_dup_packet(AVPacket *)\n        void av_packet_unref(AVPacket *)\n        void avsubtitle_free(AVSubtitle *)\n        void av_fast_malloc(void *, unsigned int *, size_t)\n        void avcodec_register_all()\n        int avcodec_close(AVCodecContext *)\n        int avcodec_send_packet(AVCodecContext *, const AVPacket *)\n        int avcodec_receive_frame(AVCodecContext *, AVFrame *)\n        void avcodec_flush_buffers(AVCodecContext *)\n        void av_init_packet(AVPacket *)\n        int avcodec_parameters_to_context(AVCodecContext *, const AVCodecParameters *)\n        void av_codec_set_pkt_timebase(AVCodecContext *, AVRational)\n        void av_picture_copy(AVPicture *, const AVPicture *,\n                             AVPixelFormat, int, int)\n        AVFrame* av_frame_alloc()\n        int avcodec_decode_subtitle2(AVCodecContext *, AVSubtitle *,\n                                     int *, AVPacket *)\n        int avcodec_decode_audio4(AVCodecContext *, AVFrame *, int *, const AVPacket *)\n        enum AVCodecID:\n            AV_CODEC_ID_NONE\n            AV_CODEC_ID_RAWVIDEO\n        AVCodec *avcodec_find_decoder(AVCodecID)\n        AVCodec *avcodec_find_encoder(AVCodecID)\n        AVCodec *avcodec_find_encoder_by_name(const char *)\n        AVCodec *avcodec_find_decoder_by_name(const char *)\n        const AVClass *avcodec_get_class()\n        AVCodecContext *avcodec_alloc_context3(const AVCodec *)\n        void avcodec_free_context(AVCodecContext **)\n        int avcodec_open2(AVCodecContext *, const AVCodec *, AVDictionary **)\n        enum AVDiscard:\n            AVDISCARD_DEFAULT,\n            AVDISCARD_ALL\n        int av_copy_packet(AVPacket *, AVPacket *)\n        struct AVCodecDescriptor:\n            AVCodecID id\n            const char *name\n            AVMediaType type\n        const AVCodecDescriptor *avcodec_descriptor_get(AVCodecID)\n        const AVCodecDescriptor *avcodec_descriptor_next(const AVCodecDescriptor *)\n        const AVCodecDescriptor *avcodec_descriptor_get_by_name(const char *)\n        AVPixelFormat avcodec_find_best_pix_fmt_of_list(AVPixelFormat *, AVPixelFormat,\n                                                        int, int *)\n        int avpicture_fill(AVPicture *, const uint8_t *, AVPixelFormat, int, int)\n        int avcodec_encode_video2(AVCodecContext *, AVPacket *, const AVFrame *, int *)\n        const char *avcodec_get_name(AVCodecID)\n        const AVCodec *av_codec_iterate(void **)\n        int av_codec_is_encoder(const AVCodec *)\n        int av_codec_is_decoder(const AVCodec *)\n        int avcodec_send_frame(AVCodecContext *, const AVFrame *)\n        int avcodec_receive_packet(AVCodecContext *, AVPacket *)\n\n    extern from \"libavfilter/avfilter.h\" nogil:\n        struct AVFilterContext:\n            AVFilterLink **inputs\n        struct AVFilterLink:\n            AVRational time_base\n            int sample_rate\n            int channels\n            uint64_t channel_layout\n            AVRational frame_rate\n        struct AVFilterGraph:\n            char *scale_sws_opts\n            unsigned nb_filters\n            AVFilterContext **filters\n            int nb_threads\n        struct AVFilterInOut:\n            char *name\n            AVFilterContext *filter_ctx\n            int pad_idx\n            AVFilterInOut *next\n        struct AVFilter:\n            pass\n        int avfilter_link_get_channels(AVFilterLink *)\n        AVFilterInOut *avfilter_inout_alloc()\n        void avfilter_inout_free(AVFilterInOut **)\n        int avfilter_graph_parse_ptr(AVFilterGraph *, const char *,\n                                     AVFilterInOut **, AVFilterInOut **,\n                                     void *)\n        int avfilter_link(AVFilterContext *, unsigned,\n                          AVFilterContext *, unsigned)\n        int avfilter_graph_config(AVFilterGraph *, void *)\n        int avfilter_graph_create_filter(AVFilterContext **, const AVFilter *,\n                                         const char *, const char *, void *,\n                                         AVFilterGraph *)\n        AVFilter *avfilter_get_by_name(const char *)\n        void avfilter_graph_free(AVFilterGraph **)\n        AVFilterGraph *avfilter_graph_alloc()\n\n    extern from \"libavfilter/buffersink.h\" nogil:\n        int av_buffersink_get_frame_flags(AVFilterContext *, AVFrame *, int)\n        AVRational av_buffersink_get_time_base(const AVFilterContext *)\n        AVRational av_buffersink_get_frame_rate(const AVFilterContext *)\n        int av_buffersink_get_sample_rate(const AVFilterContext *)\n        int av_buffersink_get_channels(const AVFilterContext *)\n        uint64_t av_buffersink_get_channel_layout(const AVFilterContext *)\n\n    extern from \"libavfilter/buffersrc.h\" nogil:\n        int av_buffersrc_add_frame(AVFilterContext *, AVFrame *)\n\n    extern from \"clib/misc.h\" nogil:\n        uint8_t INDENT\n        uint8_t SHOW_VERSION\n        uint8_t SHOW_CONFIG\n        void print_all_libs_info(int, int)\n        int opt_default(\n            const char *, const char *, SwsContext *, AVDictionary **, AVDictionary **,\n            AVDictionary **, AVDictionary **, AVDictionary **)\n        int get_plane_sizes(int *, int *, AVPixelFormat, int, const int *)\n\ncdef enum:\n    AV_SYNC_AUDIO_MASTER, # default choice\n    AV_SYNC_VIDEO_MASTER,\n    AV_SYNC_EXTERNAL_CLOCK, # synchronize to an external clock\n"
  },
  {
    "path": "ffpyplayer/includes/inline_funcs.pxi",
    "content": "\ncdef extern from \"string.h\" nogil:\n    char *strerror(int)\n\ncdef extern from \"errno.h\" nogil:\n    int EINVAL\n    int EDOM\n\ncdef extern from \"limits.h\" nogil:\n    int INT_MAX\n\nimport sys\n\ncdef int PY3 = sys.version_info > (3, )\n\ncdef inline int FFMAX(int a, int b) nogil:\n    if a > b:\n        return a\n    else:\n        return b\ncdef inline double FFMAXD(double a, double b) nogil:\n    if a > b:\n        return a\n    else:\n        return b\ncdef inline void * FFMAXptr(void *a, void *b) nogil:\n    if a > b:\n        return a\n    else:\n        return b\ncdef inline int FFMIN(int a, int b) nogil:\n    if a > b:\n        return b\n    else:\n        return a\ncdef inline double FFMIND(double a, double b) nogil:\n    if a > b:\n        return b\n    else:\n        return a\ncdef inline void * FFMINptr(void *a, void *b) nogil:\n    if a > b:\n        return b\n    else:\n        return a\ncdef inline int compute_mod(int a, int b) nogil:\n    if a < 0:\n        return a%b + b\n    else:\n        return a%b\n\ncdef inline int av_opt_set_int_list(void *obj, const char *name, const void *val,\n                                    size_t val_deref_size, uint64_t term, int flags) nogil:\n    if av_int_list_length_for_size(val_deref_size, val, term) > INT_MAX / val_deref_size:\n        return AVERROR(EINVAL)\n    else:\n        return av_opt_set_bin(obj, name, <const uint8_t *>val,\\\n        av_int_list_length_for_size(val_deref_size, val, term) * val_deref_size, flags)\n\ncdef inline int cmp_audio_fmts(AVSampleFormat fmt1, int64_t channel_count1,\n                   AVSampleFormat fmt2, int64_t channel_count2) nogil:\n    # If channel count == 1, planar and non-planar formats are the same\n    if channel_count1 == 1 and channel_count2 == 1:\n        return av_get_packed_sample_fmt(fmt1) != av_get_packed_sample_fmt(fmt2)\n    else:\n        return channel_count1 != channel_count2 or fmt1 != fmt2\n\ncdef inline int64_t get_valid_channel_layout(int64_t channel_layout, int channels) nogil:\n    if channel_layout and av_get_channel_layout_nb_channels(channel_layout) == channels:\n        return channel_layout\n    else:\n        return 0\n\ncdef inline char * emsg(int code, char *msg, int buff_size) except NULL:\n    if av_strerror(code, msg, buff_size) < 0:\n        if EDOM > 0:\n            code = -code\n        return strerror(code)\n    return msg\n\ncdef inline char * fmt_err(int code, char *msg, int buff_size) nogil:\n    if av_strerror(code, msg, buff_size) < 0:\n        if EDOM > 0:\n            code = -code\n        return strerror(code)\n    return msg\n\ncdef inline int insert_filt(\n        const char *name, const char *arg, AVFilterGraph *graph,\n        AVFilterContext **last_filter) nogil:\n    cdef int ret\n    cdef AVFilterContext *filt_ctx\n\n    ret = avfilter_graph_create_filter(\n        &filt_ctx, avfilter_get_by_name(name), name, arg, NULL, graph)\n    if ret < 0:\n        return ret\n\n    ret = avfilter_link(filt_ctx, 0, last_filter[0], 0)\n    if ret < 0:\n        return ret\n\n    last_filter[0] = filt_ctx\n    return 0\n\ncdef inline object tcode(bytes s):\n    if PY3:\n        return s.decode('utf8')\n    return s\n"
  },
  {
    "path": "ffpyplayer/includes/sdl.pxi",
    "content": "from libc.stdint cimport int64_t, uint64_t, int32_t, uint32_t, uint16_t,\\\nint16_t, uint8_t, int8_t, uintptr_t\n\ncdef extern from \"SDL.h\" nogil:\n    int SDL_INIT_VIDEO\n    int SDL_INIT_AUDIO\n    int SDL_INIT_TIMER\n    int SDL_INIT_EVENTTHREAD\n\n    void SDL_Delay(int)\n\n    void SDL_WaitThread(SDL_Thread *, int *)\n    struct SDL_mutex:\n        pass\n    struct SDL_Thread:\n        pass\n    struct SDL_cond:\n        pass\n\n    char *SDL_GetError()\n\n    SDL_cond *SDL_CreateCond()\n    void SDL_DestroyCond(SDL_cond *)\n    int SDL_CondSignal(SDL_cond *)\n    int SDL_CondWait(SDL_cond *, SDL_mutex *)\n\n    void SDL_Quit()\n    int SDL_Init(uint32_t) with gil\n    int SDL_InitSubSystem(uint32_t) with gil\n\n    struct SDL_AudioSpec:\n        int freq\n        uint16_t format\n        uint8_t channels\n        uint8_t silence\n        uint16_t samples\n        uint16_t padding\n        uint32_t size\n        void (*callback)(void *, uint8_t *, int)\n        void *userdata\n\n\ncdef extern from \"SDL_thread.h\" nogil:\n    SDL_Thread *SDL_CreateThread(int_void_func, const char *, void *) with gil\n\nIF USE_SDL2_MIXER:\n    cdef extern from \"SDL_mixer.h\" nogil:\n        struct Mix_Chunk:\n            int allocated\n            uint8_t *abuf\n            uint32_t alen\n            uint8_t volume\n\n        int Mix_OpenAudio(int, uint16_t, int, int)\n        int Mix_QuerySpec(int *, uint16_t *, int *)\n        void Mix_CloseAudio()\n\n        Mix_Chunk *Mix_QuickLoad_RAW(uint8_t *, uint32_t)\n        void Mix_FreeChunk(Mix_Chunk *)\n\n        int Mix_AllocateChannels(int)\n        int Mix_PlayChannel(int, Mix_Chunk *, int)\n        int Mix_Volume(int, int)\n        int Mix_RegisterEffect(int, void (*)(int, void *, int, void *), void (*)(int, void *), void *)\n        int Mix_UnregisterEffect(int, void (*)(int, void *, int, void *))\n        void Mix_Pause(int)\n        void Mix_Resume(int)\n        int Mix_HaltChannel(int)\n\n\ncdef extern from * nogil:\n    uint32_t SDL_HWACCEL\n    uint32_t SDL_ASYNCBLIT\n    uint32_t SDL_HWSURFACE\n    uint32_t SDL_FULLSCREEN\n    uint32_t SDL_RESIZABLE\n    uint32_t SDL_YV12_OVERLAY\n    uint8_t SDL_MIX_MAXVOLUME\n\n    uint16_t AUDIO_S16SYS\n    int SDL_OpenAudio(SDL_AudioSpec *, SDL_AudioSpec *)\n    int SDL_AUDIO_ALLOW_ANY_CHANGE\n    ctypedef uint32_t SDL_AudioDeviceID\n    SDL_AudioDeviceID SDL_OpenAudioDevice(\n        const char*, int, const SDL_AudioSpec*, SDL_AudioSpec*, int)\n    void SDL_PauseAudioDevice(SDL_AudioDeviceID, int)\n    void SDL_CloseAudioDevice(SDL_AudioDeviceID)\n    void SDL_MixAudioFormat(\n        uint8_t*, const uint8_t*, uint16_t, uint32_t, int)\n\n    void SDL_PauseAudio(int)\n    void SDL_CloseAudio()\n    void SDL_MixAudio(uint8_t *, const uint8_t *, uint32_t, int)\n\n    SDL_mutex *SDL_CreateMutex()\n    void SDL_DestroyMutex(SDL_mutex *)\n    int SDL_mutexP(SDL_mutex *) # SDL_LockMutex\n    int SDL_mutexV(SDL_mutex *) # SDL_UnlockMutex\n    int SDL_CondWaitTimeout(SDL_cond *, SDL_mutex *, uint32_t)\n\n    void SDL_UpdateRect(SDL_Surface *, int32_t, int32_t, uint32_t, uint32_t)\n    int SDL_FillRect(SDL_Surface *, SDL_Rect *, uint32_t)\n    int SDL_LockYUVOverlay(SDL_Overlay *)\n    void SDL_UnlockYUVOverlay(SDL_Overlay *)\n    int SDL_DisplayYUVOverlay(SDL_Overlay *, SDL_Rect *)\n    void SDL_FreeYUVOverlay(SDL_Overlay *)\n    uint32_t SDL_MapRGB(const SDL_PixelFormat * const, const uint8_t,\n                        const uint8_t, const uint8_t)\n    SDL_Overlay * SDL_CreateYUVOverlay(int, int, uint32_t, SDL_Surface *)\n\n    void SDL_WM_SetCaption(const char *, const char *)\n    int SDL_setenv(const char *, const char *, int)\n    char * SDL_getenv(const char *)\n\n    SDL_Surface *SDL_SetVideoMode(int, int, int, uint32_t)\n    const SDL_VideoInfo *SDL_GetVideoInfo()\n    uint8_t SDL_EventState(uint8_t, int)\n    void SDL_PumpEvents()\n\n    int SDL_IGNORE\n    uint8_t SDL_ACTIVEEVENT\n    uint8_t SDL_SYSWMEVENT\n    enum:\n        SDL_VIDEOEXPOSE,\n        SDL_USEREVENT,\n        SDL_QUIT,\n        SDL_VIDEORESIZE,\n    uint32_t SDL_ALLEVENTS\n\n    struct SDL_VideoInfo:\n        int current_w\n        int current_h\n    struct SDL_Overlay:\n        int w, h                  #/**< Read-only */\n        uint16_t *pitches         #/**< Read-only */\n        uint8_t **pixels          #/**< Read-write */\n    struct SDL_PixelFormat:\n        pass\n    struct SDL_Rect:\n        int16_t x, y\n        uint16_t w, h\n    struct SDL_Surface:\n        SDL_PixelFormat *format\n        int w, h\n\n\n    struct SDL_UserEvent:\n        uint8_t type\n        int code\n        void *data1\n        void *data2\n    struct SDL_ResizeEvent:\n        uint8_t type\n        int w\n        int h\n    union SDL_Event:\n        uint8_t type\n        SDL_UserEvent user\n        SDL_ResizeEvent resize\n    enum SDL_eventaction:\n        SDL_ADDEVENT,\n        SDL_PEEKEVENT,\n        SDL_GETEVENT,\n    int SDL_PushEvent(SDL_Event *event)\n    int SDL_PeepEvents(SDL_Event *, int, SDL_eventaction, uint32_t)\n\n    int SDL_ShowCursor(int)\n"
  },
  {
    "path": "ffpyplayer/pic.pxd",
    "content": "include 'includes/ffmpeg.pxi'\n\n\ncdef class SWScale(object):\n    cdef SwsContext *sws_ctx\n    cdef bytes dst_pix_fmt\n    cdef str dst_pix_fmt_s\n    cdef int dst_h\n    cdef int dst_w\n    cdef AVPixelFormat src_pix_fmt\n    cdef int src_h\n    cdef int src_w\n\n\ncdef class Image(object):\n\n    cdef AVFrame *frame\n    cdef list byte_planes\n    cdef AVPixelFormat pix_fmt\n\n    cdef int cython_init(self, AVFrame *frame) nogil except 1\n    cpdef is_ref(Image self)\n    cpdef is_key_frame(Image self)\n    cpdef get_linesizes(Image self, keep_align=*)\n    cpdef get_size(Image self)\n    cpdef get_pixel_format(Image self)\n    cpdef get_buffer_size(Image self, keep_align=*)\n    cpdef get_required_buffers(Image self)\n    cpdef to_bytearray(Image self, keep_align=*)\n    cpdef to_memoryview(Image self, keep_align=*)\n\n\ncdef class ImageLoader(object):\n    cdef AVFormatContext *format_ctx\n    cdef AVCodec *codec\n    cdef AVCodecContext *codec_ctx\n    cdef AVPacket pkt\n    cdef AVFrame *frame\n    cdef bytes filename\n    cdef char msg[256]\n    cdef int eof\n\n    cpdef next_frame(self)\n    cdef inline object eof_frame(self)\n"
  },
  {
    "path": "ffpyplayer/pic.pyx",
    "content": "'''\nFFmpeg based image storage and conversion tools\n===============================================\n\nFFmpeg based classes to store and convert images from / to many different pixel\nformats. See :class:`Image` and :class:`SWScale` for details.\n\nCreate an image in rgb24 format:\n\n.. code-block:: python\n\n    >>> w, h = 500, 100\n    >>> size = w * h * 3\n    >>> buf = bytearray([int(x * 255 / size) for x in range(size)])\n    >>> img = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\n\nConvert the image to a different size:\n\n.. code-block:: python\n\n    >>> sws = SWScale(w, h, img.get_pixel_format(), ow=w/2, oh=h/3)\n    >>> img2 = sws.scale(img)\n    >>> img2.get_size()\n    (250, 33)\n\nConvert the image to YUV420P and get the resulting plane buffers as bytearrays:\n\n.. code-block:: python\n\n    >>> sws = SWScale(w, h, img.get_pixel_format(), ofmt='yuv420p')\n    >>> img2 = sws.scale(img)\n    >>> img2.get_pixel_format()\n    'yuv420p'\n    >>> planes = img2.to_bytearray()\n    >>> map(len, planes)\n    [50000, 12500, 12500, 0]\n\nCreate an Image using default FFmpeg buffers:\n\n.. code-block:: python\n\n    >>> img = Image(pix_fmt='rgb24', size=(w, h))\n\nCopy the image:\n\n.. code-block:: python\n\n    >>> import copy\n    >>> # copy reference without actually copying the buffers\n    >>> img2 = copy.copy(img)\n    >>> # do deep copy\n    >>> img2 = copy.deepcopy(img)\n'''\n\n__all__ = ('Image', 'SWScale', 'get_image_size', 'ImageLoader')\n\ninclude \"includes/inline_funcs.pxi\"\n\nfrom cpython.ref cimport PyObject\nfrom cython cimport view as cyview\n\ncdef extern from \"string.h\" nogil:\n    void *memset(void *, int, size_t)\n    void *memcpy(void *, const void *, size_t)\n\ncdef extern from \"Python.h\":\n    PyObject* PyString_FromStringAndSize(const char *, Py_ssize_t)\n    void Py_DECREF(PyObject *)\n\nimport ffpyplayer.tools  # for initialization purposes\n\ndef get_image_size(pix_fmt, width, height):\n    '''Returns the size in bytes of the buffers of each plane of an image with a\n    given pixel format, width, and height.\n\n    :Parameters:\n\n        `pix_fmt`: str\n            The pixel format in which the image is represented. Can be one of\n            :attr:`~ffpyplayer.tools.pix_fmts`.\n        `width`: int\n            The width of the image.\n        `height`: int\n            The height of the image.\n\n    :returns:\n\n        `4-tuple of ints`:\n            A tuple of buffer sizes in bytes for each plane of this pixel format\n            required to store the image. Unused planes are zero.\n\n    :\n\n    .. code-block:: python\n\n        >>> print get_image_size('rgb24', 100, 100)\n        (30000, 0, 0, 0)\n        >>> print get_image_size('yuv420p', 100, 100)\n        (10000, 2500, 2500, 0)\n        >>> print get_image_size('gray', 100, 100)\n        (10000, 1024, 0, 0)\n    '''\n    cdef AVPixelFormat fmt\n    cdef int res, w = width, h = height\n    cdef int size[4]\n    cdef int ls[4]\n    cdef int req[4]\n    cdef char msg[256]\n    cdef bytes fmtb\n\n    if not pix_fmt or not width or not height:\n        return 0\n\n    fmtb = pix_fmt.encode('utf8')\n    fmt = av_get_pix_fmt(fmtb)\n    if fmt == AV_PIX_FMT_NONE:\n        raise Exception('Pixel format %s not found.' % pix_fmt)\n    res = av_image_fill_linesizes(ls, fmt, w)\n    if res < 0:\n        raise Exception('Failed to initialize linesizes: ' + tcode(emsg(res, msg, sizeof(msg))))\n\n    res = get_plane_sizes(size, req, fmt, h, ls)\n    if res < 0:\n        raise Exception('Failed to get planesizes: ' + tcode(emsg(res, msg, sizeof(msg))))\n    return (size[0], size[1], size[2], size[3])\n\n\ncdef class SWScale(object):\n    '''Converts Images from one format and size to another format and size.\n\n    The class accepts an Image of a given pixel format and size and converts it\n    to another Image with a different pixel format and size. Each SWScale instance\n    converts only images with parameters specified when creating the instance.\n\n    :Parameters:\n\n        `iw, ih`: int\n            The width and height of the source image.\n        `ifmt`: str\n            The pixel format of the source image. Can be one of\n            :attr:`ffpyplayer.tools.pix_fmts`.\n        `ow, oh`: int\n            The width and height of the output image after converting from the\n            source image. A value of 0 will set that parameter to the source\n            height/width. A value of -1 for one of the parameters, will result in\n            a value of that parameter that maintains the original aspect ratio.\n            Defaults to -1.\n        `ofmt`: str\n            The pixel format of the output image. Can be one of\n            :attr:`ffpyplayer.tools.pix_fmts`. If empty, the source pixel format\n            will be used. Defaults to empty string.\n\n    :\n\n    .. code-block:: python\n\n        >>> w, h = 500, 100\n        >>> size = w * h * 3\n        >>> buf = bytearray([int(x * 255 / size) for x in range(size)])\n        >>> img = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\n\n        >>> # specify output w,h\n        >>> sws = SWScale(w, h, img.get_pixel_format(), ow=w/2, oh=h/3)\n        >>> img2 = sws.scale(img)\n        >>> img2.get_size()\n        (250, 33)\n\n        >>> # use input height\n        >>> sws = SWScale(w, h, img.get_pixel_format(), ow=w/2, oh=0)\n        >>> img2 = sws.scale(img)\n        >>> img2.get_size()\n        (250, 100)\n\n        >>> # keep aspect ratio\n        >>> sws = SWScale(w, h, img.get_pixel_format(), ow=w/2)\n        >>> img2 = sws.scale(img)\n        >>> img2.get_size()\n        (250, 50)\n\n        >>> # convert rgb24 to yuv420p\n        >>> sws = SWScale(w, h, img.get_pixel_format(), ofmt='yuv420p')\n        >>> img2 = sws.scale(img)\n        >>> img2.get_pixel_format()\n        'yuv420p'\n\n        >>> # convert into a previously allocated and aligned image\n        >>> import math\n        >>> align = lambda x: int(math.ceil(x / 32.) * 32)\n        >>> img2 = Image(pix_fmt=img.get_pixel_format(), size=(w/2, h/2))\n        >>> img2.get_linesizes(keep_align=True)\n        (750, 0, 0, 0)\n        >>> linesize = map(align, img2.get_linesizes())\n        >>> linesize\n        [768, 0, 0, 0]\n        >>> img2 = Image(pix_fmt=img2.get_pixel_format(), size=img2.get_size(), linesize=linesize)\n        >>> img2.get_linesizes(keep_align=True)\n        (768, 0, 0, 0)\n        >>> sws.scale(img, dst=img2)\n        <ffpyplayer.pic.Image object at 0x02B44440>\n        >>> img2\n        <ffpyplayer.pic.Image object at 0x02B44440>\n\n    '''\n\n    def __cinit__(self, int iw, int ih, ifmt, int ow=-1, int oh=-1, ofmt='', **kargs):\n        cdef AVPixelFormat src_pix_fmt, dst_pix_fmt\n        self.dst_pix_fmt = ifmt.encode('utf8')\n        self.dst_pix_fmt_s = ifmt\n\n        self.sws_ctx = NULL\n        src_pix_fmt = av_get_pix_fmt(self.dst_pix_fmt)\n        if src_pix_fmt == AV_PIX_FMT_NONE:\n            raise Exception('Pixel format %s not found.' % ifmt)\n        dst_pix_fmt = src_pix_fmt\n        if ofmt:\n            self.dst_pix_fmt = ofmt.encode('utf8')\n            self.dst_pix_fmt_s = ofmt\n            dst_pix_fmt = av_get_pix_fmt(self.dst_pix_fmt)\n            if dst_pix_fmt == AV_PIX_FMT_NONE:\n                raise Exception('Pixel format %s not found.' % ofmt)\n        if ow == -1 and oh == -1:\n            ow = oh = 0\n        if not oh:\n            oh = ih\n        if not ow:\n            ow = iw\n        if ow == -1:\n            ow = <int>(oh / <double>ih * iw)\n        if oh == -1:\n            oh = <int>(ow / <double>iw * ih)\n        self.dst_w = ow\n        self.dst_h = oh\n        self.src_pix_fmt = src_pix_fmt\n        self.src_w = iw\n        self.src_h = ih\n\n        self.sws_ctx = sws_getCachedContext(NULL, iw, ih, src_pix_fmt, ow, oh,\n                                            dst_pix_fmt, SWS_BICUBIC, NULL, NULL, NULL)\n        if self.sws_ctx == NULL:\n            raise Exception('Cannot initialize the conversion context.')\n\n    def __dealloc__(self):\n        if self.sws_ctx != NULL:\n            sws_freeContext(self.sws_ctx)\n\n    def scale(self, Image src, Image dst=None, int _flip=False):\n        '''Scales a image into another image format and/or size as specified by the\n        instance initialization parameters.\n\n        :Parameters:\n\n            `src`: :class:`Image`\n                A image instance with values matching the source image specification\n                of this instance. An exception is raised if the Image doesn't match.\n                It will be used as the source image.\n            `dst`: :class:`Image` or None\n                A image instance with values matching the output image specification\n                of this instance. An exception is raised if the Image doesn't match.\n                If specified, the output image will be converted directly into this Image.\n                If not specified, a new Image will be created and returned.\n            `_flip`: bool, defaults to False\n                Whether the image will be flipped before scaling. This only works\n                for pixel formats whose color planes are the same size (e.g. rgb), so\n                use with caution.\n\n        :returns:\n\n            :class:`Image`:\n                The output image. If ``dst`` was not None ``dst`` will be returned,\n                otherwise a new image containing the converted image will be returned.\n        '''\n        if (<AVPixelFormat>src.frame.format != self.src_pix_fmt or\n            self.src_w != src.frame.width or self.src_h != src.frame.height):\n            raise Exception(\"Source image doesn't match the specified input parameters.\")\n        if not dst:\n            dst = Image.__new__(Image, pix_fmt=self.dst_pix_fmt_s,\n                                size=(self.dst_w, self.dst_h))\n        with nogil:\n            if _flip:\n                for i in range(4):\n                    (<uint8_t * *>src.frame.data)[i] += src.frame.linesize[i] * (src.frame.height - 1)\n                    src.frame.linesize[i] = -src.frame.linesize[i]\n            sws_scale(self.sws_ctx, <const uint8_t *const *>src.frame.data, src.frame.linesize,\n                          0, src.frame.height, dst.frame.data, dst.frame.linesize)\n            if _flip:\n                for i in range(4):\n                    src.frame.linesize[i] = -src.frame.linesize[i]\n                    (<uint8_t * *>src.frame.data)[i] -= src.frame.linesize[i] * (src.frame.height - 1)\n        return dst\n\n\ncdef int raise_exec(object ecls) nogil except 1:\n    with gil:\n        raise ecls()\n\n\ncdef class Image(object):\n    '''Stores a image using a specified pixel format.\n\n    An Image can be represented by many different pixel formats, which determines\n    how the buffer representing it is stored. We store the buffers as one to\n    four arrays of bytes representing the one to four planes. For example,\n    RGB23 has all the data in the first plane in the form of RGBRGB... while\n    YUV420P uses the first three planes.\n\n    The Image can be initialized with a list of the plane buffers, or internal\n    buffers can be created when none are provided. Depending on how it's initialized\n    one or more params need to be specified.\n\n    :Paramters:\n\n        `plane_buffers`: list\n            A list of bytes or bytearray type objects representing the 1-4 planes.\n            The number of planes is determined by ``pix_fmt`` (e.g. 1 for RGB24,\n            3 for yuv). The length of the bytes object in each plane is a function\n            of ``size``, and if provided, also ``linesize``. See ``linesize`` for details.\n            The buffers are used directly without making any copies therefore, the\n            bytes objects are kept alive internally as long as this instance is alive.\n\n            If empty, internal buffers for the image will be created for the image.\n        `pix_fmt`: str\n            The pixel format of the image. Can be one of :attr:`ffpyplayer.tools.pix_fmts`.\n            Must be provided when using ``plane_buffers``.\n        `size`: 2-tuple of ints\n            The size of the frame in the form of (width, height).\n            Must be provided when using ``plane_buffers``.\n        `linesize`: list of ints\n            The linesize of each provided plane. In addition to the width of the frame,\n            a linesize can be provided. The ``linesize`` represent the actual number of\n            bytes in each line, and may be padded at the end to satisfy some alignment\n            requirement. For example, a RGB24 frame of size ``(100, 10)`` will have\n            ``3 * 100 = 300`` bytes in each horizontal line and will be 3000 bytes large.\n            But, when 32 bit alignment is required, the buffer will have to padded at the\n            end so that each line is 320 bytes, and the total buffer length is 3200 bytes.\n            If ``linesize`` is provided, it must be provided for every valid plane.\n            If it's not provided, an alignment of 1 (i.e. no alignment) is assumed.\n            See :meth:`get_buffer_size` for more details.\n        `no_create`: bool\n            A optional argument, which if provided with True will just create the instance\n            and not initialize anything. All other parameters are ignored when True.\n            This is useful when instantiating later from cython with the ``cython_init`` method.\n\n    **Copying**\n\n    FFmpeg has an internal ref counting system where when used, it frees buffers\n    it allocated only when there's no reference to it remaining thereby allowing\n    multiple images to use the same buffer without making copies. When the\n    Image class allocates the image buffers, e.g. when ``plane_buffers`` is empty\n    such reference buffers are created. As a consequence, when copying the Image\n    object, the buffers will not have to be copied.\n\n    Using the python copy module you can do a **shallow** or a **deep** copy of\n    the object. When doing a **shallow** copy, new buffers will be created if the\n    original buffers were not FFmpeg created and referenced, e.g. if provided\n    using ``plane_buffers``. This is to ensure the buffers won't\n    go out of memory while in use.\n\n    After the copy, the buffers will be \"referenced\" and additional copies will\n    create more references without copying the buffers.\n    A **deep** copy, however, will always create a new referenced buffer.\n    The function :meth:`is_ref` indicates whether the image buffer is such a\n    FFmpeg referenced buffer.\n\n    :\n\n    .. code-block:: python\n\n        >>> w, h = 640, 480\n        >>> size = w * h * 3\n        >>> buf = bytearray([int(x * 255 / size) for x in range(size)])\n        >>> img = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\n        >>> img2 = Image(pix_fmt='rgb24', size=(w, h))\n    '''\n\n    def __cinit__(self, plane_buffers=[], pix_fmt='', size=(), linesize=[], **kwargs):\n        cdef int i, w, h, res\n        cdef object plane = None\n        cdef char msg[256]\n        cdef AVFrame *avframe\n        cdef int buff_size[4]\n        cdef int ls[4]\n        cdef int req[4]\n        cdef bytes fmt_b\n\n        self.frame = NULL\n        self.byte_planes = None\n\n        if kwargs.get('no_create', False):\n            return\n\n        fmt_b = pix_fmt.encode('utf8')\n        self.pix_fmt = av_get_pix_fmt(fmt_b)\n        if self.pix_fmt == AV_PIX_FMT_NONE:\n            raise Exception('Pixel format %s not found.' % pix_fmt)\n        w, h = size\n        self.frame = av_frame_alloc()\n        if self.frame == NULL:\n            raise MemoryError()\n\n        self.frame.format = self.pix_fmt\n        self.frame.width = w\n        self.frame.height = h\n        if linesize:\n            for i in range(min(len(linesize), 4)):\n                self.frame.linesize[i] = linesize[i]\n        else:\n            res = av_image_fill_linesizes(self.frame.linesize, self.pix_fmt, w)\n            if res < 0:\n                raise Exception('Failed to initialize linesizes: ' + tcode(emsg(res, msg, sizeof(msg))))\n        av_image_fill_linesizes(ls, self.pix_fmt, w)\n        for i in range(4):\n            if ls[i] and not self.frame.linesize[i]:\n                raise Exception('Incorrect linesize provided.')\n\n        if plane_buffers:\n            self.byte_planes = []\n            res = get_plane_sizes(buff_size, req, self.pix_fmt, self.frame.height, self.frame.linesize)\n            if res < 0:\n                raise Exception('Failed to get plane sizes: ' + tcode(emsg(res, msg, sizeof(msg))))\n            for i in range(4):\n                if req[i] and buff_size[i] and (len(plane_buffers) <= i or not plane_buffers[i]):\n                    raise Exception('Required plane %d not provided for %s' % (i, pix_fmt))\n                if len(plane_buffers) > i and plane_buffers[i] and not buff_size[i]:\n                    raise Exception('Unused plane %d provided for %s' % (i, pix_fmt))\n            for i in range(4):\n                if len(plane_buffers) == i:\n                    break\n                if not plane_buffers[i]:\n                    continue\n                plane = plane_buffers[i]\n                if len(plane) < buff_size[i]:\n                    raise Exception('Buffer for plane %d is too small, required buffer size is %d.'\\\n                                    % (i, buff_size[i]))\n                self.byte_planes.append(plane)\n                self.frame.data[i] = plane\n        else:\n            with nogil:\n                res = av_frame_get_buffer(self.frame, 32)\n            if res < 0:\n                raise Exception('Could not allocate avframe buffer of size %dx%d: %s'\\\n                                % (w, h, tcode(emsg(res, msg, sizeof(msg)))))\n\n    def __dealloc__(self):\n        av_frame_free(&self.frame)\n\n    cdef int cython_init(self, AVFrame *frame) nogil except 1:\n        '''Can be called only once after object creation and it creates a internal\n        reference to ``frame``.\n        '''\n        self.frame = av_frame_clone(frame)\n        if self.frame == NULL:\n            raise_exec(MemoryError)\n        self.pix_fmt = <AVPixelFormat>self.frame.format\n        return 0\n\n    def __copy__(self):\n        cdef Image img = Image.__new__(Image, no_create=True)\n        with nogil:\n            img.cython_init(self.frame)\n        return img\n\n    def __deepcopy__(self, memo):\n        cdef AVFrame *frame = av_frame_alloc()\n        cdef Image img\n        if frame == NULL:\n            raise MemoryError()\n\n        frame.format = self.frame.format\n        frame.width = self.frame.width\n        frame.height = self.frame.height\n        if av_frame_copy_props(frame, self.frame) < 0:\n            av_frame_free(&frame)\n            raise Exception('Cannot copy frame properties.')\n        if av_frame_get_buffer(frame, 32) < 0:\n            av_frame_free(&frame)\n            raise Exception('Cannot allocate frame buffers.')\n\n        img = Image.__new__(Image, no_create=True)\n        with nogil:\n            av_image_copy(frame.data, frame.linesize, <const uint8_t **>self.frame.data,\n                          self.frame.linesize, <AVPixelFormat>frame.format,\n                          frame.width, frame.height)\n            img.cython_init(frame)\n            av_frame_free(&frame)\n        return img\n\n    cpdef is_ref(Image self):\n        '''Returns whether the image buffer is FFmpeg referenced. This can only be\n        True when the buffers were allocated internally or by FFmpeg bit not when\n        ``plane_buffers`` is provided. See :class:`Image` for details. After a copy,\n        it will always returns True.\n\n        :returns:\n\n            bool: True if the buffer is FFmpeg referenced.\n\n        For example:\n\n        .. code-block:: python\n\n            >>> w, h = 640, 480\n            >>> img = Image(plane_buffers=[bytes(' ') * (w * h * 3)], pix_fmt='rgb24', size=(w, h))\n            >>> img.is_ref()\n            False\n            >>> import copy\n            >>> img2 = copy.copy(img)\n            >>> img2.is_ref()\n            True\n\n        Or if directly allocated internally:\n\n        .. code-block:: python\n\n            >>> img = Image(pix_fmt='rgb24', size=(w, h))\n            >>> img.is_ref()\n            True\n        '''\n        return self.frame.buf[0] != NULL\n\n    cpdef is_key_frame(Image self):\n        '''Returns whether the image is a key frame.\n\n        :returns:\n\n            bool: True if the image was a key frame.\n        '''\n        return self.frame.key_frame == 1\n\n    cpdef get_linesizes(Image self, keep_align=False):\n        '''Returns the linesize of each plane.\n\n        The linesize is the actual number of bytes in each horizontal line for a given plane,\n        which may be padded at the end to satisfy some alignment requirement.\n        For example, a RGB24 frame of size ``(100, 10)`` will have ``3 * 100 = 300``\n        bytes in each line and will be 3000 bytes large. But, when 32 bit\n        alignment is required, the buffer will have to padded at the end so\n        that each line is 320 bytes, and the total buffer length is 3200 bytes.\n\n        :Parameters:\n\n            `keep_align`: bool\n                If True, the original linesize alignments of the image will be returned for\n                every plane. If False, linesize with an alignment of 1 (i.e. no alignment)\n                will be used, returning the minimal linesize required to for the image.\n                Defaults to False.\n\n        :returns:\n\n            4-tuple of ints:\n                A 4 tuple with the linesizes of each plane. If the plane isn't used\n                it'll be 0.\n\n        By defaults there's no alignment:\n\n        .. code-block:: python\n\n            >>> w, h = 100, 10\n            >>> img = Image(plane_buffers=[bytes(' ') * (w * h * 3)],\n            ... pix_fmt='rgb24', size=(w, h))\n            >>> img.get_linesizes(keep_align=True)\n            (300, 0, 0, 0)\n\n        You can force alignment e.g. 32 bits alignment:\n\n        .. code-block:: python\n\n            >>> import math\n            >>> linesize = [int(math.ceil(w * 3 / 32.) * 32)]\n            >>> linesize\n            [320]\n            >>> img = Image(plane_buffers=[bytes(' ') * (h * linesize[0])],\n            ... pix_fmt='rgb24', size=(w, h), linesize=linesize)\n            >>> img.get_linesizes(keep_align=True)\n            (320, 0, 0, 0)\n            >>> img.get_size()\n            (100, 10)\n\n        The linesizes of an unaligned and 32 bit aligned yuv420p image:\n\n        .. code-block:: python\n\n            >>> img = Image(pix_fmt='yuv420p', size=(w, h))\n            >>> img.get_linesizes(keep_align=True)\n            (100, 50, 50, 0)\n            >>> img.get_size()\n            (100, 10)\n\n            >>> # now try align to 32 bit\n            >>> linesize = img.get_linesizes(keep_align=True)\n            >>> align = lambda x: int(math.ceil(x / 32.) * 32)\n            >>> linesize = map(align, linesize)\n            >>> linesize\n            [128, 64, 64, 0]\n            >>> img = Image(pix_fmt='yuv420p', size=(w, h), linesize=linesize)\n            >>> img.get_linesizes(keep_align=True)\n            (128, 64, 64, 0)\n            >>> img.get_linesizes()\n            (100, 50, 50, 0)\n            >>> img.get_size()\n            (100, 10)\n        '''\n        cdef int lsl[4]\n        cdef int *ls = self.frame.linesize\n\n        if not keep_align:\n            av_image_fill_linesizes(lsl, self.pix_fmt, self.frame.width)\n            ls = lsl\n        return (ls[0], ls[1], ls[2], ls[3])\n\n    cpdef get_size(Image self):\n        '''Returns the size of the frame.\n\n        :returns:\n\n            2-tuple of ints: The size of the frame as ``(width, height)``.\n\n        ::\n\n            >>> img.get_size()\n            (640, 480)\n        '''\n        return (self.frame.width, self.frame.height)\n\n    cpdef get_pixel_format(Image self):\n        '''Returns the pixel format of the image. Can be one of\n        :attr:`ffpyplayer.tools.pix_fmts`.\n\n        :returns:\n\n            str: The pixel format of the image.\n\n        ::\n\n            >>> img.get_pixel_format()\n            'rgb24'\n        '''\n        return tcode(av_get_pix_fmt_name(self.pix_fmt))\n\n    cpdef get_buffer_size(Image self, keep_align=False):\n        '''Returns the size of the buffers of each plane.\n\n        :Parameters:\n\n            `keep_align`: bool\n                If True, the linesize alignments of the actual image will be used to\n                calculate the buffer size for each plane. If False, an alignment of 1\n                (i.e. no alignment) will be used, returning the minimal buffer size\n                required to store the image. Defaults to False.\n\n        :returns:\n\n            4-tuple of ints:\n                A list of buffer sizes for each plane of this pixel format.\n\n        A (unaligned) yuv420p image has 3 planes:\n\n        .. code-block:: python\n\n            >>> w, h = 100, 10\n            >>> img = Image(pix_fmt='yuv420p', size=(w, h))\n            >>> img.get_linesizes(keep_align=True)\n            (100, 50, 50, 0)\n            >>> img.get_buffer_size()\n            (1000, 250, 250, 0)\n\n            >>> # align to 32 bits\n            >>> linesize = img.get_linesizes(keep_align=True)\n            >>> align = lambda x: int(math.ceil(x / 32.) * 32)\n            >>> linesize = map(align, linesize)\n            >>> linesize\n            [128, 64, 64, 0]\n            >>> img = Image(pix_fmt='yuv420p', size=(w, h), linesize=linesize)\n            >>> img.get_linesizes(keep_align=True)\n            (128, 64, 64, 0)\n            >>> img.get_buffer_size(keep_align=True)\n            (1280, 320, 320, 0)\n            >>> img.get_buffer_size()\n            (1000, 250, 250, 0)\n        '''\n        cdef int res\n        cdef int size[4]\n        cdef int ls[4]\n        cdef int req[4]\n        cdef char msg[256]\n\n        if keep_align:\n            memcpy(ls, self.frame.linesize, sizeof(ls))\n        else:\n            res = av_image_fill_linesizes(ls, self.pix_fmt, self.frame.width)\n            if res < 0:\n                raise Exception('Failed to initialize linesizes: ' + tcode(emsg(res, msg, sizeof(msg))))\n\n        res = get_plane_sizes(size, req, <AVPixelFormat>self.frame.format, self.frame.height, ls)\n        if res < 0:\n            raise Exception('Failed to get planesizes: ' + tcode(emsg(res, msg, sizeof(msg))))\n        return (size[0], size[1], size[2], size[3])\n\n    cpdef get_required_buffers(Image self):\n        '''Returns a 4 tuple of booleans indicating which of the 4 planes are required\n        (i.e. even if get_buffer_size is non-zero for that plane it may still be\n        optional).\n        '''\n        cdef int res\n        cdef int size[4]\n        cdef int ls[4]\n        cdef int req[4]\n        cdef char msg[256]\n\n        memcpy(ls, self.frame.linesize, sizeof(ls))\n        res = get_plane_sizes(size, req, <AVPixelFormat>self.frame.format, self.frame.height, ls)\n        if res < 0:\n            raise Exception('Failed to get planesizes: ' + tcode(emsg(res, msg, sizeof(msg))))\n        return (req[0], req[1], req[2], req[3])\n\n    cpdef to_bytearray(Image self, keep_align=False):\n        '''Returns a copy of the plane buffers as bytearrays.\n\n        :Parameters:\n\n            `keep_align`: bool\n                If True, the buffer for each plane will be padded after each horizontal\n                line to match the linesize of its plane in this image. If False, an\n                alignment of 1 (i.e. no alignment) will be used, returning the\n                maximially packed buffer of this plane. Defaults to False.\n\n        :returns:\n\n            4-element list: A list of bytearray buffers for each plane of this\n            pixel format. An empty bytearray is returned for unused planes.\n\n        Get the buffer of an RGB image:\n\n        .. code-block:: python\n\n            >>> w, h = 100, 10\n            >>> img = Image(pix_fmt='rgb24', size=(w, h))\n            >>> img.get_linesizes(keep_align=True)\n            (300, 0, 0, 0)\n            >>> map(len, img.to_bytearray())\n            [3000, 0, 0, 0]\n\n        Get the buffers of a YUV420P image:\n\n        .. code-block:: python\n\n            >>> img = Image(pix_fmt='yuv420p', size=(w, h))\n            >>> linesize = img.get_linesizes(keep_align=True)\n            >>> linesize\n            (100, 50, 50, 0)\n            >>> align = lambda x: int(math.ceil(x / 32.) * 32)\n            >>> linesize = map(align, linesize)\n            >>> linesize\n            [128, 64, 64, 0]\n\n            >>> img = Image(pix_fmt='yuv420p', size=(w, h), linesize=linesize)\n            >>> map(len, img.to_bytearray())\n            [1000, 250, 250, 0]\n            >>> map(len, img.to_bytearray(keep_align=True))\n            [1280, 320, 320, 0]\n\n            >>> # now initialize a new Image with it\n            >>> img2 = Image(plane_buffers=img.to_bytearray(),\n            ... pix_fmt=img.get_pixel_format(), size=img.get_size())\n            >>> img2.get_buffer_size(keep_align=True)\n            (1000, 250, 250, 0)\n\n            >>> # keep alignment\n            >>> img2 = Image(plane_buffers=img.to_bytearray(keep_align=True),\n            ... pix_fmt=img.get_pixel_format(), size=img.get_size(),\n            ... linesize=img.get_linesizes(keep_align=True))\n            >>> img2.get_buffer_size(keep_align=True)\n            (1280, 320, 320, 0)\n\n        '''\n        cdef list planes = [None, None, None, None]\n        cdef int i, res\n        cdef uint8_t *data[4]\n        cdef int size[4]\n        cdef int ls[4]\n        cdef int req[4]\n        cdef char msg[256]\n        memset(data, 0, sizeof(data))\n\n        if keep_align:\n            memcpy(ls, self.frame.linesize, sizeof(ls))\n        else:\n            res = av_image_fill_linesizes(ls, self.pix_fmt, self.frame.width)\n            if res < 0:\n                raise Exception('Failed to initialize linesizes: ' + tcode(emsg(res, msg, sizeof(msg))))\n\n        res = get_plane_sizes(size, req, <AVPixelFormat>self.frame.format, self.frame.height, ls)\n        if res < 0:\n            raise Exception('Failed to get plane sizes: ' + tcode(emsg(res, msg, sizeof(msg))))\n        for i in range(4):\n            planes[i] = bytearray(b'\\0') * size[i]\n            if size[i]:\n                data[i] = planes[i]\n        with nogil:\n            av_image_copy(data, ls, <const uint8_t **>self.frame.data, self.frame.linesize,\n                          <AVPixelFormat>self.frame.format, self.frame.width, self.frame.height)\n        return planes\n\n    cpdef to_memoryview(Image self, keep_align=False):\n        '''Returns a memoryviews of the buffers of the image.\n\n        :Parameters:\n\n            `keep_align`: bool\n                If True, the buffers of the original image will be returned\n                without making any additional copies. If False, then if the\n                image alignment is already 1, the original buffers will be\n                returned, otherwise, new buffers will be created with an\n                alignment of 1 and the buffers will be copied into them\n                and returned. See :meth:`to_bytearray`.\n\n        :Returns:\n\n            4-element list:\n                A list of cython arrays for each plane of this\n                image's pixel format. If the data didn't have to be copied, the\n                arrays point directly to the original image data. The arrays\n                can be used where memoryviews are accepted, since cython arrays\n                implement the memoryview interface.\n\n                Unused planes are set to None.\n\n        .. warning::\n            If the data points to the original image data, you must ensure\n            that this :class:`Image` instance does not go out of memory\n            while the returned memoryviews of the arrays are in use. Otherwise when\n            the :class:`Image` goes out of memory, the original data will become\n            invalid and usage of the returned memoryviews of them will crash python.\n\n        Get the buffer of an RGB image:\n\n        .. code-block:: python\n\n            >>> w, h = 100, 10\n            >>> img = Image(pix_fmt='rgb24', size=(w, h))\n            >>> img.get_linesizes(keep_align=True)\n            (300, 0, 0, 0)\n            >>> img.to_memoryview()\n            [<ffpyplayer.pic.array object at 0x055DCE58>, None, None, None]\n            >>> arr = img.to_memoryview()[0]\n            >>> # memview is the only attribute of cython arrays\n            >>> arr.memview\n            <MemoryView of 'array' at 0x55d1468>\n            >>> arr.memview.size\n            3000\n        '''\n        cdef list planes = [None, None, None, None]\n        cdef cyview.array cyarr\n        cdef int i, res\n        cdef int size[4]\n        cdef char *data[4]\n        cdef int ls[4]\n        cdef int req[4]\n        cdef int *cls = self.frame.linesize\n        cdef char msg[256]\n        memset(data, 0, sizeof(data))\n\n        res = av_image_fill_linesizes(ls, self.pix_fmt, self.frame.width)\n        if res < 0:\n            raise Exception('Failed to initialize linesizes: ' +\n                            tcode(emsg(res, msg, sizeof(msg))))\n\n        if keep_align or (cls[0] == ls[0] and cls[1] == ls[1] and\n                          cls[2] == ls[2] and cls[3] == ls[3]):\n            res = get_plane_sizes(size, req, <AVPixelFormat>self.frame.format,\n                                  self.frame.height, self.frame.linesize)\n            if res < 0:\n                raise Exception('Failed to get plane sizes: ' + tcode(emsg(res, msg, sizeof(msg))))\n\n            for i in range(4):\n                if not size[i]:\n                    continue\n                planes[i] = cyarr = cyview.array(shape=(size[i], ), itemsize=sizeof(char),\n                format=\"B\", mode=\"c\", allocate_buffer=False)\n                cyarr.data = <char *>self.frame.data[i]\n            return planes\n\n        res = get_plane_sizes(size, req, <AVPixelFormat>self.frame.format, self.frame.height, ls)\n        if res < 0:\n            raise Exception('Failed to get plane sizes: ' + tcode(emsg(res, msg, sizeof(msg))))\n        for i in range(4):\n            if not size[i]:\n                continue\n            planes[i] = cyarr = cyview.array(shape=(size[i], ), itemsize=sizeof(char),\n            format=\"B\", mode=\"c\", allocate_buffer=True)\n            data[i] = cyarr.data\n\n        with nogil:\n            av_image_copy(<uint8_t **>data, ls, <const uint8_t **>self.frame.data, self.frame.linesize,\n                          <AVPixelFormat>self.frame.format, self.frame.width, self.frame.height)\n        return planes\n\n\ncdef class ImageLoader(object):\n    '''Class that reads one or more images from a file and returns them.\n\n    :Parameters:\n\n        `filename`: string type\n            The full path to the image file. The string will first be encoded\n            using utf8 before passing to FFmpeg.\n\n    For example, reading a simple png using the iterator syntax:\n\n    .. code-block:: python\n\n        >>> img = ImageLoader('file.png')\n        >>> images = [m for m in img]\n        >>> images\n        [(<ffpyplayer.pic.Image object at 0x02B5F5D0>, 0.0)]\n\n    Or reading it directly:\n\n    .. code-block:: python\n\n        >>> img = ImageLoader('file.png')\n        >>> img.next_frame()\n        (<ffpyplayer.pic.Image object at 0x02B74850>, 0.0)\n        >>> img.next_frame()\n        (None, 0)\n        >>> img.next_frame()\n        (None, 0)\n\n    Or reading a gif using the iterator syntax:\n\n    .. code-block:: python\n\n        >>> img = ImageLoader('sapo11.gif')\n        >>> images = [m for m in img]\n        >>> images\n        [(<ffpyplayer.pic.Image object at 0x02B749B8>, 0.0),\n        (<ffpyplayer.pic.Image object at 0x02B74918>, 0.08),\n        (<ffpyplayer.pic.Image object at 0x02B74990>, 0.22),\n        (<ffpyplayer.pic.Image object at 0x02B749E0>, 0.36),\n        (<ffpyplayer.pic.Image object at 0x02B74A08>, 0.41000000000000003),\n        (<ffpyplayer.pic.Image object at 0x02B74A30>, 0.46),\n        (<ffpyplayer.pic.Image object at 0x02B74A58>, 0.51)]\n\n    Or reading it directly:\n\n    .. code-block:: python\n\n        >>> img = ImageLoader('sapo11.gif')\n        >>> img.next_frame()\n        (<ffpyplayer.pic.Image object at 0x02B74B70>, 0.0)\n        >>> img.next_frame()\n        (<ffpyplayer.pic.Image object at 0x02B74C60>, 0.08)\n        ...\n        >>> img.next_frame()\n        (<ffpyplayer.pic.Image object at 0x02B74B70>, 0.51)\n        >>> img.next_frame()\n        (None, 0)\n        >>> img.next_frame()\n        (None, 0)\n    '''\n\n    def __cinit__(self, filename, **kwargs):\n\n        cdef AVDictionary *opts = NULL\n        cdef const AVDictionaryEntry *t = NULL\n        cdef int ret = 0\n        cdef char *fname\n\n        fname = self.filename = filename.encode('utf8')\n        self.format_ctx = NULL\n        self.codec = NULL\n        self.codec_ctx = avcodec_alloc_context3(NULL)\n        if self.codec_ctx == NULL:\n            raise MemoryError()\n\n        self.frame = NULL\n        self.eof = 0\n        av_init_packet(&self.pkt)\n\n        with nogil:\n            ret = avformat_open_input(&self.format_ctx, fname, NULL, NULL)\n        if ret < 0:\n            raise Exception(\"Failed to open input file {}: {}\".format(filename,\n                            tcode(emsg(ret, self.msg, sizeof(self.msg)))))\n\n        ret = avcodec_parameters_to_context(self.codec_ctx, self.format_ctx.streams[0].codecpar)\n        if ret < 0:\n            raise Exception(\"Failed to open input file {}: {}\".format(filename,\n                            tcode(emsg(ret, self.msg, sizeof(self.msg)))))\n\n        self.codec = avcodec_find_decoder(self.codec_ctx.codec_id)\n        if self.codec is NULL:\n            raise Exception(\"Failed to find supported codec for file {}\"\n                            .format(filename))\n\n        with nogil:\n            ret = avcodec_open2(self.codec_ctx, self.codec, &opts)\n        if ret < 0:\n            raise Exception(\"Failed to open codec for {}: {}\".format(filename,\n                            tcode(emsg(ret, self.msg, sizeof(self.msg)))))\n        t = av_dict_get(opts, \"\", NULL, AV_DICT_IGNORE_SUFFIX)\n        if t != NULL:\n            raise Exception(\"Option {} not found.\".format(t.key))\n\n    def __dealloc__(self):\n        with nogil:\n            av_packet_unref(&self.pkt)\n            av_frame_free(&self.frame)\n            avformat_close_input(&self.format_ctx)\n            if self.codec_ctx != NULL:\n                avcodec_free_context(&self.codec_ctx)\n\n    def __iter__(self):\n        while True:\n            res = self.next_frame()\n            if res == (None, 0):\n                break\n            yield res\n\n    cpdef next_frame(self):\n        ''' Returns the next available frame, or `(None, 0)` if there are no\n        more frames available.\n\n        :returns:\n            a 2-tuple of `(:class:`Image`, pts)`:\n            Where the first element is the next image to be displayed and `pts`\n            is the time, relative to the first frame, when to display it e.g. in\n            the case of a gif.\n\n            If we reached the eof of the file and there are no more frames\n            to be returned, it returns `(None, 0)`.\n\n        .. warning::\n\n            Both :meth:`next_frame` and the iterator syntax read the frames\n            identically. Consequently, calling one, will also advance the frame\n            for the other.\n        '''\n\n        cdef int frame_decoded, ret = 0\n        cdef Image image\n        cdef double t = 0\n\n        if self.eof:\n            return self.eof_frame()\n\n        with nogil:\n            ret = av_read_frame(self.format_ctx, &self.pkt)\n        if ret < 0:\n            if ret == AVERROR_EOF:\n                self.eof = 1\n                self.pkt.data = NULL\n                return self.eof_frame()\n            raise Exception(\"Failed to read frame: {}\",\n                            tcode(emsg(ret, self.msg, sizeof(self.msg))))\n\n        with nogil:\n            self.frame = av_frame_alloc()\n        if self.frame is NULL:\n            raise MemoryError(\"Failed to alloc frame\")\n\n        with nogil:\n            ret = avcodec_send_packet(self.codec_ctx, &self.pkt)\n            if ret >= 0:\n                ret = avcodec_receive_frame(self.codec_ctx, self.frame)\n        if ret < 0:\n            if ret == AVERROR_EOF:\n                self.eof = 1\n                self.pkt.data = NULL\n                return self.eof_frame()\n            raise Exception(\"Failed to decode image from file\")\n\n        self.frame.pts = self.frame.best_effort_timestamp\n        if self.frame.pts == AV_NOPTS_VALUE:\n            t = 0.\n        else:\n            t = av_q2d(self.format_ctx.streams[0].time_base) * self.frame.pts\n\n        image = Image(no_create=True)\n        image.cython_init(self.frame)\n\n        av_packet_unref(&self.pkt)\n        av_frame_free(&self.frame)\n        return image, t\n\n    cdef inline object eof_frame(self):\n        '''Used to flush the remaining frames until no more cached.\n        '''\n        cdef int ret = 0\n        cdef Image image\n        cdef double t = 0\n        if self.eof == 2:\n            return None, 0\n\n        with nogil:\n            self.frame = av_frame_alloc()\n        if self.frame is NULL:\n            raise MemoryError(\"Failed to alloc frame\")\n\n        with nogil:\n            ret = avcodec_send_packet(self.codec_ctx, &self.pkt)\n            if ret >= 0:\n                ret = avcodec_receive_frame(self.codec_ctx, self.frame)\n        if ret < 0:\n            self.eof = 2\n            av_frame_free(&self.frame)\n            return None, 0\n\n        self.frame.pts = self.frame.best_effort_timestamp\n        if self.frame.pts == AV_NOPTS_VALUE:\n            t = 0.\n        else:\n            t = av_q2d(self.format_ctx.streams[0].time_base) * self.frame.pts\n        image = Image(no_create=True)\n        image.cython_init(self.frame)\n        av_frame_free(&self.frame)\n        return image, t\n"
  },
  {
    "path": "ffpyplayer/player/__init__.py",
    "content": "'''\r\nFFmpeg based media player\r\n=========================\r\n\r\nA FFmpeg based python media player. See :class:`MediaPlayer` for details.\r\n'''\r\n\r\n__all__ = ('MediaPlayer', )\r\n\r\nfrom ffpyplayer.player.player import MediaPlayer\r\n"
  },
  {
    "path": "ffpyplayer/player/clock.pxd",
    "content": "\ninclude '../includes/ffmpeg.pxi'\n\n\ncdef class Clock(object):\n    cdef:\n        double pts           # clock base\n        double pts_drift     # clock base minus time at which we updated the clock\n        double last_updated\n        double speed\n        int serial           # clock is based on a packet with this serial\n        int paused\n        int *queue_serial    # pointer to the current packet queue serial, used for obsolete clock detection\n\n    cdef void cInit(Clock self, int *queue_serial) nogil\n    cdef double get_clock(Clock self) nogil\n    cdef void set_clock_at(Clock self, double pts, int serial, double time) nogil\n    cdef void set_clock(Clock self, double pts, int serial) nogil\n    cdef void set_clock_speed(Clock self, double speed) nogil\n    cdef void sync_clock_to_slave(Clock self, Clock slave) nogil\n"
  },
  {
    "path": "ffpyplayer/player/clock.pyx",
    "content": "#cython: cdivision=True\n\n__all__ = ('Clock', )\n\ninclude '../includes/ff_consts.pxi'\n\ncdef extern from \"math.h\" nogil:\n    double NAN\n    int isnan(double x)\n    double fabs(double x)\n\n\ncdef class Clock(object):\n\n    def __cinit__(Clock self):\n        pass\n    cdef void cInit(Clock self, int *queue_serial) nogil:\n        self.speed = 1.0\n        self.paused = 0\n        if queue_serial != NULL:\n            self.queue_serial = queue_serial\n        else:\n            self.queue_serial = &self.serial\n        self.set_clock(NAN, -1)\n\n    def __dealloc__(Clock self):\n        pass\n\n    cdef double get_clock(Clock self) nogil:\n        cdef double time\n        if self.queue_serial[0] != self.serial:\n            return NAN\n        if self.paused:\n            return self.pts\n        else:\n            time = av_gettime_relative() / 1000000.0\n            return self.pts_drift + time - (time - self.last_updated) * (1.0 - self.speed)\n\n    cdef void set_clock_at(Clock self, double pts, int serial, double time) nogil:\n        self.pts = pts\n        self.last_updated = time\n        self.pts_drift = self.pts - time\n        self.serial = serial\n\n    cdef void set_clock(Clock self, double pts, int serial) nogil:\n        cdef double time = av_gettime_relative() / 1000000.0\n        self.set_clock_at(pts, serial, time)\n\n    cdef void set_clock_speed(Clock self, double speed) nogil:\n        self.set_clock(self.get_clock(), self.serial)\n        self.speed = speed\n\n    cdef void sync_clock_to_slave(Clock self, Clock slave) nogil:\n        cdef double clock = self.get_clock()\n        cdef double slave_clock = slave.get_clock()\n        if (not isnan(slave_clock)) and (isnan(clock) or fabs(clock - slave_clock) > AV_NOSYNC_THRESHOLD):\n            self.set_clock(slave_clock, slave.serial)\n"
  },
  {
    "path": "ffpyplayer/player/core.pxd",
    "content": "\ninclude '../includes/ffmpeg.pxi'\n\nfrom ffpyplayer.player.queue cimport FFPacketQueue\nfrom ffpyplayer.player.frame_queue cimport FrameQueue, Frame\nfrom ffpyplayer.player.decoder cimport Decoder\nfrom ffpyplayer.threading cimport MTGenerator, MTThread, MTMutex, MTCond\nfrom ffpyplayer.player.clock cimport Clock\nfrom ffpyplayer.pic cimport Image\nfrom cpython.ref cimport PyObject\n\n\ncdef struct AudioParams:\n    int freq\n    int channels\n    int64_t channel_layout\n    AVSampleFormat fmt\n    int frame_size\n    int bytes_per_sec\n\n\ncdef class VideoState(object):\n    cdef:\n        MTThread read_tid\n        const AVInputFormat *iformat\n        int abort_request\n        int paused\n        int last_paused\n        int queue_attachments_req\n        int seek_req\n        int seek_flags\n        int64_t seek_pos\n        int64_t seek_rel\n        int read_pause_return\n        AVFormatContext *ic\n        int realtime\n        int reached_eof\n        int eof\n        int audio_dev\n\n        Clock audclk\n        Clock vidclk\n        Clock extclk\n\n        FrameQueue pictq\n        FrameQueue subpq\n        FrameQueue sampq\n\n        Decoder auddec\n        Decoder viddec\n        Decoder subdec\n\n        int audio_stream\n\n        int av_sync_type\n\n        double audio_clock\n        int audio_clock_serial\n        double audio_diff_cum # used for AV difference average computation\n        double audio_diff_avg_coef\n        double audio_diff_threshold\n        int audio_diff_avg_count\n        AVStream *audio_st\n        FFPacketQueue audioq\n        int audio_hw_buf_size\n\n        IF USE_SDL2_MIXER:\n            uint8_t chunk_buf[AUDIO_MIN_BUFFER_SIZE]\n            Mix_Chunk *chunk\n            int audio_count\n\n        uint8_t *audio_buf\n        uint8_t *audio_buf1\n        unsigned int audio_buf_size # in bytes\n        unsigned int audio_buf1_size\n        int audio_buf_index # in bytes\n        int audio_write_buf_size\n        AudioParams audio_src\n        IF CONFIG_AVFILTER:\n            AudioParams audio_filter_src\n        AudioParams audio_tgt\n        SwrContext *swr_ctx\n        int frame_drops_early\n        int frame_drops_late\n\n        int16_t sample_array[SAMPLE_ARRAY_SIZE]\n        int sample_array_index\n\n        int subtitle_stream\n        AVStream *subtitle_st\n        FFPacketQueue subtitleq\n\n        double frame_timer\n        double frame_last_returned_time\n        double frame_last_filter_delay\n        int video_stream\n        AVStream *video_st\n        FFPacketQueue videoq\n        double max_frame_duration      # maximum duration of a frame - above this, we consider the jump a timestamp discontinuity\n\n        IF CONFIG_AVFILTER:\n            int vfilter_idx\n            AVFilterContext *in_video_filter   # the first filter in the video chain\n            AVFilterContext *out_video_filter  # the last filter in the video chain\n            AVFilterContext *in_audio_filter   # the first filter in the audio chain\n            AVFilterContext *out_audio_filter  # the last filter in the audio chain\n            AVFilterContext *split_audio_filter  # the last filter in the audio chain\n            AVFilterGraph *agraph              # audio filter graph\n\n        int last_video_stream, last_audio_stream, last_subtitle_stream\n\n        MTCond continue_read_thread\n        MTGenerator mt_gen\n        VideoSettings *player\n        int64_t last_time\n\n        MTCond pause_cond\n        double last_clock\n        PyObject *self_id\n\n        dict metadata\n\n        object callback\n        int is_ref\n        AVPixelFormat pix_fmt\n\n\n    cdef int cInit(self, MTGenerator mt_gen, VideoSettings *player, int paused,\n                   AVPixelFormat out_fmt) nogil except 1\n    cdef int cquit(VideoState self) nogil except 1\n    cdef int request_thread_s(self, char *name, char *msg) nogil except 1\n    cdef int request_thread(self, char *name, object msg) nogil except 1\n    cdef int request_thread_py(self, object name, object msg) except 1\n    cdef object get_out_pix_fmt(self)\n    cdef void set_out_pix_fmt(self, AVPixelFormat out_fmt)\n    cdef int get_master_sync_type(VideoState self) nogil\n    cdef double get_master_clock(VideoState self) nogil except? 0.0\n    cdef int check_external_clock_speed(VideoState self) nogil except 1\n    cdef int stream_seek(VideoState self, int64_t pos, int64_t rel, int seek_by_bytes, int flush) nogil except 1\n    cdef int seek_chapter(VideoState self, int incr, int flush) nogil except 1\n    cdef int toggle_pause(VideoState self) nogil except 1\n    cdef double compute_target_delay(VideoState self, double delay) nogil except? 0.0\n    cdef double vp_duration(VideoState self, Frame *vp, Frame *nextvp) nogil except? 0.0\n    cdef void update_video_pts(VideoState self, double pts, int64_t pos, int serial) nogil\n    cdef int video_refresh(VideoState self, Image next_image, double *pts, double *remaining_time,\n                           int force_refresh) nogil except -1\n    cdef int get_video_frame(VideoState self, AVFrame *frame) nogil except 2\n    IF CONFIG_AVFILTER:\n        cdef int configure_filtergraph(VideoState self, AVFilterGraph *graph, const char *filtergraph,\n                                       AVFilterContext *source_ctx, AVFilterContext *sink_ctx) nogil except? 1\n        cdef int configure_video_filters(VideoState self, AVFilterGraph *graph,\n                                         const char *vfilters, AVFrame *frame,\n                                         AVPixelFormat pix_fmt) nogil except? 1\n        cdef int configure_audio_filters(VideoState self, const char *afilters,\n                                         int force_output_format) nogil except? 1\n    cdef int audio_thread(self) nogil except? 1\n    cdef int video_thread(VideoState self) nogil except? 1\n    cdef int subtitle_thread(VideoState self) nogil except 1\n    cdef int subtitle_display(self, AVSubtitle *sub) nogil except 1\n    cdef int update_sample_display(VideoState self, int16_t *samples, int samples_size) nogil except 1\n    cdef int synchronize_audio(VideoState self, int nb_samples) nogil except -1\n    cdef int audio_decode_frame(VideoState self) nogil except? 1\n    cdef int sdl_audio_callback(VideoState self, uint8_t *stream, int len) nogil except 1\n    cdef inline int open_audio_device(VideoState self, SDL_AudioSpec *wanted_spec, SDL_AudioSpec *spec) nogil except 1\n    cdef int audio_open(VideoState self, int64_t wanted_channel_layout, int wanted_nb_channels,\n                        int wanted_sample_rate, AudioParams *audio_hw_params) nogil except? 1\n    cdef int stream_component_open(VideoState self, int stream_index) nogil except 1\n    cdef int stream_component_close(VideoState self, int stream_index) nogil except 1\n    cdef int read_thread(VideoState self) nogil except 1\n    cdef int stream_has_enough_packets(self, AVStream *st, int stream_id, FFPacketQueue queue) nogil\n    cdef inline int failed(VideoState self, int ret, AVFormatContext *ic, AVPacket **pkt) nogil except 1\n    cdef int stream_select_program(VideoState self, int requested_program) nogil except 1\n    cdef int stream_select_channel(VideoState self, int codec_type, unsigned int requested_stream) nogil except 1\n    cdef int stream_cycle_channel(VideoState self, int codec_type) nogil except 1\n    cdef int decode_interrupt_cb(VideoState self) nogil\n\n\ncdef struct VideoSettings:\n    unsigned sws_flags\n    int loglevel\n\n    const AVInputFormat *file_iformat\n    char *input_filename\n    int screen_width\n    int screen_height\n    uint8_t audio_volume\n    int muted\n    int audio_sdl\n    int audio_disable\n    int video_disable\n    int subtitle_disable\n    const char* wanted_stream_spec[<int>AVMEDIA_TYPE_NB]\n    int seek_by_bytes\n    int show_status\n    int av_sync_type\n    int64_t start_time\n    int64_t duration\n    int fast\n    int genpts\n    int lowres\n    int decoder_reorder_pts\n    int autoexit\n    int loop\n    int framedrop\n    int infinite_buffer\n    char *audio_codec_name\n    char *subtitle_codec_name\n    char *video_codec_name\n    const char **vfilters_list\n    int nb_vfilters\n    char *afilters\n    char *avfilters\n\n    int autorotate\n    int find_stream_info\n    int filter_threads\n\n    #/* current context */\n    int64_t audio_callback_time\n\n    SwsContext *img_convert_ctx\n    AVDictionary *format_opts\n    AVDictionary *codec_opts\n    AVDictionary *resample_opts\n    AVDictionary *sws_dict\n    AVDictionary *swr_opts\n"
  },
  {
    "path": "ffpyplayer/player/core.pyx",
    "content": "\n__all__ = ('VideoState', )\n\ninclude '../includes/ff_consts.pxi'\ninclude \"../includes/inline_funcs.pxi\"\n\nfrom ffpyplayer.player.queue cimport FFPacketQueue\nfrom ffpyplayer.player.frame_queue cimport FrameQueue\nfrom ffpyplayer.threading cimport MTGenerator, MTThread, MTMutex, MTCond, Py_MT, SDL_MT\nfrom ffpyplayer.player.clock cimport Clock\nfrom ffpyplayer.pic cimport Image\nfrom cpython.ref cimport PyObject\n\nimport ffpyplayer.tools  # for init\nimport traceback\nfrom weakref import ref\n\n# android platform detection\nfrom os import environ\ncdef int IS_ANDROID = 0\n\ncdef extern from \"ffconfig.h\":\n    bint WIN_IS_DEFINED\n\ncdef extern from \"Python.h\":\n    PyObject *PyUnicode_FromString(const char *u)\n    void Py_DECREF(PyObject *)\n\nif \"ANDROID_ARGUMENT\" in environ:\n    import jnius\n    IS_ANDROID = 1\n\ncdef extern from \"limits.h\" nogil:\n    int64_t INT64_MAX\n    int64_t INT64_MIN\n\ncdef extern from \"math.h\" nogil:\n    double NAN\n    int isnan(double x)\n    double fabs(double x)\n    double exp(double x)\n    double log(double x)\n    double floor(double x)\n    double round(double x)\n\ncdef extern from \"errno.h\" nogil:\n    int ENOSYS\n    int ENOMEM\n    int EAGAIN\n\ncdef extern from \"stdio.h\" nogil:\n    int snprintf(char *, size_t, const char *, ... )\n\ncdef extern from \"stdlib.h\" nogil:\n    int atoi(const char *)\n\ncdef extern from \"inttypes.h\" nogil:\n    const char *PRId64\n    const char *PRIx64\n\ncdef extern from \"string.h\" nogil:\n    void * memset(void *, int, size_t)\n    void * memcpy(void *, const void *, size_t)\n    char * strchr (char *, int)\n    int strcmp(const char *, const char *)\n    int strncmp(const char *, const char *, size_t)\n    char * strerror(int)\n    size_t strlen(const char *)\n    char * strcat(char *, const char *)\n    char * strcpy(char *, const char *)\n\nctypedef enum LoopState:\n    retry,\n    display\n\n# XXX: const\ncdef object sub_ass = str(b'ass'), sub_text = str(b'text'), sub_fmt\n\ncdef AVSampleFormat *sample_fmts = [AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE]\ncdef int *next_nb_channels = [0, 0, 1, 6, 2, 6, 4, 6]\ncdef int *next_sample_rates = [0, 44100, 48000, 96000, 192000]\ncdef int next_sample_rates_len = 5\n\ncdef MTMutex audio_mutex = MTMutex(SDL_MT)\ncdef int audio_count = 0\ncdef SDL_AudioSpec spec_used\n\n\ncdef void sdl_mixer_callback(int chan, uint8_t *stream, int len, VideoState self) nogil:\n    self.sdl_audio_callback(stream, len)\n\n\ncdef int read_thread_enter(void *obj_id) except? 1 with gil:\n    cdef VideoState vs = <VideoState>obj_id\n    cdef bytes msg\n    try:\n        with nogil:\n            return vs.read_thread()\n    except Exception as e:\n        msg = str(e).encode('utf8')\n        av_log(NULL, AV_LOG_FATAL, '%s', msg)\n        msg = traceback.format_exc().encode('utf8')\n        av_log(NULL, AV_LOG_FATAL, '%s', msg)\n        vs.request_thread_s('read:error', e)\n        if vs.mt_gen.mt_src == Py_MT:\n            raise\n        else:\n            return 1\n    finally:\n        if IS_ANDROID:\n            jnius.detach()\n\ncdef int video_thread_enter(void *obj_id) except? 1 with gil:\n    cdef VideoState vs = <VideoState>obj_id\n    cdef bytes msg\n    try:\n        with nogil:\n            return vs.video_thread()\n    except Exception as e:\n        msg = str(e).encode('utf8')\n        av_log(NULL, AV_LOG_FATAL, '%s', msg)\n        msg = traceback.format_exc().encode('utf8')\n        av_log(NULL, AV_LOG_FATAL, '%s', msg)\n        vs.request_thread_s('video:error', e)\n        if vs.mt_gen.mt_src == Py_MT:\n            raise\n        else:\n            return 1\n    finally:\n        if IS_ANDROID:\n            jnius.detach()\n\ncdef int audio_thread_enter(void *obj_id) except? 1 with gil:\n    cdef VideoState vs = <VideoState>obj_id\n    cdef bytes msg\n    try:\n        with nogil:\n            return vs.audio_thread()\n    except Exception as e:\n        msg = str(e).encode('utf8')\n        av_log(NULL, AV_LOG_FATAL, '%s', msg)\n        msg = traceback.format_exc().encode('utf8')\n        av_log(NULL, AV_LOG_FATAL, '%s', msg)\n        vs.request_thread_s('audio:error', e)\n        if vs.mt_gen.mt_src == Py_MT:\n            raise\n        else:\n            return 1\n    finally:\n        if IS_ANDROID:\n            jnius.detach()\n\ncdef int subtitle_thread_enter(void *obj_id) except? 1 with gil:\n    cdef VideoState vs = <VideoState>obj_id\n    cdef bytes msg\n    try:\n        with nogil:\n            return vs.subtitle_thread()\n    except Exception as e:\n        msg = str(e).encode('utf8')\n        av_log(NULL, AV_LOG_FATAL, '%s', msg)\n        msg = traceback.format_exc().encode('utf8')\n        av_log(NULL, AV_LOG_FATAL, '%s', msg)\n        vs.request_thread_s('subtitle:error', e)\n        if vs.mt_gen.mt_src == Py_MT:\n            raise\n        else:\n            return 1\n    finally:\n        if IS_ANDROID:\n            jnius.detach()\n\ncdef int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec) nogil:\n    cdef int ret = avformat_match_stream_specifier(s, st, spec)\n    if ret < 0:\n        av_log(s, AV_LOG_ERROR, b\"Invalid stream specifier: %s.\\n\", spec)\n    return ret\n\ncdef AVDictionary *filter_codec_opts(AVDictionary *opts, AVCodecID codec_id,\n                                     AVFormatContext *s, AVStream *st, AVCodec *codec) nogil:\n    cdef AVDictionary *ret = NULL\n    cdef const AVDictionaryEntry *t = NULL\n    cdef int flags\n    cdef char prefix = 0\n    cdef char *p\n    cdef const AVClass *cc = avcodec_get_class()\n    cdef int res\n    if s.oformat != NULL:\n        flags = AV_OPT_FLAG_ENCODING_PARAM\n    else:\n        flags = AV_OPT_FLAG_DECODING_PARAM\n    if codec == NULL:\n        if s.oformat != NULL:\n            codec = avcodec_find_encoder(codec_id)\n        else:\n            codec = avcodec_find_decoder(codec_id)\n\n    if st.codecpar.codec_type == AVMEDIA_TYPE_VIDEO:\n        prefix  = b'v'\n        flags  |= AV_OPT_FLAG_VIDEO_PARAM\n    elif st.codecpar.codec_type ==  AVMEDIA_TYPE_AUDIO:\n        prefix  = b'a'\n        flags  |= AV_OPT_FLAG_AUDIO_PARAM\n    elif st.codecpar.codec_type ==  AVMEDIA_TYPE_SUBTITLE:\n        prefix  = b's'\n        flags  |= AV_OPT_FLAG_SUBTITLE_PARAM\n\n    while 1:\n        t = av_dict_get(opts, b\"\", t, AV_DICT_IGNORE_SUFFIX)\n        if t == NULL:\n            break\n        p = strchr(t.key, b':')\n\n        # check stream specification in opt name\n        if p != NULL:\n            res = check_stream_specifier(s, st, p + 1)\n            if res == 1:\n                p[0] = 0\n            elif res == 0:\n                continue\n            else:\n                return NULL\n\n        if (av_opt_find(&cc, t.key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) != NULL or\n            (codec != NULL and codec.priv_class != NULL and\n             av_opt_find(&codec.priv_class, t.key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) != NULL)):\n            av_dict_set(&ret, t.key, t.value, 0)\n        elif (t.key[0] == prefix and av_opt_find(&cc, t.key + 1, NULL, flags,\n                                                 AV_OPT_SEARCH_FAKE_OBJ) != NULL):\n            av_dict_set(&ret, t.key + 1, t.value, 0)\n\n        if p != NULL:\n            p[0] = b':'\n    return ret\n\ncdef int is_realtime(AVFormatContext *s) nogil:\n    if((not strcmp(s.iformat.name, b\"rtp\")) or\n       (not strcmp(s.iformat.name, b\"rtsp\")) or\n       not strcmp(s.iformat.name, b\"sdp\")):\n        return 1\n    if s.pb and ((not strncmp(s.url, b\"rtp:\", 4)) or\n                 not strncmp(s.url, b\"udp:\", 4)):\n        return 1\n    return 0\n\ncdef AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, AVDictionary *codec_opts) nogil:\n    cdef int i\n    cdef AVDictionary **opts\n\n    if not s.nb_streams:\n        return NULL\n    opts = <AVDictionary **>av_mallocz(s.nb_streams * sizeof(AVDictionary *))\n    if opts == NULL:\n        av_log(NULL, AV_LOG_ERROR, b\"Could not alloc memory for stream options.\\n\")\n        return NULL\n    for i in range(s.nb_streams):\n        opts[i] = filter_codec_opts(codec_opts, s.streams[i].codecpar.codec_id,\n                                    s, s.streams[i], NULL)\n    return opts\n\ncdef double get_rotation(int32_t *displaymatrix) nogil:\n    cdef double theta = 0\n\n    if displaymatrix:\n        theta = -round(av_display_rotation_get(<int32_t *>displaymatrix))\n    theta -= 360 * floor(theta / 360. + 0.9 / 360.)\n\n    if fabs(theta - 90 * round(theta / 90)) > 2:\n        av_log(NULL, AV_LOG_WARNING, \"Odd rotation angle\")\n\n    return theta\n\ncdef bytes py_pat = bytes(b\"%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%\" + PRId64 + b\"/%\" + PRId64 + b\"   \\r\")\ncdef char *py_pat_str = py_pat\ncdef bytes av_str = b\"A-V\", mv_str = b\"M-V\", ma_str = b\"M-A\", empty_str = b\"   \"\ncdef char *str_av = av_str\ncdef char *str_mv = mv_str\ncdef char *str_ma = ma_str\ncdef char *str_empty = empty_str\n\n\ncdef class VideoState(object):\n\n    def __cinit__(self, object callback=None):\n        self.callback = callback\n        self.is_ref = isinstance(callback, ref)\n        self.self_id = <PyObject*>self\n        self.metadata = {\n            'src_vid_size': (0, 0), 'sink_vid_size': (0, 0), 'title': '',\n            'duration': None, 'frame_rate': (0, 0), 'src_pix_fmt': '',\n            'aspect_ratio':(1, 1)}\n\n    cdef int cInit(self, MTGenerator mt_gen, VideoSettings *player, int paused,\n                   AVPixelFormat out_fmt) nogil except 1:\n        cdef int i\n        self.player = player\n        self.vfilter_idx = 0\n        self.pix_fmt = out_fmt\n        self.last_video_stream = self.video_stream = -1\n        self.last_audio_stream = self.audio_stream = -1\n        self.last_subtitle_stream = self.subtitle_stream = -1\n\n        IF not CONFIG_AVFILTER:\n            self.player.img_convert_ctx = NULL\n        self.iformat = player.file_iformat\n        with gil:\n            self.read_tid = None\n            self.mt_gen = mt_gen\n            self.audioq = FFPacketQueue.__new__(FFPacketQueue, mt_gen)\n            self.subtitleq = FFPacketQueue.__new__(FFPacketQueue, mt_gen)\n            self.videoq = FFPacketQueue.__new__(FFPacketQueue, mt_gen)\n\n            self.auddec = Decoder.__new__(Decoder)\n            self.viddec = Decoder.__new__(Decoder)\n            self.subdec = Decoder.__new__(Decoder)\n\n            self.pictq = FrameQueue.__new__(\n                FrameQueue, mt_gen, self.videoq,\n                VIDEO_PICTURE_QUEUE_SIZE, 1)\n            self.subpq = FrameQueue.__new__(\n                FrameQueue, mt_gen, self.subtitleq,\n                SUBPICTURE_QUEUE_SIZE, 0)\n            self.sampq = FrameQueue.__new__(\n                FrameQueue, mt_gen, self.audioq,\n                SAMPLE_QUEUE_SIZE, 1)\n            self.continue_read_thread = MTCond.__new__(MTCond, mt_gen.mt_src)\n            self.pause_cond = MTCond.__new__(MTCond, mt_gen.mt_src)\n\n            self.vidclk = Clock.__new__(Clock)\n            self.audclk = Clock.__new__(Clock)\n            self.extclk = Clock.__new__(Clock)\n\n        self.vidclk.cInit(&self.videoq.serial)\n        self.audclk.cInit(&self.audioq.serial)\n        self.extclk.cInit(NULL)\n\n        self.audio_clock_serial = -1\n        self.av_sync_type = player.av_sync_type\n        self.reached_eof = 0\n        if paused:\n            self.toggle_pause()\n\n        with gil:\n            self.read_tid = MTThread.__new__(MTThread, mt_gen.mt_src)\n            self.read_tid.create_thread(read_thread_enter, \"read_thread\", self.self_id)\n        return 0\n\n    def __dealloc__(VideoState self):\n        with nogil:\n            self.cquit()\n\n    cdef int cquit(VideoState self) nogil except 1:\n        cdef int i\n        # XXX: use a special url_shutdown call to abort parse cleanly\n        if self.read_tid is None:\n            return 0\n        self.abort_request = 1\n        self.pause_cond.lock()\n        self.pause_cond.cond_signal()\n        self.pause_cond.unlock()\n        self.read_tid.wait_thread(NULL)\n\n        with gil:\n            self.read_tid = None\n\n        if self.audio_stream >= 0:\n            self.stream_component_close(self.audio_stream)\n        if self.video_stream >= 0:\n            self.stream_component_close(self.video_stream)\n        if self.subtitle_stream >= 0:\n            self.stream_component_close(self.subtitle_stream)\n\n        avformat_close_input(&self.ic)\n        self.ic = NULL\n\n        IF not CONFIG_AVFILTER:\n            sws_freeContext(self.player.img_convert_ctx)\n\n        return 0\n\n    cdef int request_thread_s(self, char *name, char *msg) nogil except 1:\n        if self.callback is None:\n            return 0\n        with gil:\n            return self.request_thread_py(tcode(name), tcode(msg))\n\n    cdef int request_thread(self, char *name, object msg) nogil except 1:\n        if self.callback is None:\n            return 0\n        with gil:\n            return self.request_thread_py(tcode(name), msg)\n\n    cdef int request_thread_py(self, object name, object msg) except 1:\n        cdef object f\n        if self.is_ref:\n            f = self.callback()\n            if f is not None:\n                f(name, msg)\n        else:\n            self.callback(name, msg)\n        return 0\n\n    cdef object get_out_pix_fmt(self):\n        return tcode(av_get_pix_fmt_name(self.pix_fmt))\n\n    cdef void set_out_pix_fmt(self, AVPixelFormat out_fmt):\n        '''\n        Users set the pixel fmt here. If avfilter is enabled, the filter is\n        changed when this is changed. If disabled, this method may only\n        be called before other methods below, and can not be called once things\n        are running.\n\n        After the user changes the pix_fmt, it might take a few frames until they\n        receive the new fmt in case pics were already queued.\n        '''\n        self.pix_fmt = out_fmt\n\n    cdef int decode_interrupt_cb(VideoState self) nogil:\n        return self.abort_request\n\n    cdef int get_master_sync_type(VideoState self) nogil:\n        if self.av_sync_type == AV_SYNC_VIDEO_MASTER:\n            if self.video_st != NULL:\n                return AV_SYNC_VIDEO_MASTER\n            else:\n                return AV_SYNC_AUDIO_MASTER\n        elif self.av_sync_type == AV_SYNC_AUDIO_MASTER:\n            if self.audio_st != NULL:\n                return AV_SYNC_AUDIO_MASTER\n            else:\n                return AV_SYNC_EXTERNAL_CLOCK\n        else:\n            return AV_SYNC_EXTERNAL_CLOCK\n\n    # get the current master clock value\n    cdef double get_master_clock(VideoState self) nogil except? 0.0:\n        cdef double val\n        cdef int sync_type = self.get_master_sync_type()\n\n        if sync_type == AV_SYNC_VIDEO_MASTER:\n            val = self.vidclk.get_clock()\n        elif sync_type == AV_SYNC_AUDIO_MASTER:\n            val = self.audclk.get_clock()\n        else:\n            val = self.extclk.get_clock()\n        return val\n\n    cdef int check_external_clock_speed(VideoState self) nogil except 1:\n        cdef double speed\n        if self.video_stream >= 0 and self.videoq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES or\\\n        self.audio_stream >= 0 and self.audioq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES:\n            self.extclk.set_clock_speed(FFMAXD(EXTERNAL_CLOCK_SPEED_MIN, self.extclk.speed - EXTERNAL_CLOCK_SPEED_STEP))\n        elif (self.video_stream < 0 or self.videoq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES) and\\\n        (self.audio_stream < 0 or self.audioq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES):\n            self.extclk.set_clock_speed(FFMIND(EXTERNAL_CLOCK_SPEED_MAX, self.extclk.speed + EXTERNAL_CLOCK_SPEED_STEP))\n        else:\n            speed = self.extclk.speed\n            if speed != 1.0:\n                self.extclk.set_clock_speed(speed + EXTERNAL_CLOCK_SPEED_STEP * (1.0 - speed) / fabs(1.0 - speed))\n        return 0\n\n    # seek in the stream\n    cdef int stream_seek(VideoState self, int64_t pos, int64_t rel, int seek_by_bytes, int flush) nogil except 1:\n        if not self.seek_req:\n            self.viddec.set_seek_pos(-1)\n            self.auddec.set_seek_pos(-1)\n            if flush:\n                if self.get_master_sync_type() != AV_SYNC_VIDEO_MASTER:\n                    self.viddec.set_seek_pos(pos / <double>AV_TIME_BASE)\n                else:\n                    self.auddec.set_seek_pos(pos / <double>AV_TIME_BASE)\n            self.seek_pos = pos\n            self.seek_rel = rel\n            self.seek_flags &= ~AVSEEK_FLAG_BYTE\n            if seek_by_bytes:\n                self.seek_flags |= AVSEEK_FLAG_BYTE\n            self.seek_req = 1\n            self.continue_read_thread.lock()\n            self.continue_read_thread.cond_signal()\n            self.continue_read_thread.unlock()\n            if flush:\n                while not self.pictq.is_empty():\n                    self.pictq.frame_queue_next()\n        return 0\n\n    cdef int seek_chapter(VideoState self, int incr, int flush) nogil except 1:\n        cdef int64_t pos = <int64_t>(self.get_master_clock() * AV_TIME_BASE)\n        cdef int i\n        cdef AVChapter *ch\n\n        if not self.ic.nb_chapters:\n            return 0\n\n        # find the current chapter\n        for i in range(self.ic.nb_chapters):\n            ch = self.ic.chapters[i]\n            if av_compare_ts(pos, AV_TIME_BASE_Q, ch.start, ch.time_base) < 0:\n                i -= 1\n                break\n\n        i += incr\n        i = FFMAX(i, 0)\n        if i >= self.ic.nb_chapters:\n            return 0\n\n        if self.player.loglevel >= AV_LOG_VERBOSE:\n            av_log(NULL, AV_LOG_VERBOSE, b\"Seeking to chapter %d.\\n\", i)\n        self.stream_seek(av_rescale_q(self.ic.chapters[i].start, self.ic.chapters[i].time_base, AV_TIME_BASE_Q),\n                         0, 0, flush)\n        return 0\n\n    # pause or resume the video\n    cdef int toggle_pause(VideoState self) nogil except 1:\n        if self.paused:\n            self.frame_timer += av_gettime_relative() / 1000000.0 - self.vidclk.last_updated\n            if self.read_pause_return != AVERROR(ENOSYS):\n                self.vidclk.paused = 0\n            self.vidclk.set_clock(self.vidclk.get_clock(), self.vidclk.serial)\n        self.extclk.set_clock(self.extclk.get_clock(), self.extclk.serial)\n        self.paused = self.audclk.paused = self.vidclk.paused = self.extclk.paused = not self.paused\n        self.pause_cond.lock()\n        self.pause_cond.cond_signal()\n        self.pause_cond.unlock()\n        return 0\n\n    cdef double compute_target_delay(VideoState self, double delay) nogil except? 0.0:\n        cdef double sync_threshold, diff = 0\n\n        # update delay to follow master synchronisation source\n        if self.get_master_sync_type() != AV_SYNC_VIDEO_MASTER:\n            ''' if video is slave, we try to correct big delays by\n               duplicating or deleting a frame '''\n            diff = self.vidclk.get_clock() - self.get_master_clock()\n            ''' skip or repeat frame. We take into account the\n               delay to compute the threshold. I still don't know\n               if it is the best guess '''\n            sync_threshold = FFMAXD(AV_SYNC_THRESHOLD_MIN, FFMIND(AV_SYNC_THRESHOLD_MAX, delay))\n            if (not isnan(diff)) and fabs(diff) < self.max_frame_duration:\n                if diff <= -sync_threshold:\n                    delay = FFMAXD(0, delay + diff)\n                elif diff >= sync_threshold and delay > AV_SYNC_FRAMEDUP_THRESHOLD:\n                    delay = delay + diff\n                elif diff >= sync_threshold:\n                    delay = 2 * delay\n\n        if self.player.loglevel >= AV_LOG_TRACE:\n            av_log(NULL, AV_LOG_TRACE, b\"video: delay=%0.3f A-V=%f\\n\", delay, -diff)\n        return delay\n\n    cdef double vp_duration(VideoState self, Frame *vp, Frame *nextvp) nogil except? 0.0:\n        cdef double duration\n        if vp.serial == nextvp.serial:\n            duration = nextvp.pts - vp.pts\n            if isnan(duration) or duration <= 0 or duration > self.max_frame_duration:\n                return vp.duration\n            else:\n                return duration\n        else:\n            return 0.0\n\n    cdef void update_video_pts(VideoState self, double pts, int64_t pos, int serial) nogil:\n        # update current video pts\n        self.vidclk.set_clock(pts, serial)\n        self.extclk.sync_clock_to_slave(self.vidclk)\n\n    cdef int video_refresh(VideoState self, Image next_image, double *pts, double *remaining_time,\n                           int force_refresh) nogil except -1:\n        ''' Returns: 1 = paused, 2 = eof, 3 = no pic but remaining_time is set, 0 = valid image\n        '''\n        cdef Frame *vp\n        cdef Frame *vp_temp\n        cdef Frame *lastvp\n        cdef double time\n        cdef Frame *sp\n        cdef Frame *sp2\n        cdef int redisplay\n        cdef LoopState state = retry\n        cdef double last_duration, duration, delay\n        cdef Frame *nextvp\n        cdef int64_t cur_time\n        cdef int aqsize, vqsize, sqsize\n        cdef double av_diff\n        cdef const char *pat\n        cdef char *m\n        cdef int64_t m2, m3\n        cdef int result = 3\n        remaining_time[0] = 0.\n\n        self.pictq.alloc_picture()\n        if self.paused and not force_refresh:\n            return 1  # paused\n        if (not self.paused) and self.get_master_sync_type() == AV_SYNC_EXTERNAL_CLOCK and self.realtime:\n            self.check_external_clock_speed()\n\n        if self.video_st != NULL:\n            redisplay = 0\n            if force_refresh:\n                redisplay = self.pictq.frame_queue_prev()\n            while True:\n                if state == retry:\n                    if self.pictq.frame_queue_nb_remaining() == 0:\n                        if self.reached_eof:\n                            return 2  # eof\n                        # nothing to do, no picture to display in the queue\n                    else:\n                        # dequeue the picture\n                        lastvp = self.pictq.frame_queue_peek_last()\n                        vp = self.pictq.frame_queue_peek()\n                        if vp.serial != self.videoq.serial:\n                            self.pictq.frame_queue_next()\n                            redisplay = 0\n                            continue\n\n                        if lastvp.serial != vp.serial and not redisplay:\n                            self.frame_timer = av_gettime_relative() / 1000000.0\n\n                        if self.paused:\n                            state = display\n                            continue\n\n                        # compute nominal last_duration\n                        last_duration = self.vp_duration(lastvp, vp)\n                        if redisplay:\n                            delay = 0.0\n                        else:\n                            delay = self.compute_target_delay(last_duration)\n\n                        time = av_gettime_relative() / 1000000.0\n                        if time < self.frame_timer + delay and not redisplay:\n                            remaining_time[0] = self.frame_timer + delay - time\n\n                        self.frame_timer += delay\n                        if delay > 0 and time - self.frame_timer > AV_SYNC_THRESHOLD_MAX:\n                            self.frame_timer = time\n\n                        self.pictq.cond.lock()\n                        if (not redisplay) and not isnan(vp.pts):\n                            self.update_video_pts(vp.pts, vp.pos, vp.serial)\n                        self.pictq.cond.unlock()\n\n                        if self.pictq.frame_queue_nb_remaining() > 1:\n                            nextvp = self.pictq.frame_queue_peek_next()\n                            duration = self.vp_duration(vp, nextvp)\n                            if (redisplay or self.player.framedrop > 0 or\\\n                            (self.player.framedrop and self.get_master_sync_type() != AV_SYNC_VIDEO_MASTER))\\\n                            and time > self.frame_timer + duration:\n                                if not redisplay:\n                                    self.frame_drops_late += 1\n                                self.pictq.frame_queue_next()\n                                redisplay = 0\n                                continue\n\n                        if self.subtitle_st != NULL:\n                            while self.subpq.frame_queue_nb_remaining() > 0:\n                                sp = self.subpq.frame_queue_peek()\n\n                                if self.subpq.frame_queue_nb_remaining() > 1:\n                                    sp2 = self.subpq.frame_queue_peek_next()\n                                else:\n                                    sp2 = NULL\n\n                                if sp.serial != self.subtitleq.serial\\\n                                or (self.vidclk.pts > (sp.pts + <float> sp.sub.end_display_time / 1000.))\\\n                                or (sp2 != NULL and self.vidclk.pts > (sp2.pts + <float> sp2.sub.start_display_time / 1000.)):\n                                    self.subpq.frame_queue_next()\n                                else:\n                                    break\n                        state = display\n                        continue\n                elif state == display:\n                    # display picture\n                    if (not self.player.video_disable) and self.video_st != NULL:\n                        vp_temp = self.pictq.frame_queue_peek_last()\n                        if next_image is not None:\n                            next_image.cython_init(vp_temp.frame)\n                        pts[0] = vp_temp.pts\n                        result = 0\n                    self.pictq.frame_queue_next()\n                break\n\n        if self.player.show_status:\n\n            cur_time = av_gettime_relative()\n            if (not self.last_time) or (cur_time - self.last_time) >= 30000:\n                aqsize = 0\n                vqsize = 0\n                sqsize = 0\n                if self.audio_st != NULL:\n                    aqsize = self.audioq.size\n                if self.video_st != NULL:\n                    vqsize = self.videoq.size\n                if self.subtitle_st != NULL:\n                    sqsize = self.subtitleq.size\n                av_diff = 0\n                if self.audio_st != NULL and self.video_st != NULL:\n                    av_diff = self.audclk.get_clock() - self.vidclk.get_clock()\n                elif self.video_st != NULL:\n                    av_diff = self.get_master_clock() - self.vidclk.get_clock()\n                elif self.audio_st != NULL:\n                    av_diff = self.get_master_clock() - self.audclk.get_clock()\n\n                m = (str_av if self.audio_st != NULL and self.video_st != NULL else\\\n                (str_mv if self.video_st != NULL else (str_ma if self.audio_st != NULL else str_empty)))\n                m2 = self.viddec.avctx.pts_correction_num_faulty_dts if self.video_st != NULL else 0\n                m3 = self.viddec.avctx.pts_correction_num_faulty_pts if self.video_st != NULL else 0\n\n                if self.player.loglevel >= AV_LOG_INFO:\n                    av_log(NULL, AV_LOG_INFO,\n                       py_pat_str,\n                       self.get_master_clock(),\n                       m,\n                       av_diff,\n                       self.frame_drops_early + self.frame_drops_late,\n                       aqsize / 1024,\n                       vqsize / 1024,\n                       sqsize,\n                       m2,\n                       m3)\n                self.last_time = cur_time\n        return result\n\n    cdef int get_video_frame(VideoState self, AVFrame *frame) nogil except 2:\n        cdef int got_picture = self.viddec.decoder_decode_frame(frame, NULL, self.player.decoder_reorder_pts)\n        cdef double dpts = NAN, diff\n\n        if got_picture < 0:\n            return -1\n\n        if got_picture:\n            if frame.pts != AV_NOPTS_VALUE:\n                dpts = av_q2d(self.video_st.time_base) * frame.pts\n\n            frame.sample_aspect_ratio = av_guess_sample_aspect_ratio(self.ic, self.video_st, frame)\n            if self.viddec.is_seeking() or self.auddec.is_seeking():\n                if dpts == NAN or dpts >= self.viddec.seek_req_pos:\n                    if self.viddec.is_seeking():\n                        self.viddec.set_seek_pos(-1)\n                else:\n                    av_frame_unref(frame)\n                    return 0\n\n            if self.player.framedrop > 0 or (self.player.framedrop and\\\n            self.get_master_sync_type() != AV_SYNC_VIDEO_MASTER):\n                if frame.pts != AV_NOPTS_VALUE:\n                    diff = dpts - self.get_master_clock()\n                    if (not isnan(diff)) and\\\n                    fabs(diff) < AV_NOSYNC_THRESHOLD and\\\n                    diff - self.frame_last_filter_delay < 0 and\\\n                    self.viddec.pkt_serial == self.vidclk.serial and\\\n                    self.videoq.nb_packets:\n                        self.frame_drops_early += 1\n                        av_frame_unref(frame)\n                        got_picture = 0\n        return got_picture\n\n    IF CONFIG_AVFILTER:\n        cdef int configure_filtergraph(VideoState self, AVFilterGraph *graph, const char *filtergraph,\n                                       AVFilterContext *source_ctx, AVFilterContext *sink_ctx) nogil except? 1:\n            cdef int ret = 0, i\n            cdef int nb_filters = graph.nb_filters\n            cdef AVFilterInOut *outputs = NULL\n            cdef AVFilterInOut *inputs = NULL\n            cdef AVFilterContext *filt_ctx\n\n            if filtergraph != NULL:\n                outputs = avfilter_inout_alloc()\n                inputs  = avfilter_inout_alloc()\n                if outputs == NULL or inputs == NULL:\n                    ret = AVERROR(ENOMEM)\n\n                if not ret:\n                    outputs.name       = av_strdup(b\"in\")\n                    outputs.filter_ctx = source_ctx\n                    outputs.pad_idx    = 0\n                    outputs.next       = NULL\n\n                    inputs.name        = av_strdup(b\"out\")\n                    inputs.filter_ctx  = sink_ctx\n                    inputs.pad_idx     = 0\n                    inputs.next        = NULL\n\n                    ret = avfilter_graph_parse_ptr(graph, filtergraph, &inputs,\n                                                   &outputs, NULL)\n                    if ret > 0:\n                        ret = 0\n            else:\n                ret = avfilter_link(source_ctx, 0, sink_ctx, 0)\n                if ret > 0:\n                    ret = 0\n            if not ret:\n                for i in range(graph.nb_filters - nb_filters):\n                    filt_ctx = graph.filters[i]\n                    graph.filters[i] = graph.filters[i + nb_filters]\n                    graph.filters[i + nb_filters] = filt_ctx\n                ret = avfilter_graph_config(graph, NULL)\n            avfilter_inout_free(&outputs)\n            avfilter_inout_free(&inputs)\n            return ret\n\n        cdef int configure_video_filters(VideoState self, AVFilterGraph *graph,\n                                         const char *vfilters, AVFrame *frame,\n                                         AVPixelFormat pix_fmt) nogil except? 1:\n            cdef char sws_flags_str[512]\n            cdef char buffersrc_args[256]\n            cdef char scale_args[256]\n            cdef char str_flags[64]\n            cdef int ret\n            cdef int32_t *displaymatrix = NULL\n            cdef AVFilterContext *filt_src = NULL\n            cdef AVFilterContext *filt_out = NULL\n            cdef AVFilterContext *last_filter = NULL\n            cdef AVFilterContext *filt_scale = NULL\n            cdef AVCodecParameters *codecpar = self.video_st.codecpar\n            cdef AVRational fr = av_guess_frame_rate(self.ic, self.video_st, NULL)\n            cdef AVPixelFormat *pix_fmts = [pix_fmt, AV_PIX_FMT_NONE]\n            cdef double rot\n            cdef double theta = 0\n            cdef char rotate_buf[64]\n            cdef const AVDictionaryEntry *e = NULL\n            cdef AVFrameSideData *sd = NULL\n            memset(str_flags, 0, sizeof(str_flags))\n            memset(sws_flags_str, 0, sizeof(sws_flags_str))\n            strcpy(str_flags, b\"flags=%\")\n            strcat(str_flags, PRId64)\n\n            e = av_dict_get(self.player.sws_dict, b\"\", e, AV_DICT_IGNORE_SUFFIX)\n            while e != NULL:\n                if not strcmp(e.key, b\"sws_flags\"):\n                    av_strlcatf(sws_flags_str, sizeof(sws_flags_str), b\"%s=%s:\", b\"flags\", e.value)\n                else:\n                    av_strlcatf(sws_flags_str, sizeof(sws_flags_str), b\"%s=%s:\", e.key, e.value)\n                e = av_dict_get(self.player.sws_dict, b\"\", e, AV_DICT_IGNORE_SUFFIX)\n            if strlen(sws_flags_str):\n                sws_flags_str[strlen(sws_flags_str) - 1] = b'\\0'\n\n            graph.scale_sws_opts = av_strdup(sws_flags_str)\n\n            snprintf(buffersrc_args, sizeof(buffersrc_args),\n                     b\"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d\",\n                     frame.width, frame.height, frame.format,\n                     self.video_st.time_base.num, self.video_st.time_base.den,\n                     codecpar.sample_aspect_ratio.num, FFMAX(codecpar.sample_aspect_ratio.den, 1))\n            if fr.num and fr.den:\n                av_strlcatf(buffersrc_args, sizeof(buffersrc_args), b\":frame_rate=%d/%d\", fr.num, fr.den)\n\n            ret = avfilter_graph_create_filter(&filt_src, avfilter_get_by_name(b\"buffer\"),\n                                               b\"ffpyplayer_buffer\", buffersrc_args, NULL, graph)\n            if ret < 0:\n                return ret\n\n            ret = avfilter_graph_create_filter(&filt_out, avfilter_get_by_name(b\"buffersink\"),\n                                               b\"ffpyplayer_buffersink\", NULL, NULL, graph)\n            if ret < 0:\n                return ret\n\n            ret = av_opt_set_int_list(filt_out, b\"pix_fmts\", pix_fmts,\n                                      sizeof(pix_fmts[0]), AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN)\n            if ret < 0:\n                return ret\n\n            last_filter = filt_out\n\n            ''' SDL YUV code is not handling odd width/height for some driver\n            combinations, therefore we crop the picture to an even width/height. '''\n            ret = insert_filt(b\"crop\", b\"floor(in_w/2)*2:floor(in_h/2)*2\", graph, &last_filter)\n            if ret < 0:\n                return ret\n\n            if self.player.autorotate:\n                sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)\n                if sd != NULL:\n                    displaymatrix = <int32_t *>sd.data\n                if displaymatrix == NULL:\n                    displaymatrix = <int32_t *>av_stream_get_side_data(self.video_st, AV_PKT_DATA_DISPLAYMATRIX, NULL)\n                theta = get_rotation(displaymatrix)\n                if fabs(theta - 90) < 1.0:\n                    insert_filt(b\"transpose\", b\"clock\", graph, &last_filter)\n                elif fabs(theta - 180) < 1.0:\n                    insert_filt(b\"hflip\", NULL, graph, &last_filter)\n                    insert_filt(b\"vflip\", NULL, graph, &last_filter)\n                elif fabs(theta - 270) < 1.0:\n                    insert_filt(b\"transpose\", b\"cclock\", graph, &last_filter)\n                elif fabs(theta) > 1.0:\n                    snprintf(rotate_buf, sizeof(rotate_buf), b\"%f*PI/180\", theta)\n                    insert_filt(b\"rotate\", rotate_buf, graph, &last_filter)\n\n            if self.player.screen_height or self.player.screen_width:\n                snprintf(scale_args, sizeof(scale_args), b\"%d:%d\", self.player.screen_width,\n                         self.player.screen_height)\n                ret = avfilter_graph_create_filter(&filt_scale, avfilter_get_by_name(b\"scale\"),\n                                                   b\"ffpyplayer_scale\", scale_args,\n                                                   NULL, graph)\n                if ret < 0:\n                    return ret\n\n                ret = avfilter_link(filt_scale, 0, last_filter, 0)\n                if ret < 0:\n                    return ret\n                # this needs to be here in case user provided filter at the input\n                ret = self.configure_filtergraph(graph, vfilters, filt_src, filt_scale)\n                if ret < 0:\n                    return ret\n            else:\n                ret = self.configure_filtergraph(graph, vfilters, filt_src, last_filter)\n                if ret < 0:\n                    return ret\n\n            self.in_video_filter  = filt_src\n            self.out_video_filter = filt_out\n            return ret\n\n        cdef int configure_audio_filters(VideoState self, const char *afilters, int force_output_format) nogil except? 1:\n            cdef int *sample_rates = [0, -1]\n            cdef int64_t *channel_layouts = [0, -1]\n            cdef int *channels = [0, -1]\n            cdef AVFilterContext *filt_asrc = NULL\n            cdef AVFilterContext *filt_asink = NULL\n            cdef char aresample_swr_opts[512]\n            cdef const AVDictionaryEntry *e = NULL\n            cdef char asrc_args[256]\n            cdef char str_flags[64]\n            cdef int ret\n\n            memset(str_flags, 0, sizeof(str_flags))\n            strcpy(str_flags, b\":channel_layout=0x%\")\n            strcat(str_flags, PRIx64)\n            aresample_swr_opts[0] = 0\n            avfilter_graph_free(&self.agraph)\n            self.agraph = avfilter_graph_alloc()\n            if self.agraph == NULL:\n                return AVERROR(ENOMEM)\n            self.agraph.nb_threads = self.player.filter_threads\n            e = av_dict_get(self.player.swr_opts, b\"\", e, AV_DICT_IGNORE_SUFFIX)\n            while e != NULL:\n                av_strlcatf(aresample_swr_opts, sizeof(aresample_swr_opts), b\"%s=%s:\", e.key, e.value)\n                e = av_dict_get(self.player.swr_opts, b\"\", e, AV_DICT_IGNORE_SUFFIX)\n            if strlen(aresample_swr_opts):\n                aresample_swr_opts[strlen(aresample_swr_opts)-1] = b'\\0'\n            av_opt_set(self.agraph, b\"aresample_swr_opts\", aresample_swr_opts, 0)\n\n            ret = snprintf(asrc_args, sizeof(asrc_args),\n                           b\"sample_rate=%d:sample_fmt=%s:channels=%d:time_base=%d/%d\",\n                           self.audio_filter_src.freq, av_get_sample_fmt_name(self.audio_filter_src.fmt),\n                           self.audio_filter_src.channels, 1, self.audio_filter_src.freq)\n            if self.audio_filter_src.channel_layout:\n                snprintf(asrc_args + ret, sizeof(asrc_args) - ret, str_flags,\n                         self.audio_filter_src.channel_layout)\n\n            ret = avfilter_graph_create_filter(&filt_asrc, avfilter_get_by_name(b\"abuffer\"),\n                                               b\"ffpyplayer_abuffer\", asrc_args, NULL, self.agraph)\n            if ret >= 0:\n                ret = avfilter_graph_create_filter(&filt_asink, avfilter_get_by_name(b\"abuffersink\"),\n                                                   b\"ffpyplayer_abuffersink\", NULL, NULL, self.agraph)\n            if ret >= 0:\n                ret = av_opt_set_int_list(filt_asink, b\"sample_fmts\", sample_fmts, sizeof(sample_fmts[0]),\n                                          AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN)\n            if ret >= 0:\n                ret = av_opt_set_int(filt_asink, b\"all_channel_counts\", 1, AV_OPT_SEARCH_CHILDREN)\n            if ret >= 0 and force_output_format:\n                channel_layouts[0] = self.audio_tgt.channel_layout\n                channels       [0] = -1 if self.audio_tgt.channel_layout else self.audio_tgt.channels\n                sample_rates   [0] = self.audio_tgt.freq\n                ret = av_opt_set_int(filt_asink, b\"all_channel_counts\", 0, AV_OPT_SEARCH_CHILDREN)\n                if ret >= 0:\n                    ret = av_opt_set_int_list(filt_asink, b\"channel_layouts\", channel_layouts, sizeof(channel_layouts[0]),\n                                              -1, AV_OPT_SEARCH_CHILDREN)\n                if ret >= 0:\n                    ret = av_opt_set_int_list(filt_asink, b\"channel_counts\", channels, sizeof(channels[0]),\n                                              -1, AV_OPT_SEARCH_CHILDREN)\n                if ret >= 0:\n                    ret = av_opt_set_int_list(filt_asink, b\"sample_rates\", sample_rates, sizeof(sample_rates[0]),\n                                              -1, AV_OPT_SEARCH_CHILDREN)\n            if ret >= 0:\n                ret = self.configure_filtergraph(self.agraph, afilters, filt_asrc, filt_asink)\n            if ret >= 0:\n                self.in_audio_filter  = filt_asrc\n                self.out_audio_filter = filt_asink\n            if ret < 0:\n                avfilter_graph_free(&self.agraph)\n            return ret\n\n    cdef int audio_thread(self) nogil except? 1:\n        cdef AVFrame *frame = av_frame_alloc()\n        cdef Frame *af\n        cdef int got_frame = 0\n        cdef AVRational tb\n        cdef int ret = 0\n        cdef char err_msg[256]\n\n        IF CONFIG_AVFILTER:\n            cdef int last_serial = -1\n            cdef int64_t dec_channel_layout\n            cdef int reconfigure\n            cdef char buf1[1024]\n            cdef char buf2[1024]\n\n        if frame == NULL:\n            if self.player.loglevel >= AV_LOG_ERROR:\n                av_log(NULL, AV_LOG_ERROR, b'Memory error in audio thread\\n')\n            self.request_thread_s(b'audio:error', fmt_err(AVERROR(ENOMEM), err_msg, sizeof(err_msg)))\n            return AVERROR(ENOMEM)\n\n        while True:\n            ret = 0\n            got_frame = self.auddec.decoder_decode_frame(frame, NULL, self.player.decoder_reorder_pts)\n            if got_frame < 0:\n                ret = -1\n                break\n\n            if got_frame:\n                tb.num = 1\n                tb.den = frame.sample_rate\n\n                IF CONFIG_AVFILTER:\n                    dec_channel_layout = get_valid_channel_layout(frame.channel_layout, frame.channels)\n                    reconfigure = (\n                        cmp_audio_fmts(self.audio_filter_src.fmt, self.audio_filter_src.channels,\n                                       <AVSampleFormat>frame.format, frame.channels) or\n                        self.audio_filter_src.channel_layout != dec_channel_layout or\n                        self.audio_filter_src.freq != frame.sample_rate or\n                        self.auddec.pkt_serial != last_serial)\n\n                    if reconfigure:\n                        av_get_channel_layout_string(buf1, sizeof(buf1), -1, self.audio_filter_src.channel_layout)\n                        av_get_channel_layout_string(buf2, sizeof(buf2), -1, dec_channel_layout)\n                        if self.player.loglevel >= AV_LOG_DEBUG:\n                            av_log(NULL, AV_LOG_DEBUG,\n                               b\"Audio frame changed from rate:%d ch:%d fmt:%s layout:%s serial:%d to rate:%d ch:%d fmt:%s layout:%s serial:%d\\n\",\n                               self.audio_filter_src.freq, self.audio_filter_src.channels,\n                               av_get_sample_fmt_name(self.audio_filter_src.fmt), buf1, last_serial,\n                               frame.sample_rate, frame.channels,\n                               av_get_sample_fmt_name(<AVSampleFormat>frame.format), buf2, self.auddec.pkt_serial)\n\n                        self.audio_filter_src.fmt = <AVSampleFormat>frame.format\n                        self.audio_filter_src.channels = frame.channels\n                        self.audio_filter_src.channel_layout = dec_channel_layout\n                        self.audio_filter_src.freq = frame.sample_rate\n                        last_serial = self.auddec.pkt_serial\n\n                        ret = self.configure_audio_filters(self.player.afilters, 1)\n                        if ret < 0:\n                            break\n\n                    ret = av_buffersrc_add_frame(self.in_audio_filter, frame)\n                    if ret < 0:\n                        break\n\n                    ret = av_buffersink_get_frame_flags(self.out_audio_filter, frame, 0)\n                    while ret >= 0:\n                        tb = av_buffersink_get_time_base(self.out_audio_filter)\n                        af = self.sampq.frame_queue_peek_writable()\n                        if af == NULL:\n                            avfilter_graph_free(&self.agraph)\n                            av_frame_free(&frame)\n                            if self.audioq.abort_request:\n                                self.request_thread_s(b'audio:exit', b'')\n                            else:\n                                if self.player.loglevel >= AV_LOG_ERROR:\n                                    av_log(NULL, AV_LOG_ERROR, b'Error getting writable audio frame\\n')\n                                self.request_thread_s(b'audio:error', fmt_err(ret, err_msg, sizeof(err_msg)))\n                            return ret\n\n                        af.pts = NAN if frame.pts == AV_NOPTS_VALUE else frame.pts * av_q2d(tb)\n                        af.pos = frame.pkt_pos\n                        af.serial = self.auddec.pkt_serial\n                        tb.num = frame.nb_samples\n                        tb.den = frame.sample_rate\n                        af.duration = av_q2d(tb)\n\n                        av_frame_move_ref(af.frame, frame)\n                        self.sampq.frame_queue_push()\n\n                        if self.audioq.serial != self.auddec.pkt_serial:\n                            break\n                        ret = av_buffersink_get_frame_flags(self.out_audio_filter, frame, 0)\n\n                    if ret == AVERROR_EOF:\n                        self.auddec.finished = self.auddec.pkt_serial\n                ELSE:\n                    af = self.sampq.frame_queue_peek_writable()\n                    if af == NULL:\n                       break\n\n                    af.pts = NAN if frame.pts == AV_NOPTS_VALUE else frame.pts * av_q2d(tb)\n                    af.pos = frame.pkt_pos\n                    af.serial = self.auddec.pkt_serial\n                    tb.num = frame.nb_samples\n                    tb.den = frame.sample_rate\n                    af.duration = av_q2d(tb)\n\n                    av_frame_move_ref(af.frame, frame)\n                    self.sampq.frame_queue_push()\n\n            if ret < 0 and ret != AVERROR(EAGAIN) and ret != AVERROR_EOF:\n                break\n\n        IF CONFIG_AVFILTER:\n            avfilter_graph_free(&self.agraph)\n        av_frame_free(&frame)\n        if ret and not self.audioq.abort_request:\n            if ret != -1:\n                if self.player.loglevel >= AV_LOG_ERROR:\n                    av_log(NULL, AV_LOG_ERROR, b'Audio thread error: %s\\n', fmt_err(ret, err_msg, sizeof(err_msg)))\n                self.request_thread_s(b'audio:error', fmt_err(ret, err_msg, sizeof(err_msg)))\n            else:\n                if self.player.loglevel >= AV_LOG_ERROR:\n                    av_log(NULL, AV_LOG_ERROR, b'Audio thread error\\n')\n                self.request_thread_s(b'audio:error', b'')\n        else:\n            self.request_thread_s(b'audio:exit', b'')\n        return ret\n\n    cdef int video_thread(VideoState self) nogil except? 1:\n        cdef AVFrame *frame = av_frame_alloc()\n        cdef double pts, duration\n        cdef int ret\n        cdef AVRational tb = self.video_st.time_base\n        cdef AVRational tb_temp\n        cdef AVRational frame_rate = av_guess_frame_rate(self.ic, self.video_st, NULL)\n        cdef AVRational sar\n        cdef char err_msg[256]\n        cdef AVPixelFormat last_out_fmt = self.pix_fmt\n        IF CONFIG_AVFILTER:\n            cdef AVFilterGraph *graph = NULL\n            cdef AVFilterContext *filt_out = NULL\n            cdef AVFilterContext *filt_in = NULL\n            cdef int last_w = 0\n            cdef int last_h = 0\n            cdef int last_scr_h = 0, last_scr_w = 0\n            cdef AVPixelFormat last_format = <AVPixelFormat>-2\n            cdef AVPixelFormat last_out_fmt_temp\n            cdef int last_serial = -1\n            cdef int last_vfilter_idx = self.vfilter_idx\n\n        if frame == NULL:\n            if self.player.loglevel >= AV_LOG_ERROR:\n                av_log(NULL, AV_LOG_ERROR, b'Memory Error in video thread\\n')\n            self.request_thread_s(b'video:error', fmt_err(AVERROR(ENOMEM), err_msg, sizeof(err_msg)))\n            return AVERROR(ENOMEM)\n\n        while 1:\n            av_frame_unref(frame)\n            ret = self.get_video_frame(frame)\n            if ret < 0:\n                break\n            if not ret:\n                continue\n\n            IF CONFIG_AVFILTER:\n                last_out_fmt_temp = self.pix_fmt\n                if (last_w != frame.width or last_h != frame.height\n                    or last_scr_h != self.player.screen_height\n                    or last_scr_w != self.player.screen_width\n                    or last_format != frame.format or last_serial != self.viddec.pkt_serial\n                    or last_vfilter_idx != self.vfilter_idx\n                    or last_out_fmt != last_out_fmt_temp):\n\n                    if self.player.loglevel >= AV_LOG_DEBUG:\n                        av_log(NULL, AV_LOG_DEBUG,\n                           b\"Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\\n\",\n                           last_w, last_h,\n                           <const char *>av_x_if_null(av_get_pix_fmt_name(last_format), b\"none\"), last_serial,\n                           frame.width, frame.height,\n                           <const char *>av_x_if_null(av_get_pix_fmt_name(<AVPixelFormat>frame.format), b\"none\"),\n                           self.viddec.pkt_serial)\n\n                    avfilter_graph_free(&graph)\n                    graph = avfilter_graph_alloc()\n                    if graph == NULL:\n                        ret = AVERROR(ENOMEM)\n                        break\n\n                    graph.nb_threads = self.player.filter_threads\n                    ret = self.configure_video_filters(\n                        graph, self.player.vfilters_list[self.vfilter_idx] if self.player.vfilters_list != NULL else NULL,\n                        frame, last_out_fmt_temp)\n                    if ret < 0:\n                        break\n\n                    filt_in  = self.in_video_filter\n                    filt_out = self.out_video_filter\n                    last_w = frame.width\n                    last_h = frame.height\n                    last_scr_h = self.player.screen_height\n                    last_scr_w = self.player.screen_width\n                    last_format = <AVPixelFormat>frame.format\n                    last_out_fmt = last_out_fmt_temp\n                    last_serial = self.viddec.pkt_serial\n                    frame_rate = av_buffersink_get_frame_rate(filt_out)\n                    last_vfilter_idx = self.vfilter_idx\n                    sar = <AVRational>frame.sample_aspect_ratio\n                    with gil:\n                        self.metadata['src_vid_size'] = (last_w, last_h)\n                        self.metadata['aspect_ratio'] = (sar.num, sar.den)\n                        self.metadata['frame_rate'] = (frame_rate.num, frame_rate.den)\n\n                ret = av_buffersrc_add_frame(filt_in, frame)\n                if ret < 0:\n                    break\n\n                while ret >= 0:\n                    self.frame_last_returned_time = av_gettime_relative() / 1000000.0\n                    ret = av_buffersink_get_frame_flags(filt_out, frame, 0)\n                    if ret < 0:\n                        if ret == AVERROR_EOF:\n                            self.viddec.finished = self.viddec.pkt_serial\n                        ret = 0\n                        break\n\n                    self.frame_last_filter_delay = av_gettime_relative() / 1000000.0 - self.frame_last_returned_time\n                    if fabs(self.frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0:\n                        self.frame_last_filter_delay = 0\n\n                    tb = av_buffersink_get_time_base(filt_out)\n                    duration = 0\n                    if frame_rate.num and frame_rate.den:\n                        tb_temp.num = frame_rate.den\n                        tb_temp.den = frame_rate.num\n                        duration = av_q2d(tb_temp)\n                    if frame.pts == AV_NOPTS_VALUE:\n                        pts = NAN\n                    else:\n                        pts = frame.pts * av_q2d(tb)\n                    ret = self.pictq.queue_picture(frame, pts, duration, frame.pkt_pos,\n                                             self.viddec.pkt_serial, last_out_fmt, &self.abort_request, self.player)\n                    #av_frame_unref(frame)\n                    if self.videoq.serial != self.viddec.pkt_serial:\n                        break\n            ELSE:\n                duration = 0\n                if frame_rate.num and frame_rate.den:\n                    tb_temp.num = frame_rate.den\n                    tb_temp.den = frame_rate.num\n                    duration = av_q2d(tb_temp)\n                if frame.pts == AV_NOPTS_VALUE:\n                    pts = NAN\n                else:\n                    pts = frame.pts * av_q2d(tb)\n                sar = <AVRational>frame.sample_aspect_ratio\n                with gil:\n                    self.metadata['src_vid_size'] = (frame.width, frame.height)\n                    self.metadata['aspect_ratio'] = (sar.num, sar.den)\n                    self.metadata['frame_rate'] = (frame_rate.num, frame_rate.den)\n                ret = self.pictq.queue_picture(frame, pts, duration, frame.pkt_pos,\n                                         self.viddec.pkt_serial, last_out_fmt, &self.abort_request,\n                                         self.player)\n                #av_frame_unref(frame)\n\n            if ret < 0:\n                break\n\n        IF CONFIG_AVFILTER:\n            avfilter_graph_free(&graph)\n        av_frame_free(&frame)\n\n        if ret and not self.videoq.abort_request:\n            if ret != -1:\n                if self.player.loglevel >= AV_LOG_ERROR:\n                    av_log(NULL, AV_LOG_ERROR, b'Video thread error: %s\\n', fmt_err(ret, err_msg, sizeof(err_msg)))\n                self.request_thread_s(b'video:error', fmt_err(ret, err_msg, sizeof(err_msg)))\n            else:\n                if self.player.loglevel >= AV_LOG_ERROR:\n                    av_log(NULL, AV_LOG_ERROR, b'Video thread error\\n')\n                self.request_thread_s(b'video:error', b'')\n        else:\n            self.request_thread_s(b'video:exit', b'')\n        return 0\n\n    cdef int subtitle_thread(VideoState self) nogil except 1:\n        cdef Frame *sp\n        cdef int got_subtitle\n        cdef double pts\n        cdef int i, j, ret = 0\n        cdef int r, g, b, y, u, v, a\n        cdef char err_msg[256]\n\n        while 1:\n            sp = self.subpq.frame_queue_peek_writable()\n            if sp == NULL:\n                ret = -1\n                break\n\n            got_subtitle = self.subdec.decoder_decode_frame(NULL, &sp.sub, self.player.decoder_reorder_pts)\n            if got_subtitle < 0:\n                ret = -1\n                break\n            pts = 0\n\n#             if got_subtitle and sp.sub.format == 0:\n#                 if sp.sub.pts != AV_NOPTS_VALUE:\n#                     pts = sp.sub.pts / <double>AV_TIME_BASE\n#                 sp.pts = pts\n#                 sp.serial = self.subdec.pkt_serial\n#\n#                 for i in range(sp.sub.num_rects):\n#                     for j in range(sp.sub.rects[i].nb_colors):\n#                         sp.sub.rects[i]\n#\n#                 self.subpq.frame_queue_push()\n            if got_subtitle:\n                if sp.sub.format != 0:\n                    self.subtitle_display(&sp.sub)\n                avsubtitle_free(&sp.sub)\n\n        if ret and not self.subtitleq.abort_request:\n            if ret != -1:\n                if self.player.loglevel >= AV_LOG_ERROR:\n                    av_log(NULL, AV_LOG_ERROR, b'Subtitle thread error: %s\\n', fmt_err(ret, err_msg, sizeof(err_msg)))\n                self.request_thread_s(b'subtitle:error', fmt_err(ret, err_msg, sizeof(err_msg)))\n            else:\n                if self.player.loglevel >= AV_LOG_ERROR:\n                    av_log(NULL, AV_LOG_ERROR, b'Subtitle thread error\\n')\n                self.request_thread_s(b'subtitle:error', b'')\n        else:\n            self.request_thread_s(b'subtitle:exit', b'')\n        return 0\n\n    cdef int subtitle_display(self, AVSubtitle *sub) nogil except 1:\n        cdef PyObject *buff\n        cdef int i\n        cdef double pts\n        with gil:\n            for i in range(sub.num_rects):\n                if sub.rects[i].type == SUBTITLE_ASS:\n                    buff = PyUnicode_FromString(sub.rects[i].ass)\n                    sub_fmt = sub_ass\n                elif sub.rects[i].type == SUBTITLE_TEXT:\n                    buff = PyUnicode_FromString(sub.rects[i].text)\n                    sub_fmt = sub_text\n                else:\n                    buff = NULL\n                    continue\n                if sub.pts != AV_NOPTS_VALUE:\n                    pts = sub.pts / <double>AV_TIME_BASE\n                else:\n                    pts = 0.0\n                self.request_thread(b'display_sub', (\n                    <object>buff, sub_fmt, pts, sub.start_display_time / 1000.,\n                    sub.end_display_time / 1000.))\n                if buff != NULL:\n                    Py_DECREF(buff)\n        return 0\n\n    # copy samples for viewing in editor window\n    cdef int update_sample_display(VideoState self, int16_t *samples, int samples_size) nogil except 1:\n        cdef int size, len\n\n        size = samples_size // sizeof(short)\n        while size > 0:\n            len = SAMPLE_ARRAY_SIZE - self.sample_array_index\n            if len > size:\n                len = size\n            memcpy(&self.sample_array[self.sample_array_index], samples, len * sizeof(short))\n            samples += len\n            self.sample_array_index += len\n            if self.sample_array_index >= SAMPLE_ARRAY_SIZE:\n                self.sample_array_index = 0\n            size -= len\n        return 0\n\n    ''' return the wanted number of samples to get better sync if sync_type is video\n    or external master clock '''\n    cdef int synchronize_audio(VideoState self, int nb_samples) nogil except -1:\n        cdef int wanted_nb_samples = nb_samples\n        cdef double diff, avg_diff\n        cdef int min_nb_samples, max_nb_samples\n\n        # if not master, then we try to remove or add samples to correct the clock\n        if self.get_master_sync_type() != AV_SYNC_AUDIO_MASTER:\n            diff = self.audclk.get_clock() - self.get_master_clock()\n\n            if (not isnan(diff)) and fabs(diff) < AV_NOSYNC_THRESHOLD:\n                self.audio_diff_cum = diff + self.audio_diff_avg_coef * self.audio_diff_cum\n                if self.audio_diff_avg_count < AUDIO_DIFF_AVG_NB:\n                    # not enough measures to have a correct estimate\n                    self.audio_diff_avg_count += 1\n                else:\n                    # estimate the A-V difference\n                    avg_diff = self.audio_diff_cum * (1.0 - self.audio_diff_avg_coef)\n                    if fabs(avg_diff) >= self.audio_diff_threshold:\n                        wanted_nb_samples = nb_samples + <int>(diff * self.audio_src.freq)\n                        min_nb_samples = nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) // 100\n                        max_nb_samples = nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) // 100\n                        wanted_nb_samples = av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples)\n                    if self.player.loglevel >= AV_LOG_TRACE:\n                        av_log(NULL, AV_LOG_TRACE, b\"diff=%f adiff=%f sample_diff=%d apts=%0.3f %f\\n\",\n                           diff, avg_diff, wanted_nb_samples - nb_samples,\n                           self.audio_clock, self.audio_diff_threshold)\n            else:\n                ''' too big difference : may be initial PTS errors, so\n                   reset A-V filter '''\n                self.audio_diff_avg_count = 0\n                self.audio_diff_cum       = 0\n        return wanted_nb_samples\n\n\n    '''\n       Decode one audio frame and return its uncompressed size.\n\n       The processed audio frame is decoded, converted if required, and\n       stored in is->audio_buf, with size in bytes given by the return\n       value.\n    '''\n    cdef int audio_decode_frame(VideoState self) nogil except? 1:\n        cdef int data_size, resampled_data_size\n        cdef int64_t dec_channel_layout\n        cdef double audio_clock0\n        cdef int wanted_nb_samples\n\n        cdef const uint8_t **input\n        cdef uint8_t **out\n        cdef int out_count\n        cdef int out_size\n        cdef int len2\n        cdef Frame *af\n\n        if self.paused:\n            return -1\n\n        while True:\n            if WIN_IS_DEFINED:\n                while self.sampq.frame_queue_nb_remaining() == 0:\n                    if ((av_gettime_relative() - self.player.audio_callback_time) >\n                        1000000LL * self.audio_hw_buf_size / self.audio_tgt.bytes_per_sec / 2.):\n                        return -1\n                    av_usleep(1000)\n\n            af = self.sampq.frame_queue_peek_readable()\n            if af == NULL:\n                return -1\n\n            self.sampq.frame_queue_next()\n            if af.serial == self.audioq.serial:\n                break\n\n        data_size = av_samples_get_buffer_size(NULL, af.frame.channels,\n                                               af.frame.nb_samples, <AVSampleFormat>af.frame.format, 1)\n\n        if af.frame.channel_layout and af.frame.channels ==\\\n        av_get_channel_layout_nb_channels(af.frame.channel_layout):\n            dec_channel_layout = af.frame.channel_layout\n        else:\n            dec_channel_layout = av_get_default_channel_layout(af.frame.channels)\n        wanted_nb_samples = self.synchronize_audio(af.frame.nb_samples)\n\n        if (af.frame.format != self.audio_src.fmt or\n            dec_channel_layout != self.audio_src.channel_layout or\n            af.frame.sample_rate != self.audio_src.freq or\n            (wanted_nb_samples != af.frame.nb_samples and self.swr_ctx == NULL)):\n            swr_free(&self.swr_ctx)\n            self.swr_ctx = swr_alloc_set_opts(NULL, self.audio_tgt.channel_layout,\n                                              self.audio_tgt.fmt, self.audio_tgt.freq,\n                                              dec_channel_layout, <AVSampleFormat>af.frame.format,\n                                              af.frame.sample_rate, 0, NULL)\n            if self.swr_ctx == NULL or swr_init(self.swr_ctx) < 0:\n                if self.player.loglevel >= AV_LOG_ERROR:\n                    av_log(NULL, AV_LOG_ERROR, b\"Cannot create sample rate converter for \\\n                conversion of %d Hz %s %d channels to %d Hz %s %d channels!\\n\",\\\n                af.frame.sample_rate, av_get_sample_fmt_name(<AVSampleFormat>af.frame.format),\\\n                af.frame.channels, self.audio_tgt.freq,\\\n                av_get_sample_fmt_name(self.audio_tgt.fmt), self.audio_tgt.channels)\n                return -1\n            self.audio_src.channel_layout = dec_channel_layout\n            self.audio_src.channels = af.frame.channels\n            self.audio_src.freq = af.frame.sample_rate\n            self.audio_src.fmt = <AVSampleFormat>af.frame.format\n\n        if self.swr_ctx != NULL:\n            input = <const uint8_t **>af.frame.extended_data\n            out = &self.audio_buf1\n            out_count = <int64_t>wanted_nb_samples * self.audio_tgt.freq // af.frame.sample_rate + 256\n            out_size  = av_samples_get_buffer_size(NULL, self.audio_tgt.channels, out_count, self.audio_tgt.fmt, 0)\n            if out_size < 0:\n                if self.player.loglevel >= AV_LOG_ERROR:\n                    av_log(NULL, AV_LOG_ERROR, b\"av_samples_get_buffer_size() failed\\n\")\n                return -1\n\n            if wanted_nb_samples != af.frame.nb_samples:\n                if swr_set_compensation(self.swr_ctx, (wanted_nb_samples - af.frame.nb_samples)\\\n                * self.audio_tgt.freq // af.frame.sample_rate, wanted_nb_samples *\\\n                self.audio_tgt.freq // af.frame.sample_rate) < 0:\n                    if self.player.loglevel >= AV_LOG_ERROR:\n                        av_log(NULL, AV_LOG_ERROR, b\"swr_set_compensation() failed\\n\")\n                    return -1\n\n            av_fast_malloc(&self.audio_buf1, &self.audio_buf1_size, out_size)\n            if self.audio_buf1 == NULL:\n                return AVERROR(ENOMEM)\n            len2 = swr_convert(self.swr_ctx, out, out_count, input, af.frame.nb_samples)\n            if len2 < 0:\n                if self.player.loglevel >= AV_LOG_ERROR:\n                    av_log(NULL, AV_LOG_ERROR, b\"swr_convert() failed\\n\")\n                return -1\n\n            if len2 == out_count:\n                if self.player.loglevel >= AV_LOG_WARNING:\n                    av_log(NULL, AV_LOG_WARNING, b\"audio buffer is probably too small\\n\")\n                if swr_init(self.swr_ctx) < 0:\n                    swr_free(&self.swr_ctx)\n            self.audio_buf = self.audio_buf1\n            resampled_data_size = len2 * self.audio_tgt.channels * av_get_bytes_per_sample(self.audio_tgt.fmt)\n        else:\n            self.audio_buf = af.frame.data[0]\n            resampled_data_size = data_size\n\n        audio_clock0 = self.audio_clock\n        # update the audio clock with the pts\n        if not isnan(af.pts):\n            self.audio_clock = af.pts + <double>af.frame.nb_samples / af.frame.sample_rate\n        else:\n            self.audio_clock = NAN\n        self.audio_clock_serial = af.serial\n#         IF DEBUG:\n#             printf(b\"audio: delay=%0.3f clock=%0.3f clock0=%0.3f\\n\",\n#                    self.audio_clock - self.last_clock,\n#                    self.audio_clock, audio_clock0)\n#             self.last_clock = is->audio_clock;\n        if self.auddec.is_seeking() or self.viddec.is_seeking():\n            if self.audio_clock == NAN or self.audio_clock >= self.auddec.seek_req_pos:\n                if self.auddec.is_seeking():\n                    self.auddec.set_seek_pos(-1)\n            else:\n                return -1\n        return resampled_data_size\n\n    # prepare a new audio buffer\n    cdef int sdl_audio_callback(VideoState self, uint8_t *stream, int len) nogil except 1:\n        cdef int audio_size, len1\n        self.player.audio_callback_time = av_gettime_relative()\n\n        memset(stream, 0, len)\n        while len > 0:\n            if self.audio_buf_index >= self.audio_buf_size:\n                audio_size = self.audio_decode_frame()\n\n                if audio_size < 0:\n                    # if error, just output silence\n                    self.audio_buf = NULL\n                    self.audio_buf_size = SDL_AUDIO_MIN_BUFFER_SIZE // self.audio_tgt.frame_size * self.audio_tgt.frame_size\n                else:\n#                     if self.show_mode != SHOW_MODE_VIDEO:\n#                         self.update_sample_display(<int16_t *>self.audio_buf, audio_size)\n                    self.audio_buf_size = audio_size\n                self.audio_buf_index = 0\n            len1 = self.audio_buf_size - self.audio_buf_index\n            if len1 > len:\n                len1 = len\n\n            if USE_SDL2_MIXER:\n                if self.audio_buf:\n                    memcpy(stream, <uint8_t *>self.audio_buf + self.audio_buf_index, len1)\n            elif not self.player.muted and self.player.audio_volume == SDL_MIX_MAXVOLUME:\n                if self.audio_buf:\n                    memcpy(stream, <uint8_t *>self.audio_buf + self.audio_buf_index, len1)\n                else:\n                    memset(stream, 0, len1)\n            else:\n                memset(stream, 0, len1)\n                if not self.player.muted and self.audio_buf:\n                    SDL_MixAudioFormat(stream, <uint8_t *>self.audio_buf + self.audio_buf_index,\n                                       AUDIO_S16SYS, len1, self.player.audio_volume)\n\n            len -= len1\n            stream += len1\n            self.audio_buf_index += len1\n\n        self.audio_write_buf_size = self.audio_buf_size - self.audio_buf_index\n        # Let's assume the audio driver that is used by SDL has two periods.\n        if not isnan(self.audio_clock):\n            self.audclk.set_clock_at(\n                self.audio_clock - <double>(2 * self.audio_hw_buf_size + self.audio_write_buf_size) /\n                self.audio_tgt.bytes_per_sec, self.audio_clock_serial, self.player.audio_callback_time / 1000000.0)\n            self.extclk.sync_clock_to_slave(self.audclk)\n        return 0\n\n    cdef inline int open_audio_device(VideoState self, SDL_AudioSpec *wanted_spec,\n                                      SDL_AudioSpec *spec) nogil except 1:\n        cdef int error = 0\n        cdef int channels\n        global audio_count, spec_used\n\n        IF USE_SDL2_MIXER:\n            self.audio_count = -1\n            audio_mutex.lock()\n            if audio_count:\n                memcpy(spec, &spec_used, sizeof(spec_used))\n            else:\n                memcpy(spec, wanted_spec, sizeof(spec_used))\n                spec.size = spec.samples * 2 * spec.channels\n                error = Mix_OpenAudio(spec.freq, AUDIO_S16SYS, spec.channels, spec.size)\n                if not error:\n                    if not Mix_QuerySpec(&spec.freq, &spec.format, &channels):\n                        error = -1\n                    spec.channels = channels\n\n                if not error:\n                    spec.samples = FFMAX(AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(spec.freq // AUDIO_MAX_CALLBACKS_PER_SEC))\n                    spec.size = spec.samples * 2 * spec.channels\n                    memcpy(&spec_used, spec, sizeof(spec_used))\n\n            if not error:\n                self.audio_count = audio_count\n                audio_count += 1\n                if Mix_AllocateChannels(-1) < audio_count:\n                    Mix_AllocateChannels(audio_count)\n            audio_mutex.unlock()\n            if error:\n                return error\n\n            memset(self.chunk_buf, 0, sizeof(self.chunk_buf))\n            self.chunk = Mix_QuickLoad_RAW(self.chunk_buf, sizeof(self.chunk_buf) // sizeof(uint8_t))\n            if self.chunk == NULL:\n                return -1\n\n            self.audio_dev = Mix_PlayChannel(-1, self.chunk, -1)\n            if self.audio_dev == -1:\n                return -1\n\n            if not Mix_RegisterEffect(self.audio_dev, <void (*)(int, void *, int, void *) noexcept nogil>sdl_mixer_callback, NULL, self.self_id):\n                return -1\n\n        ELSE:\n            self.audio_dev = <int>SDL_OpenAudioDevice(NULL, 0, wanted_spec, spec, SDL_AUDIO_ALLOW_ANY_CHANGE)\n            error = 0 if self.audio_dev else -1\n        return error\n\n    cdef int audio_open(VideoState self, int64_t wanted_channel_layout, int wanted_nb_channels,\n                        int wanted_sample_rate, AudioParams *audio_hw_params) nogil except? 1:\n        cdef SDL_AudioSpec wanted_spec, spec\n        cdef const char *env\n        cdef int error\n        cdef int next_sample_rate_idx = next_sample_rates_len - 1\n\n        env = SDL_getenv(b\"SDL_AUDIO_CHANNELS\")\n        if env != NULL:\n            wanted_nb_channels = atoi(env)\n            wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels)\n        if ((not wanted_channel_layout) or wanted_nb_channels !=\n            av_get_channel_layout_nb_channels(wanted_channel_layout)):\n            wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels)\n            wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX\n\n        wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout)\n        wanted_spec.channels = wanted_nb_channels\n        wanted_spec.freq = wanted_sample_rate\n        if wanted_spec.freq <= 0 or wanted_spec.channels <= 0:\n            if self.player.loglevel >= AV_LOG_ERROR:\n                av_log(NULL, AV_LOG_ERROR, b\"Invalid sample rate or channel count!\\n\")\n            return -1\n\n        while next_sample_rate_idx and next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq:\n            next_sample_rate_idx -= 1\n\n        wanted_spec.format = AUDIO_S16SYS\n        wanted_spec.silence = 0\n        wanted_spec.samples = FFMAX(AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq // AUDIO_MAX_CALLBACKS_PER_SEC))\n        wanted_spec.callback = <void (*)(void *, uint8_t *, int) noexcept nogil>self.sdl_audio_callback\n        wanted_spec.userdata = self.self_id\n\n        error = self.open_audio_device(&wanted_spec, &spec)\n        while error:\n            if self.player.loglevel >= AV_LOG_WARNING:\n                av_log(NULL, AV_LOG_WARNING, b\"SDL_OpenAudio (%d channels, %d Hz): %s\\n\",\n                    wanted_spec.channels, wanted_spec.freq, SDL_GetError())\n\n            wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)]\n            if not wanted_spec.channels:\n                wanted_spec.freq = next_sample_rates[next_sample_rate_idx]\n                next_sample_rate_idx -= 1\n                wanted_spec.channels = wanted_nb_channels\n                if not wanted_spec.freq:\n                    if self.player.loglevel >= AV_LOG_ERROR:\n                        av_log(NULL, AV_LOG_ERROR,\n                           b\"No more channel combinations to try, audio open failed\\n\")\n                    return -1\n            wanted_channel_layout = av_get_default_channel_layout(wanted_spec.channels)\n\n            error = self.open_audio_device(&wanted_spec, &spec)\n\n        if spec.format != AUDIO_S16SYS:\n            if self.player.loglevel >= AV_LOG_ERROR:\n                av_log(NULL, AV_LOG_ERROR,\n                   b\"SDL advised audio format %d is not supported!\\n\", spec.format)\n            return -1\n\n        if spec.channels != wanted_spec.channels:\n            wanted_channel_layout = av_get_default_channel_layout(spec.channels)\n            if not wanted_channel_layout:\n                if self.player.loglevel >= AV_LOG_ERROR:\n                    av_log(NULL, AV_LOG_ERROR,\n                       b\"SDL advised channel count %d is not supported!\\n\", spec.channels)\n                return -1\n\n        audio_hw_params.fmt = AV_SAMPLE_FMT_S16\n        audio_hw_params.freq = spec.freq\n        audio_hw_params.channel_layout = wanted_channel_layout\n        audio_hw_params.channels =  spec.channels\n        audio_hw_params.frame_size = av_samples_get_buffer_size(\n            NULL, audio_hw_params.channels, 1, audio_hw_params.fmt, 1)\n        audio_hw_params.bytes_per_sec = av_samples_get_buffer_size(\n            NULL, audio_hw_params.channels, audio_hw_params.freq, audio_hw_params.fmt, 1)\n\n        if audio_hw_params.bytes_per_sec <= 0 or audio_hw_params.frame_size <= 0:\n            if self.player.loglevel >= AV_LOG_ERROR:\n                av_log(NULL, AV_LOG_ERROR, b\"av_samples_get_buffer_size failed\\n\")\n            return -1\n        if self.player.loglevel >= AV_LOG_DEBUG:\n            av_log(NULL, AV_LOG_DEBUG,\n               b\"openaudio with fmt=%u freq=%u channel_layout=%u channels=%hhu\\n\",\n               audio_hw_params.fmt, audio_hw_params.freq,\n               audio_hw_params.channel_layout, audio_hw_params.channels)\n\n        return spec.size\n\n    # open a given stream. Return 0 if OK\n    cdef int stream_component_open(VideoState self, int stream_index) nogil except 1:\n        cdef AVFormatContext *ic = self.ic\n        cdef AVCodecContext *avctx\n        cdef const AVCodec *codec\n        cdef const char *forced_codec_name = NULL\n        cdef AVDictionary *opts = NULL\n        cdef const AVDictionaryEntry *t = NULL\n        cdef int sample_rate, nb_channels\n        cdef int64_t channel_layout\n        cdef int ret = 0\n        cdef int stream_lowres = self.player.lowres\n        cdef AVFilterContext *sink\n        if stream_index < 0 or stream_index >= ic.nb_streams:\n            return -1\n\n        avctx = avcodec_alloc_context3(NULL)\n        if avctx == NULL:\n            return AVERROR(ENOMEM)\n\n        ret = avcodec_parameters_to_context(avctx, ic.streams[stream_index].codecpar)\n        if ret < 0:\n            avcodec_free_context(&avctx)\n            return ret\n        avctx.pkt_timebase = ic.streams[stream_index].time_base\n\n        codec = avcodec_find_decoder(avctx.codec_id)\n\n        if avctx.codec_type == AVMEDIA_TYPE_AUDIO:\n            self.last_audio_stream = stream_index\n            forced_codec_name = self.player.audio_codec_name\n        elif avctx.codec_type == AVMEDIA_TYPE_SUBTITLE:\n            self.last_subtitle_stream = stream_index\n            forced_codec_name = self.player.subtitle_codec_name\n        elif avctx.codec_type == AVMEDIA_TYPE_VIDEO:\n            self.last_video_stream = stream_index\n            forced_codec_name = self.player.video_codec_name\n\n        if forced_codec_name != NULL:\n            codec = avcodec_find_decoder_by_name(forced_codec_name)\n        if codec == NULL:\n            if forced_codec_name != NULL:\n                if self.player.loglevel >= AV_LOG_WARNING:\n                    av_log(NULL, AV_LOG_WARNING, b\"No codec could be found with name '%s'\\n\", forced_codec_name)\n            else:\n                if self.player.loglevel >= AV_LOG_WARNING:\n                    av_log(NULL, AV_LOG_WARNING, b\"No decoder could be found for codec %s\\n\", avcodec_get_name(avctx.codec_id))\n            avcodec_free_context(&avctx)\n            return AVERROR(EINVAL)\n        avctx.codec_id = codec.id\n        if stream_lowres > codec.max_lowres:\n            av_log(avctx, AV_LOG_WARNING, b\"The maximum value for lowres supported by the decoder is %d\\n\",\n                    codec.max_lowres)\n            stream_lowres = codec.max_lowres\n        avctx.lowres =  stream_lowres\n\n        if self.player.fast:\n            avctx.flags2 |= AV_CODEC_FLAG2_FAST\n\n        opts = filter_codec_opts(self.player.codec_opts, avctx.codec_id, ic,\n                                 ic.streams[stream_index], codec)\n        if av_dict_get(opts, b\"threads\", NULL, 0) == NULL:\n            av_dict_set(&opts, b\"threads\", b\"auto\", 0)\n        if stream_lowres:\n            av_dict_set_int(&opts, b\"lowres\", stream_lowres, 0)\n        if avcodec_open2(avctx, codec, &opts) < 0:\n            avcodec_free_context(&avctx)\n            av_dict_free(&opts)\n            return -1\n        t = av_dict_get(opts, b\"\", NULL, AV_DICT_IGNORE_SUFFIX)\n        if t != NULL:\n            if self.player.loglevel >= AV_LOG_ERROR:\n                av_log(NULL, AV_LOG_ERROR, b\"Option %s not found.\\n\", t.key)\n            avcodec_free_context(&avctx)\n            av_dict_free(&opts)\n            return AVERROR_OPTION_NOT_FOUND\n        self.eof = 0\n        ic.streams[stream_index].discard = AVDISCARD_DEFAULT\n        if avctx.codec_type == AVMEDIA_TYPE_AUDIO:\n            IF CONFIG_AVFILTER:\n                self.audio_filter_src.freq           = avctx.sample_rate\n                self.audio_filter_src.channels       = avctx.channels\n                self.audio_filter_src.channel_layout = get_valid_channel_layout(avctx.channel_layout, avctx.channels)\n                self.audio_filter_src.fmt            = avctx.sample_fmt\n                ret = self.configure_audio_filters(self.player.afilters, 0)\n                if ret < 0:\n                    avcodec_free_context(&avctx)\n                    av_dict_free(&opts)\n                    return ret\n                sink = self.out_audio_filter\n                sample_rate    = av_buffersink_get_sample_rate(sink)\n                nb_channels    = av_buffersink_get_channels(sink)\n                channel_layout = av_buffersink_get_channel_layout(sink)\n            ELSE:\n                sample_rate    = avctx.sample_rate\n                nb_channels    = avctx.channels\n                channel_layout = avctx.channel_layout\n\n            # prepare audio output\n            ret = self.audio_open(channel_layout, nb_channels, sample_rate, &self.audio_tgt)\n            if ret < 0:\n                avcodec_free_context(&avctx)\n                av_dict_free(&opts)\n                return ret\n            self.audio_hw_buf_size = ret\n            self.audio_src = self.audio_tgt\n            self.audio_buf_size  = 0\n            self.audio_buf_index = 0\n\n            # init averaging filter\n            self.audio_diff_avg_coef  = exp(log(0.01) / <double>AUDIO_DIFF_AVG_NB)\n            self.audio_diff_avg_count = 0\n            ''' since we do not have a precise anough audio fifo fullness,\n            we correct audio sync only if larger than this threshold '''\n            self.audio_diff_threshold = (<double>self.audio_hw_buf_size) / self.audio_tgt.bytes_per_sec\n\n            self.audio_stream = stream_index\n            self.audio_st = ic.streams[stream_index]\n\n            self.auddec.decoder_init(self.mt_gen, avctx, self.audioq, self.continue_read_thread)\n            if ((self.ic.iformat.flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) and\n                not self.ic.iformat.read_seek):\n                self.auddec.start_pts = self.audio_st.start_time\n                self.auddec.start_pts_tb = self.audio_st.time_base\n            self.auddec.decoder_start(audio_thread_enter, \"audio_decoder\", self.self_id)\n            IF USE_SDL2_MIXER:\n                Mix_Resume(self.audio_dev)\n            ELSE:\n                SDL_PauseAudioDevice(<SDL_AudioDeviceID>self.audio_dev, 0)\n        elif avctx.codec_type ==  AVMEDIA_TYPE_VIDEO:\n            with gil:\n                self.metadata['src_pix_fmt'] = <const char *>av_x_if_null(av_get_pix_fmt_name(avctx.pix_fmt), b\"none\")\n            self.video_stream = stream_index\n            self.video_st = ic.streams[stream_index]\n            self.viddec.decoder_init(self.mt_gen, avctx, self.videoq, self.continue_read_thread)\n\n            self.viddec.decoder_start(video_thread_enter, \"video_decoder\", self.self_id)\n            self.queue_attachments_req = 1\n        elif avctx.codec_type ==  AVMEDIA_TYPE_SUBTITLE:\n            self.subtitle_stream = stream_index\n            self.subtitle_st = ic.streams[stream_index]\n            self.subdec.decoder_init(self.mt_gen, avctx, self.subtitleq, self.continue_read_thread)\n            self.subdec.decoder_start(subtitle_thread_enter, \"subtitle_decoder\", self.self_id)\n        av_dict_free(&opts)\n        return 0\n\n    cdef int stream_component_close(VideoState self, int stream_index) nogil except 1:\n        cdef AVFormatContext *ic = self.ic\n        cdef AVCodecParameters *codecpar\n        global audio_count\n        if stream_index < 0 or stream_index >= ic.nb_streams:\n            return 0\n        codecpar = ic.streams[stream_index].codecpar\n\n        if codecpar.codec_type == AVMEDIA_TYPE_AUDIO:\n            self.auddec.decoder_abort(self.sampq)\n            IF USE_SDL2_MIXER:\n                Mix_UnregisterEffect(self.audio_dev, <void (*)(int, void *, int, void *) noexcept nogil>sdl_mixer_callback)\n                Mix_HaltChannel(self.audio_dev)\n                Mix_FreeChunk(self.chunk)\n                self.chunk = NULL\n\n                audio_mutex.lock()\n                if self.audio_count != -1:\n                    audio_count -= 1\n                self.audio_count = -1\n                if not audio_count:\n                    Mix_CloseAudio()\n                audio_mutex.unlock()\n            ELSE:\n                SDL_CloseAudioDevice(<SDL_AudioDeviceID>self.audio_dev)\n\n            self.auddec.decoder_destroy()\n            swr_free(&self.swr_ctx)\n            av_freep(&self.audio_buf1)\n            self.audio_buf1_size = 0\n            self.audio_buf = NULL\n        elif codecpar.codec_type == AVMEDIA_TYPE_VIDEO:\n            self.viddec.decoder_abort(self.pictq)\n            self.viddec.decoder_destroy()\n        elif codecpar.codec_type == AVMEDIA_TYPE_SUBTITLE:\n            self.subdec.decoder_abort(self.subpq)\n            self.subdec.decoder_destroy()\n\n        ic.streams[stream_index].discard = AVDISCARD_ALL\n        if codecpar.codec_type == AVMEDIA_TYPE_AUDIO:\n            self.audio_st = NULL\n            self.audio_stream = -1\n        elif codecpar.codec_type == AVMEDIA_TYPE_VIDEO:\n            self.video_st = NULL\n            self.video_stream = -1\n        elif codecpar.codec_type == AVMEDIA_TYPE_SUBTITLE:\n            self.subtitle_st = NULL\n            self.subtitle_stream = -1\n        return 0\n\n    # this thread gets the stream from the disk or the network\n    cdef int read_thread(VideoState self) nogil except 1:\n        cdef AVFormatContext *ic = NULL\n        cdef int err, i, ret\n        cdef int st_index[<int>AVMEDIA_TYPE_NB]\n        cdef AVPacket *pkt = NULL\n        cdef int64_t stream_start_time\n        cdef int pkt_in_play_range = 0\n        cdef const AVDictionaryEntry *t\n        cdef AVDictionary **opts\n        cdef int orig_nb_streams\n        cdef int scan_all_pmts_set = 0\n        cdef int64_t pkt_ts\n        cdef char err_msg[256]\n        cdef int64_t timestamp\n        cdef int temp\n        cdef int64_t seek_target, seek_min, seek_max\n        cdef int64_t temp64, temp64_2\n        cdef AVStream *st\n        cdef AVMediaType media_type\n        self.eof = 0\n        memset(st_index, -1, sizeof(st_index))\n\n        pkt = av_packet_alloc()\n        if pkt == NULL:\n            av_log(NULL, AV_LOG_FATAL, \"Could not allocate packet.\\n\")\n            return self.failed(AVERROR(ENOMEM), ic, &pkt)\n\n        ic = avformat_alloc_context()\n        if ic == NULL:\n            if self.player.loglevel >= AV_LOG_FATAL:\n                av_log(NULL, AV_LOG_FATAL, b\"Could not allocate context.\\n\");\n            return self.failed(AVERROR(ENOMEM), ic, &pkt)\n        #av_opt_set_int(ic, b\"threads\", 1, 0)\n        ic.interrupt_callback.callback = <int (*)(void *) noexcept>self.decode_interrupt_cb\n        ic.interrupt_callback.opaque = self.self_id\n\n        if not av_dict_get(self.player.format_opts, b\"scan_all_pmts\", NULL, AV_DICT_MATCH_CASE):\n            av_dict_set(&self.player.format_opts, b\"scan_all_pmts\", b\"1\", AV_DICT_DONT_OVERWRITE)\n            scan_all_pmts_set = 1\n\n        err = avformat_open_input(&ic, self.player.input_filename, self.iformat, &self.player.format_opts)\n        if err < 0:\n            if self.player.loglevel >= AV_LOG_ERROR:\n                av_log(NULL, AV_LOG_ERROR, b\"%s: %s\\n\", self.player.input_filename, fmt_err(err, err_msg, sizeof(err_msg)))\n            return self.failed(-1, ic, &pkt)\n\n        if scan_all_pmts_set:\n            av_dict_set(&self.player.format_opts, b\"scan_all_pmts\", NULL, AV_DICT_MATCH_CASE)\n        t = av_dict_get(self.player.format_opts, b\"\", NULL, AV_DICT_IGNORE_SUFFIX)\n        if t != NULL:\n            if self.player.loglevel >= AV_LOG_ERROR:\n                av_log(NULL, AV_LOG_ERROR, b\"Option %s not found.\\n\", t.key)\n            return self.failed(AVERROR_OPTION_NOT_FOUND, ic, &pkt)\n        self.ic = ic\n\n        if self.player.genpts:\n            ic.flags |= AVFMT_FLAG_GENPTS\n        av_format_inject_global_side_data(ic)\n\n        if self.player.find_stream_info:\n            opts = setup_find_stream_info_opts(ic, self.player.codec_opts)\n            orig_nb_streams = ic.nb_streams\n\n            err = avformat_find_stream_info(ic, opts)\n            for i in range(orig_nb_streams):\n                av_dict_free(&opts[i])\n            av_freep(&opts)\n\n            if err < 0:\n                if self.player.loglevel >= AV_LOG_WARNING:\n                    av_log(NULL, AV_LOG_WARNING, b\"%s: could not find codec parameters\\n\", self.player.input_filename)\n                return self.failed(-1, ic, &pkt)\n\n        if ic.pb != NULL:\n            ic.pb.eof_reached = 0 # FIXME hack, ffplay maybe should not use avio_feof() to test for the end\n\n        if self.player.seek_by_bytes < 0:\n            self.player.seek_by_bytes = (ic.iformat.flags & AVFMT_NO_BYTE_SEEK) == 0 \\\n                and (ic.iformat.flags & AVFMT_TS_DISCONT) != 0 \\\n                and strcmp(b\"ogg\", ic.iformat.name) != 0\n\n        self.max_frame_duration = 10.0 if ic.iformat.flags & AVFMT_TS_DISCONT else 3600.0\n\n        t = av_dict_get(ic.metadata, b\"title\", NULL, 0)\n        if t != NULL:\n            with gil:\n                self.metadata['title'] = str(t.value)\n\n        with gil:\n            self.metadata['duration'] = (ic.duration / <double>AV_TIME_BASE) if ic.duration >= 0 else 0.\n\n        # if seeking requested, we execute it\n        if self.player.start_time != AV_NOPTS_VALUE:\n            timestamp = self.player.start_time\n            # add the stream start time\n            if ic.start_time != AV_NOPTS_VALUE:\n                timestamp += ic.start_time\n            ret = avformat_seek_file(ic, -1, INT64_MIN, timestamp, INT64_MAX, 0)\n            if ret < 0:\n                if self.player.loglevel >= AV_LOG_WARNING:\n                    av_log(NULL, AV_LOG_WARNING, b\"%s: could not seek to position %0.3f\\n\",\n                       self.player.input_filename, <double>timestamp / <double>AV_TIME_BASE)\n\n        self.realtime = is_realtime(ic)\n        if self.player.show_status:\n            av_dump_format(ic, 0, self.player.input_filename, 0)\n        for i in range(ic.nb_streams):\n            ic.streams[i].discard = AVDISCARD_ALL\n\n        for i in range(ic.nb_streams):\n            st = ic.streams[i]\n            media_type = st.codecpar.codec_type\n            st.discard = AVDISCARD_ALL\n            if <int>media_type >= 0 and self.player.wanted_stream_spec[<int>media_type] != NULL and st_index[<int>media_type] == -1:\n                if avformat_match_stream_specifier(ic, st, self.player.wanted_stream_spec[<int>media_type]) > 0:\n                    st_index[<int>media_type] = i\n\n        for i in range(AVMEDIA_TYPE_NB):\n            if self.player.wanted_stream_spec[i] != NULL and st_index[i] == -1:\n                if self.player.loglevel >= AV_LOG_ERROR:\n                    av_log(NULL, AV_LOG_ERROR, b\"Stream specifier %s does not match any %s stream\\n\",\n                       self.player.wanted_stream_spec[i], av_get_media_type_string(<AVMediaType>i))\n                st_index[i] = INT_MAX\n\n        if not self.player.video_disable:\n            st_index[<int>AVMEDIA_TYPE_VIDEO] = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,\\\n            st_index[<int>AVMEDIA_TYPE_VIDEO], -1, NULL, 0)\n        if not self.player.audio_disable:\n            st_index[<int>AVMEDIA_TYPE_AUDIO] = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,\\\n            st_index[<int>AVMEDIA_TYPE_AUDIO], st_index[<int>AVMEDIA_TYPE_VIDEO], NULL, 0)\n        if st_index[<int>AVMEDIA_TYPE_AUDIO] >= 0:\n            temp = st_index[<int>AVMEDIA_TYPE_AUDIO]\n        else:\n            temp = st_index[<int>AVMEDIA_TYPE_VIDEO]\n        if (not self.player.video_disable) and not self.player.subtitle_disable:\n            st_index[<int>AVMEDIA_TYPE_SUBTITLE] = av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,\\\n            st_index[<int>AVMEDIA_TYPE_SUBTITLE], temp, NULL, 0)\n\n        # open the streams\n        if st_index[<int>AVMEDIA_TYPE_AUDIO] >= 0:\n            self.stream_component_open(st_index[<int>AVMEDIA_TYPE_AUDIO])\n\n        ret = -1\n        if st_index[<int>AVMEDIA_TYPE_VIDEO] >= 0:\n            ret = self.stream_component_open(st_index[<int>AVMEDIA_TYPE_VIDEO])\n#         if self.show_mode == SHOW_MODE_NONE:\n#             if ret >= 0:\n#                 self.show_mode = SHOW_MODE_VIDEO\n#             else:\n#                 self.show_mode = SHOW_MODE_RDFT\n\n        if st_index[<int>AVMEDIA_TYPE_SUBTITLE] >= 0:\n            self.stream_component_open(st_index[<int>AVMEDIA_TYPE_SUBTITLE])\n\n        if self.video_stream < 0 and self.audio_stream < 0:\n            if self.player.loglevel >= AV_LOG_FATAL:\n                av_log(NULL, AV_LOG_FATAL, b\"Failed to open file '%s' or configure filtergraph\\n\",\n                   self.player.input_filename)\n            return self.failed(-1, ic, &pkt)\n\n        if self.player.infinite_buffer < 0 and self.realtime:\n            self.player.infinite_buffer = 1\n\n        while 1:\n            if self.abort_request:\n                break\n            if self.paused != self.last_paused:\n                self.last_paused = self.paused\n                if self.paused:\n                    self.read_pause_return = av_read_pause(ic)\n                else:\n                    av_read_play(ic)\n            IF CONFIG_RTSP_DEMUXER or CONFIG_MMSH_PROTOCOL:\n                if self.paused and ((not strcmp(ic.iformat.name, b\"rtsp\")) or\\\n                ic.pb != NULL and not strncmp(self.player.input_filename, b\"mmsh:\", 5)):\n                    # wait 10 ms to avoid trying to get another packet\n                    # XXX: horrible\n                    self.pause_cond.lock()\n                    self.pause_cond.cond_wait()\n                    self.pause_cond.unlock()\n                    #self.mt_gen.delay(10)\n                    continue\n            if self.seek_req:\n                self.reached_eof = 0\n                seek_target = self.seek_pos\n                if self.seek_rel > 0:\n                    seek_min = seek_target - self.seek_rel + 2\n                else:\n                    seek_min = INT64_MIN\n                if self.seek_rel < 0:\n                    seek_max = seek_target - self.seek_rel - 2\n                else:\n                    seek_max = INT64_MAX\n                ''' FIXME the +-2 is due to rounding being not done in the correct\n                direction in generation of the seek_pos/seek_rel variables'''\n\n                ret = avformat_seek_file(self.ic, -1, seek_min, seek_target,\n                                         seek_max, self.seek_flags)\n                if ret < 0:\n                    if self.player.loglevel >= AV_LOG_ERROR:\n                        av_log(NULL, AV_LOG_ERROR, b\"%s: error while seeking\\n\",\n                           self.ic.url)\n                else:\n                    if self.audio_stream >= 0:\n                        self.audioq.packet_queue_flush()\n                    if self.subtitle_stream >= 0:\n                        self.subtitleq.packet_queue_flush()\n                    if self.video_stream >= 0:\n                        self.videoq.packet_queue_flush()\n                    if self.seek_flags & AVSEEK_FLAG_BYTE:\n                        self.extclk.set_clock(NAN, 0)\n                    else:\n                        self.extclk.set_clock(seek_target / <double>AV_TIME_BASE, 0)\n                self.seek_req = 0\n                self.queue_attachments_req = 1\n                self.eof = 0\n\n            if self.queue_attachments_req:\n                if self.video_st != NULL and self.video_st.disposition & AV_DISPOSITION_ATTACHED_PIC:\n                    ret = av_packet_ref(pkt, &self.video_st.attached_pic)\n                    if ret < 0:\n                        if self.player.loglevel >= AV_LOG_ERROR:\n                            av_log(NULL, AV_LOG_ERROR, b\"Failed to copy packet%s\\n\", fmt_err(ret, err_msg, sizeof(err_msg)))\n                        return self.failed(ret, ic, &pkt)\n                    self.videoq.packet_queue_put(pkt)\n                    self.videoq.packet_queue_put_nullpacket(pkt, self.video_stream)\n                self.queue_attachments_req = 0\n            # if the queue are full, no need to read more\n            if self.player.infinite_buffer < 1 and \\\n                (self.audioq.size + self.videoq.size + self.subtitleq.size > MAX_QUEUE_SIZE or\n                (self.stream_has_enough_packets(self.audio_st, self.audio_stream, self.audioq) and\n                self.stream_has_enough_packets(self.video_st, self.video_stream, self.videoq) and\n                self.stream_has_enough_packets(self.subtitle_st, self.subtitle_stream, self.subtitleq))):\n                # wait 10 ms\n                self.continue_read_thread.lock()\n                self.continue_read_thread.cond_wait_timeout(10)\n                self.continue_read_thread.unlock()\n                continue\n\n            if (not self.paused) and (\n                self.audio_st == NULL or (self.auddec.finished == self.audioq.serial and\n                                        self.sampq.frame_queue_nb_remaining() == 0)) and (\n                self.video_st == NULL or (self.viddec.finished == self.videoq.serial and\n                                          self.pictq.frame_queue_nb_remaining() == 0)):\n                self.auddec.set_seek_pos(-1)\n                self.viddec.set_seek_pos(-1)\n                if self.player.loop != 1:\n                    self.request_thread_s(b'eof', b'')\n                    if self.player.start_time != AV_NOPTS_VALUE:\n                        temp64 = self.player.start_time\n                    else:\n                        temp64 = 0\n                    if not self.player.loop:\n                        self.stream_seek(temp64, 0, 0, 0)\n                    else:\n                        self.player.loop = self.player.loop - 1\n                        if self.player.loop:\n                            self.stream_seek(temp64, 0, 0, 0)\n                elif self.player.autoexit:\n                    if self.player.loglevel >= AV_LOG_INFO:\n                        av_log(NULL, AV_LOG_INFO, b\"Reached eof\\n\")\n                    self.request_thread_s(b'eof', b'')\n                    return self.failed(0, ic, &pkt)\n                else:\n                    if not self.reached_eof:\n                        self.reached_eof = 1\n                        self.request_thread_s(b'eof', b'')\n\n            ret = av_read_frame(ic, pkt)\n            if ret < 0:\n                if (ret == AVERROR_EOF or avio_feof(ic.pb)) and not self.eof:\n                    self.auddec.set_seek_pos(-1)\n                    self.viddec.set_seek_pos(-1)\n                    if self.video_stream >= 0:\n                        self.videoq.packet_queue_put_nullpacket(pkt, self.video_stream)\n                    if self.audio_stream >= 0:\n                        self.audioq.packet_queue_put_nullpacket(pkt, self.audio_stream)\n                    if self.subtitle_stream >= 0:\n                        self.subtitleq.packet_queue_put_nullpacket(pkt, self.subtitle_stream)\n                    self.eof = 1\n                if ic.pb != NULL and ic.pb.error:\n                    if self.player.autoexit:\n                        if self.player.loglevel >= AV_LOG_INFO:\n                            av_log(NULL, AV_LOG_INFO, b\"Reached eof\\n\")\n                        self.request_thread_s(b'eof', b'')\n                    break\n                self.continue_read_thread.lock()\n                self.continue_read_thread.cond_wait_timeout(10)\n                self.continue_read_thread.unlock()\n                continue\n            else:\n                self.eof = 0\n\n            # check if packet is in play range specified by user, then queue, otherwise discard\n            stream_start_time = ic.streams[pkt.stream_index].start_time\n            pkt_ts = pkt.dts if pkt.pts == AV_NOPTS_VALUE else pkt.pts\n            if stream_start_time != AV_NOPTS_VALUE:\n                temp64 = stream_start_time\n            else:\n                temp64 = 0\n            if self.player.start_time != AV_NOPTS_VALUE:\n                temp64_2 = self.player.start_time\n            else:\n                temp64_2 = 0\n\n            pkt_in_play_range = self.player.duration == AV_NOPTS_VALUE or \\\n                (pkt_ts - temp64) * av_q2d(ic.streams[pkt.stream_index].time_base) - \\\n                <double>temp64_2 / 1000000.0 <= (<double>self.player.duration / 1000000.0)\n            if pkt.stream_index == self.audio_stream and pkt_in_play_range:\n                self.audioq.packet_queue_put(pkt)\n            elif (pkt.stream_index == self.video_stream and pkt_in_play_range\n                  and not (self.video_st.disposition & AV_DISPOSITION_ATTACHED_PIC)):\n                self.videoq.packet_queue_put(pkt)\n            elif pkt.stream_index == self.subtitle_stream and pkt_in_play_range:\n                self.subtitleq.packet_queue_put(pkt)\n            else:\n                av_packet_unref(pkt)\n\n        ret = 0\n        if self.player.loglevel >= AV_LOG_INFO:\n            av_log(NULL, AV_LOG_INFO, b\"Exiting read thread\\n\")\n        return self.failed(ret, ic, &pkt)\n\n    cdef int stream_has_enough_packets(self, AVStream *st, int stream_id, FFPacketQueue queue) nogil:\n        return (\n            stream_id < 0 or\n            queue.abort_request or\n            (st.disposition & AV_DISPOSITION_ATTACHED_PIC) or\n            queue.nb_packets > MIN_FRAMES and\n            (not queue.duration or av_q2d(st.time_base) * queue.duration > 1.0)\n        )\n\n    cdef inline int failed(VideoState self, int ret, AVFormatContext *ic, AVPacket **pkt) nogil except 1:\n        cdef char err_msg[256]\n        if ic != NULL and self.ic == NULL:\n            avformat_close_input(&ic)\n\n        if pkt != NULL:\n            av_packet_free(pkt)\n\n        if ret and not self.abort_request:\n            if ret != -1:\n                self.request_thread_s(b'read:error', fmt_err(ret, err_msg, sizeof(err_msg)))\n            else:\n                self.request_thread_s(b'read:error', b'')\n        else:\n            self.request_thread_s(b'read:exit', b'Done')\n        return 0\n\n    cdef int stream_select_program(VideoState self,\n                                   int requested_program) nogil except 1:\n        cdef unsigned int i\n        cdef AVProgram *p\n        cdef AVProgram *selected_program = NULL\n        cdef AVStream *st\n        cdef unsigned int nb_streams\n        cdef unsigned int stream_index\n        cdef int video_stream_index = -1\n        cdef int audio_stream_index = -1\n        cdef int subtitle_stream_index = -1\n        cdef int program = -1\n        cdef unsigned int nb_programs = self.ic.nb_programs\n\n        i = 0\n        while i < nb_programs:\n            p = self.ic.programs[i]\n\n            if p.id == requested_program:\n                selected_program = p\n                break\n\n            i += 1\n\n        if selected_program == NULL:\n            return -1\n\n        nb_streams = selected_program.nb_stream_indexes\n\n        i = 0\n        while i < nb_streams:\n            stream_index = selected_program.stream_index[i]\n            st = self.ic.streams[stream_index]\n\n            if st.codecpar.codec_type == AVMEDIA_TYPE_VIDEO:\n                if video_stream_index == -1:\n                    video_stream_index = <int>stream_index\n            elif st.codecpar.codec_type == AVMEDIA_TYPE_AUDIO:\n                if audio_stream_index == -1:\n                    audio_stream_index = <int>stream_index\n            elif st.codecpar.codec_type == AVMEDIA_TYPE_SUBTITLE:\n                if subtitle_stream_index == -1:\n                    subtitle_stream_index = <int>stream_index\n\n            i += 1\n\n        self.stream_component_close(self.video_stream)\n        self.stream_component_close(self.audio_stream)\n        self.stream_component_close(self.subtitle_stream)\n\n        if video_stream_index != -1:\n            self.stream_component_open(video_stream_index)\n\n        if audio_stream_index != -1:\n            self.stream_component_open(audio_stream_index)\n\n        if subtitle_stream_index != -1:\n            self.stream_component_open(subtitle_stream_index)\n\n        return 0\n\n    cdef int stream_select_channel(VideoState self, int codec_type,\n                                  unsigned int requested_stream) nogil except 1:\n        cdef int old_index\n        cdef AVStream *st\n        cdef unsigned int nb_streams = self.ic.nb_streams\n\n        if codec_type == AVMEDIA_TYPE_VIDEO:\n            old_index = self.video_stream\n        elif codec_type == AVMEDIA_TYPE_AUDIO:\n            old_index = self.audio_stream\n        else:\n            old_index = self.subtitle_stream\n\n        if requested_stream >= nb_streams:\n            return -1\n\n        st = self.ic.streams[requested_stream]\n\n        if st.codecpar.codec_type != codec_type:\n            return -1\n\n        if codec_type == AVMEDIA_TYPE_AUDIO:\n            if st.codecpar.sample_rate == 0 or st.codecpar.channels == 0:\n                av_log(NULL, AV_LOG_ERROR, b'Invalid audio stream #%d\\n', requested_stream)\n                return -1\n\n        if self.player.loglevel >= AV_LOG_INFO:\n            av_log(NULL, AV_LOG_INFO, b'Switch %s stream from #%d to #%d\\n',\n                    av_get_media_type_string(<AVMediaType>codec_type), old_index, requested_stream)\n\n        self.stream_component_close(old_index)\n        self.stream_component_open(<int>requested_stream)\n\n        return 0\n\n    cdef int stream_cycle_channel(VideoState self, int codec_type) nogil except 1:\n        cdef AVFormatContext *ic = self.ic\n        cdef int start_index, stream_index\n        cdef int old_index, was_closed = 0\n        cdef AVStream *st\n        cdef AVProgram *p = NULL\n        cdef int nb_streams = self.ic.nb_streams\n        cdef double pos\n        cdef int sync_type = self.get_master_sync_type()\n\n        if codec_type == AVMEDIA_TYPE_VIDEO:\n            start_index = self.last_video_stream\n            old_index = self.video_stream\n        elif codec_type == AVMEDIA_TYPE_AUDIO:\n            start_index = self.last_audio_stream\n            old_index = self.audio_stream\n        else:\n            start_index = self.last_subtitle_stream\n            old_index = self.subtitle_stream\n        was_closed = old_index == -1\n        stream_index = start_index\n        if codec_type != AVMEDIA_TYPE_VIDEO and self.video_stream != -1:\n            p = av_find_program_from_stream(ic, NULL, self.video_stream)\n            if p != NULL:\n                nb_streams = p.nb_stream_indexes\n                start_index = 0\n                while start_index < nb_streams:\n                    if p.stream_index[start_index] == stream_index:\n                        break\n                    start_index += 1\n                if start_index == nb_streams:\n                    start_index = -1\n                stream_index = start_index\n        while 1:\n            if not was_closed:\n                stream_index += 1\n            if stream_index >= nb_streams:\n                if codec_type == AVMEDIA_TYPE_SUBTITLE:\n                    stream_index = -1\n                    self.last_subtitle_stream = -1\n                    break\n                if start_index == -1:\n                    return 0\n                stream_index = 0\n            if stream_index == start_index and not was_closed:\n                return 0\n            st = ic.streams[stream_index]\n            if p != NULL:\n                st = self.ic.streams[p.stream_index[stream_index]]\n            else:\n                st = self.ic.streams[stream_index]\n            if st.codecpar.codec_type == codec_type:\n                # check that parameters are OK\n                if codec_type == AVMEDIA_TYPE_AUDIO:\n                    if st.codecpar.sample_rate != 0 and st.codecpar.channels != 0:\n                        break\n                elif codec_type == AVMEDIA_TYPE_VIDEO or codec_type == AVMEDIA_TYPE_SUBTITLE:\n                    break\n\n        if p != NULL and stream_index != -1:\n            stream_index = p.stream_index[stream_index]\n        if self.player.loglevel >= AV_LOG_INFO:\n            av_log(NULL, AV_LOG_INFO, b'Switch %s stream from #%d to #%d\\n',\n            av_get_media_type_string(<AVMediaType>codec_type), old_index, stream_index)\n        self.stream_component_close(old_index)\n        self.stream_component_open(stream_index)\n\n        if was_closed:\n            if (sync_type == AV_SYNC_VIDEO_MASTER and\n                codec_type != AVMEDIA_TYPE_VIDEO and\n                self.video_stream != -1):\n                pos = self.vidclk.get_clock()\n            elif (sync_type == AV_SYNC_AUDIO_MASTER and\n                codec_type != AVMEDIA_TYPE_AUDIO and\n                self.audio_stream != -1):\n                pos = self.audclk.get_clock()\n            else:\n                pos = self.extclk.get_clock()\n            if isnan(pos):\n                pos = <double>self.seek_pos / <double>AV_TIME_BASE\n            if self.ic.start_time != AV_NOPTS_VALUE and pos < self.ic.start_time / <double>AV_TIME_BASE:\n                pos = self.ic.start_time / <double>AV_TIME_BASE\n            self.stream_seek(<int64_t>(pos * AV_TIME_BASE), 0, 0, 1)\n        return 0\n"
  },
  {
    "path": "ffpyplayer/player/decoder.pxd",
    "content": "\ninclude '../includes/ffmpeg.pxi'\n\nfrom ffpyplayer.threading cimport MTGenerator, MTCond, MTMutex, MTThread\nfrom ffpyplayer.player.queue cimport FFPacketQueue\nfrom ffpyplayer.player.frame_queue cimport FrameQueue\n\n\ncdef class Decoder(object):\n    cdef:\n        AVPacket *pkt\n        FFPacketQueue queue\n        AVCodecContext *avctx\n        int pkt_serial\n        int finished\n        int packet_pending\n        MTCond empty_queue_cond\n        int64_t start_pts\n        AVRational start_pts_tb\n        int64_t next_pts\n        AVRational next_pts_tb\n        MTThread decoder_tid\n\n        double seek_req_pos\n        int seeking\n        MTGenerator mt_gen\n\n    cdef int decoder_init(self, MTGenerator mt_gen, AVCodecContext *avctx, FFPacketQueue queue,\n                           MTCond empty_queue_cond) nogil except 1\n    cdef void decoder_destroy(self) nogil\n    cdef void set_seek_pos(self, double seek_req_pos) nogil\n    cdef int is_seeking(self) nogil\n    cdef int decoder_abort(self, FrameQueue fq) nogil except 1\n    cdef int decoder_start(self, int_void_func func, const char *thread_name, void *arg) nogil except 1\n    cdef int decoder_decode_frame(self, AVFrame *frame, AVSubtitle *sub, int decoder_reorder_pts) nogil except? 2\n"
  },
  {
    "path": "ffpyplayer/player/decoder.pyx",
    "content": "\n__all__ = ('Decoder', )\n\ninclude '../includes/ff_consts.pxi'\n\ncdef extern from \"string.h\" nogil:\n    void * memset(void *, int, size_t)\n\ncdef extern from \"errno.h\" nogil:\n    int ENOSYS\n    int ENOMEM\n    int EAGAIN\n\n\ncdef class Decoder(object):\n\n    def __cinit__(Decoder self):\n        self.avctx = NULL\n        self.pkt = NULL\n\n    cdef int decoder_init(\n            self, MTGenerator mt_gen, AVCodecContext *avctx, FFPacketQueue queue,\n            MTCond empty_queue_cond) nogil except 1:\n        self.pkt = av_packet_alloc()\n\n        with gil:\n            self.queue = queue\n            self.empty_queue_cond = empty_queue_cond\n            self.mt_gen = mt_gen\n            if self.pkt == NULL:\n                raise MemoryError\n\n        self.avctx = avctx\n        self.packet_pending = self.finished = 0\n        self.seeking = self.start_pts = self.next_pts = 0\n        self.seek_req_pos = -1\n        self.start_pts = AV_NOPTS_VALUE\n        self.pkt_serial = -1\n        memset(&self.start_pts_tb, 0, sizeof(self.start_pts_tb))\n        memset(&self.next_pts_tb, 0, sizeof(self.next_pts_tb))\n        return 0\n\n    cdef void decoder_destroy(self) nogil:\n        av_packet_free(&self.pkt)\n        avcodec_free_context(&self.avctx)\n\n    cdef void set_seek_pos(self, double seek_req_pos) nogil:\n        self.seek_req_pos = seek_req_pos\n        if seek_req_pos == -1:\n            self.seeking = 0\n\n    cdef int is_seeking(self) nogil:\n        return self.seeking and self.seek_req_pos != -1\n\n    cdef int decoder_abort(self, FrameQueue fq) nogil except 1:\n        self.queue.packet_queue_abort()\n        fq.frame_queue_signal()\n        self.decoder_tid.wait_thread(NULL)\n        with gil:\n            self.decoder_tid = None\n        self.queue.packet_queue_flush()\n        return 0\n\n    cdef int decoder_start(self, int_void_func func, const char *thread_name, void *arg) nogil except 1:\n        self.queue.packet_queue_start()\n        with gil:\n            self.decoder_tid = MTThread(self.mt_gen.mt_src)\n            self.decoder_tid.create_thread(func, thread_name, arg)\n        return 0\n\n    cdef int decoder_decode_frame(self, AVFrame *frame, AVSubtitle *sub, int decoder_reorder_pts) nogil except? 2:\n        cdef int ret = AVERROR(EAGAIN)\n        cdef int got_frame\n        cdef AVRational tb\n        cdef int old_serial\n\n        while True:\n            if self.queue.serial == self.pkt_serial:\n                while True:\n                    if self.queue.abort_request:\n                        return -1\n\n                    if self.avctx.codec_type == AVMEDIA_TYPE_VIDEO:\n                        ret = avcodec_receive_frame(self.avctx, frame)\n                        if ret >= 0:\n                            if decoder_reorder_pts == -1:\n                                frame.pts = frame.best_effort_timestamp\n                            elif not decoder_reorder_pts:\n                                frame.pts = frame.pkt_dts\n\n                    elif self.avctx.codec_type == AVMEDIA_TYPE_AUDIO:\n                        ret = avcodec_receive_frame(self.avctx, frame)\n                        if ret >= 0:\n                            tb.num = 1\n                            tb.den = frame.sample_rate\n                            if frame.pts != AV_NOPTS_VALUE:\n                                frame.pts = av_rescale_q(frame.pts, self.avctx.pkt_timebase, tb)\n                            elif self.next_pts != AV_NOPTS_VALUE:\n                                frame.pts = av_rescale_q(self.next_pts, self.next_pts_tb, tb)\n                            if frame.pts != AV_NOPTS_VALUE:\n                                self.next_pts = frame.pts + frame.nb_samples\n                                self.next_pts_tb = tb\n\n                    if ret == AVERROR_EOF:\n                        self.finished = self.pkt_serial\n                        avcodec_flush_buffers(self.avctx)\n                        return 0\n                    if ret >= 0:\n                        return 1\n                    if ret == AVERROR(EAGAIN):\n                        break\n\n            while True:\n                if not self.queue.nb_packets:\n                    self.empty_queue_cond.lock()\n                    self.empty_queue_cond.cond_signal()\n                    self.empty_queue_cond.unlock()\n\n                if self.packet_pending:\n                    self.packet_pending = 0\n                else:\n                    old_serial = self.pkt_serial\n                    if self.queue.packet_queue_get(self.pkt, 1, &self.pkt_serial) < 0:\n                        return -1\n\n                    if old_serial != self.pkt_serial:\n                        avcodec_flush_buffers(self.avctx)\n                        self.finished = 0\n                        self.seeking = self.seek_req_pos != -1\n                        self.next_pts = self.start_pts\n                        self.next_pts_tb = self.start_pts_tb\n\n                if self.queue.serial == self.pkt_serial:\n                    break\n                av_packet_unref(self.pkt)\n\n            if self.avctx.codec_type == AVMEDIA_TYPE_SUBTITLE:\n                got_frame = 0\n                ret = avcodec_decode_subtitle2(self.avctx, sub, &got_frame, self.pkt)\n                if ret < 0:\n                    ret = AVERROR(EAGAIN)\n                else:\n                    if got_frame and self.pkt.data == NULL:\n                       self.packet_pending = 1\n                    if got_frame:\n                        ret = 0\n                    else:\n                        ret = AVERROR(EAGAIN) if self.pkt.data != NULL else AVERROR_EOF\n                av_packet_unref(self.pkt)\n            else:\n                if avcodec_send_packet(self.avctx, self.pkt) == AVERROR(EAGAIN):\n                    av_log(self.avctx, AV_LOG_ERROR, \"Receive_frame and send_packet both returned EAGAIN, which is an API violation.\\n\")\n                    self.packet_pending = 1\n                else:\n                    av_packet_unref(self.pkt)\n"
  },
  {
    "path": "ffpyplayer/player/frame_queue.pxd",
    "content": "\ninclude '../includes/ffmpeg.pxi'\n\nfrom ffpyplayer.threading cimport MTGenerator, MTCond, MTMutex\nfrom ffpyplayer.player.queue cimport FFPacketQueue\nfrom ffpyplayer.player.core cimport VideoSettings\n\ncdef struct Frame:\n    AVFrame *frame\n    int need_conversion\n    AVSubtitle sub\n    int serial\n    double pts  # presentation timestamp for the frame\n    double duration  # estimated duration of the frame\n    int64_t pos  # byte position of the frame in the input file\n    SDL_Overlay *bmp\n    int allocated\n    int reallocate\n    int width\n    int height\n    AVRational sar\n    AVPixelFormat pix_fmt\n\n\ncdef class FrameQueue(object):\n    cdef:\n        MTCond cond\n        FFPacketQueue pktq\n        Frame queue[FRAME_QUEUE_SIZE]\n        int rindex\n        int windex\n        int size\n        int max_size\n        int keep_last\n        int rindex_shown\n\n        MTMutex alloc_mutex\n        int requested_alloc\n\n    cdef void frame_queue_unref_item(self, Frame *vp) nogil\n    cdef int frame_queue_signal(self) nogil except 1\n    cdef int is_empty(self) nogil\n    cdef Frame *frame_queue_peek(self) nogil\n    cdef Frame *frame_queue_peek_next(self) nogil\n    cdef Frame *frame_queue_peek_last(self) nogil\n    cdef Frame *frame_queue_peek_writable(self) nogil\n    cdef Frame *frame_queue_peek_readable(self) nogil\n    cdef int frame_queue_push(self) nogil except 1\n    cdef int frame_queue_next(self) nogil except 1\n    cdef int frame_queue_prev(self) nogil\n    cdef int frame_queue_nb_remaining(self) nogil\n    cdef int64_t frame_queue_last_pos(self) nogil\n    cdef int copy_picture(self, Frame *vp, AVFrame *src_frame,\n                          VideoSettings *player) nogil except 1\n    cdef int peep_alloc(self) nogil\n    cdef int queue_picture(\n        self, AVFrame *src_frame, double pts, double duration, int64_t pos,\n        int serial, AVPixelFormat out_fmt, int *abort_request,\n        VideoSettings *player) nogil except 1\n    cdef int alloc_picture(self) nogil except 1\n    cdef int copy_picture(self, Frame *vp, AVFrame *src_frame,\n                           VideoSettings *player) nogil except 1\n"
  },
  {
    "path": "ffpyplayer/player/frame_queue.pyx",
    "content": "\n__all__ = ('FrameQueue', )\n\ninclude '../includes/ff_consts.pxi'\ninclude \"../includes/inline_funcs.pxi\"\n\ncdef extern from \"string.h\" nogil:\n    void * memset(void *, int, size_t)\n\ncdef void raise_py_exception(msg) nogil except *:\n    with gil:\n        raise Exception(tcode(msg))\n\n\ncdef class FrameQueue(object):\n\n    def __cinit__(FrameQueue self, MTGenerator mt_gen, FFPacketQueue pktq, int max_size, int keep_last):\n        self.cond = MTCond.__new__(MTCond, mt_gen.mt_src)\n        self.alloc_mutex = MTMutex.__new__(MTMutex, mt_gen.mt_src)\n        self.max_size = FFMIN(max_size, FRAME_QUEUE_SIZE)\n        self.pktq = pktq\n        cdef int i\n\n        with nogil:\n            self.requested_alloc = 0\n            memset(self.queue, 0, sizeof(self.queue))\n            self.keep_last = not not keep_last\n\n            for i in range(self.max_size):\n                self.queue[i].pix_fmt = <AVPixelFormat>-1\n                self.queue[i].frame = av_frame_alloc()\n                if self.queue[i].frame == NULL:\n                    with gil:\n                        raise_py_exception(b'Could not allocate avframe buffer')\n\n    def __dealloc__(self):\n        cdef int i\n        cdef Frame *vp\n\n        with nogil:\n            for i in range(self.max_size):\n                vp = &self.queue[i]\n                self.frame_queue_unref_item(vp)\n                if vp.need_conversion:\n                    av_freep(&vp.frame.data[0])\n                av_frame_free(&vp.frame)\n\n    cdef void frame_queue_unref_item(self, Frame *vp) nogil:\n        av_frame_unref(vp.frame)\n        avsubtitle_free(&vp.sub)\n\n    cdef int frame_queue_signal(self) nogil except 1:\n        self.cond.lock()\n        self.cond.cond_signal()\n        self.cond.unlock()\n        return 0\n\n    cdef int is_empty(self) nogil:\n        return self.size - self.rindex_shown <= 0\n\n    cdef Frame *frame_queue_peek(self) nogil:\n        return &self.queue[(self.rindex + self.rindex_shown) % self.max_size]\n\n    cdef Frame *frame_queue_peek_next(self) nogil:\n        return &self.queue[(self.rindex + self.rindex_shown + 1) % self.max_size]\n\n    cdef Frame *frame_queue_peek_last(self) nogil:\n        return &self.queue[self.rindex]\n\n    cdef Frame *frame_queue_peek_writable(self) nogil:\n        # wait until we have space to put a new frame\n        self.cond.lock()\n        while self.size >= self.max_size and not self.pktq.abort_request:\n            self.cond.cond_wait()\n        self.cond.unlock()\n\n        if self.pktq.abort_request:\n            return NULL\n\n        return &self.queue[self.windex]\n\n    cdef Frame *frame_queue_peek_readable(self) nogil:\n        # wait until we have a readable a new frame\n        self.cond.lock()\n        while self.size - self.rindex_shown <= 0 and not self.pktq.abort_request:\n            self.cond.cond_wait()\n        self.cond.unlock()\n\n        if self.pktq.abort_request:\n            return NULL\n\n        return &self.queue[(self.rindex + self.rindex_shown) % self.max_size]\n\n    cdef int frame_queue_push(self) nogil except 1:\n        self.windex += 1\n        if self.windex == self.max_size:\n            self.windex = 0\n\n        self.cond.lock()\n        self.size += 1\n        self.cond.cond_signal()\n        self.cond.unlock()\n        return 0\n\n    cdef int frame_queue_next(self) nogil except 1:\n        if self.keep_last and not self.rindex_shown:\n            self.rindex_shown = 1\n            return 0\n\n        self.frame_queue_unref_item(&self.queue[self.rindex])\n        self.rindex += 1\n        if self.rindex == self.max_size:\n            self.rindex = 0\n\n        self.cond.lock()\n        self.size -= 1\n        self.cond.cond_signal()\n        self.cond.unlock()\n        return 0\n\n    cdef int frame_queue_prev(self) nogil:\n        # TODO: https://github.com/FFmpeg/FFmpeg/commit/37d201aad9f7e7f233955345aee1198421a68f5e\n        # jump back to the previous frame if available by resetting rindex_shown\n        cdef int ret = self.rindex_shown\n        self.rindex_shown = 0\n        return ret\n\n    cdef int frame_queue_nb_remaining(self) nogil:\n        # return the number of undisplayed frames in the queue\n        return self.size - self.rindex_shown\n\n    cdef int64_t frame_queue_last_pos(self) nogil:\n        cdef Frame *fp = &self.queue[self.rindex]\n        if self.rindex_shown and fp.serial == self.pktq.serial:\n            return fp.pos\n        else:\n            return -1\n\n    cdef int copy_picture(self, Frame *vp, AVFrame *src_frame,\n                           VideoSettings *player) nogil except 1:\n        cdef const AVDictionaryEntry *e\n        cdef const AVClass *cls\n        cdef const AVOption *o\n        cdef int ret\n\n        if not vp.need_conversion:\n            av_frame_unref(vp.frame)\n            av_frame_move_ref(vp.frame, src_frame)\n        else:\n            e = av_dict_get(player.sws_dict, b\"sws_flags\", NULL, 0)\n            if e != NULL:\n                cls = sws_get_class()\n                o = av_opt_find(&cls, b\"sws_flags\", NULL, 0,\n                                                   AV_OPT_SEARCH_FAKE_OBJ);\n                ret = av_opt_eval_flags(&cls, o, e.value, <int *>&player.sws_flags)\n                if ret < 0:\n                    raise_py_exception(b'Could not av_opt_eval_flags')\n\n            player.img_convert_ctx = sws_getCachedContext(player.img_convert_ctx,\\\n            vp.width, vp.height, <AVPixelFormat>src_frame.format, vp.width, vp.height,\\\n            vp.pix_fmt, player.sws_flags, NULL, NULL, NULL)\n            if player.img_convert_ctx == NULL:\n                av_log(NULL, AV_LOG_FATAL, b\"Cannot initialize the conversion context\\n\")\n                raise_py_exception(b'Cannot initialize the conversion context.')\n            sws_scale(player.img_convert_ctx, <const unsigned char* const*>src_frame.data, src_frame.linesize,\n                      0, vp.height, vp.frame.data, vp.frame.linesize)\n            av_frame_unref(src_frame)\n        return 0\n\n    cdef int alloc_picture(self) nogil except 1:\n        ''' allocate a picture (needs to do that in main thread to avoid\n        potential locking problems '''\n        cdef Frame *vp\n        self.alloc_mutex.lock()\n        if self.requested_alloc:\n            vp = &self.queue[self.windex]\n            self.frame_queue_unref_item(vp)\n            if vp.need_conversion:\n                av_freep(&vp.frame.data[0])\n\n            if vp.need_conversion:\n                if (av_image_alloc(vp.frame.data, vp.frame.linesize, vp.width,\n                                   vp.height, vp.pix_fmt, 1) < 0):\n                    av_log(NULL, AV_LOG_FATAL, b\"Could not allocate avframe buffer.\\n\")\n                    raise_py_exception(b'Could not allocate avframe buffer')\n\n                vp.frame.width = vp.width\n                vp.frame.height = vp.height\n                vp.frame.format = <int>vp.pix_fmt\n\n            self.cond.lock()\n            vp.allocated = 1\n            self.cond.cond_signal()\n            self.cond.unlock()\n            self.requested_alloc = 0\n        self.alloc_mutex.unlock()\n        return 0\n\n    cdef int peep_alloc(self) nogil:\n        cdef int requested_alloc = 0\n        self.alloc_mutex.lock()\n        requested_alloc = self.requested_alloc\n        self.alloc_mutex.unlock()\n        return requested_alloc\n\n    cdef int queue_picture(\n            self, AVFrame *src_frame, double pts, double duration, int64_t pos,\n            int serial, AVPixelFormat out_fmt, int *abort_request,\n            VideoSettings *player) nogil except 1:\n        cdef Frame *vp\n\n        IF 0:# and defined(DEBUG_SYNC):\n            av_log(NULL, AV_LOG_DEBUG, b\"frame_type=%c pts=%0.3f\\n\",\n                   av_get_picture_type_char(src_frame.pict_type), pts)\n\n        vp = self.frame_queue_peek_writable()\n        if vp == NULL:\n            return -1\n\n        vp.sar = src_frame.sample_aspect_ratio\n\n        # alloc or resize hardware picture buffer\n        if (vp.reallocate or (not vp.allocated) or\n            vp.width != src_frame.width or vp.height != src_frame.height\n            or <int>vp.pix_fmt != <int>out_fmt):\n            vp.allocated = 0\n            vp.reallocate = 0\n            vp.width = src_frame.width\n            vp.height = src_frame.height\n            vp.pix_fmt = out_fmt\n            vp.need_conversion = not CONFIG_AVFILTER and out_fmt != <AVPixelFormat>src_frame.format\n\n            # the allocation must be done in the main thread to avoid locking problems.\n            self.alloc_mutex.lock()\n            self.requested_alloc = 1\n            self.alloc_mutex.unlock()\n\n            # wait until the picture is allocated\n            self.cond.lock()\n            while (not vp.allocated) and not self.pktq.abort_request:\n                self.cond.cond_wait()\n            ''' if the queue is aborted, we have to pop the pending ALLOC event\n            or wait for the allocation to complete '''\n            if self.pktq.abort_request and self.peep_alloc():\n                while not vp.allocated and not abort_request[0]:\n                    self.cond.cond_wait()\n            self.cond.unlock()\n\n            if self.pktq.abort_request:\n                return -1\n\n        # if the frame is not skipped, then display it\n        self.copy_picture(vp, src_frame, player)\n\n        vp.pts = pts\n        vp.duration = duration\n        vp.pos = pos\n        vp.serial = serial\n        self.frame_queue_push()\n        return 0\n"
  },
  {
    "path": "ffpyplayer/player/player.pxd",
    "content": "\ninclude '../includes/ffmpeg.pxi'\n\nfrom ffpyplayer.threading cimport MTGenerator, MTThread, MTMutex\nfrom ffpyplayer.player.core cimport VideoState, VideoSettings\nfrom ffpyplayer.pic cimport Image\n\n\ncdef class MediaPlayer(object):\n    cdef:\n        VideoSettings settings\n        MTGenerator mt_gen\n        VideoState ivs\n        Image next_image\n        int is_closed\n        dict ff_opts\n\n    cdef void _seek(self, double pts, int relative, int seek_by_bytes, int accurate) nogil\n    cpdef close_player(self)\n"
  },
  {
    "path": "ffpyplayer/player/player.pyx",
    "content": "\n__all__ = ('MediaPlayer', )\n\ninclude '../includes/ff_consts.pxi'\ninclude \"../includes/inline_funcs.pxi\"\n\ncdef extern from \"Python.h\":\n    void PyEval_InitThreads()\n\ncdef extern from \"math.h\" nogil:\n    double NAN\n    int isnan(double x)\n\ncdef extern from \"string.h\" nogil:\n    void * memset(void *, int, size_t)\n\nfrom ffpyplayer.threading cimport MTGenerator, SDL_MT, Py_MT, MTThread, MTMutex\nfrom ffpyplayer.player.queue cimport FFPacketQueue\nfrom ffpyplayer.player.core cimport VideoState, VideoSettings\nfrom ffpyplayer.pic cimport Image\nfrom libc.stdio cimport printf\nfrom cpython.ref cimport PyObject\n\nimport ffpyplayer.tools  # required to init ffmpeg\nfrom ffpyplayer.tools import initialize_sdl_aud, encode_to_bytes, loglevels\nfrom copy import deepcopy\n\n\ncdef inline void *grow_array(void *array, int elem_size, int *size, int new_size) nogil:\n    cdef uint8_t *tmp\n    if new_size >= INT_MAX / elem_size:\n        return NULL\n\n    if size[0] < new_size:\n        tmp  = <uint8_t *>av_realloc_array(array, new_size, elem_size)\n        if tmp == NULL:\n            return NULL\n\n        memset(tmp + size[0] * elem_size, 0, (new_size - size[0]) * elem_size)\n        size[0] = new_size\n        return tmp\n    return array\n\n\ncdef class MediaPlayer(object):\n    '''An FFmpeg based media player.\n\n    Was originally ported from FFplay. Most options offered in FFplay is\n    also available here.\n\n    The class provides a player interface to a media file. Video components\n    of the file are returned with :meth:`get_frame`. Audio is played directly\n    using SDL. And subtitles are acquired either through the callback function\n    (text subtitles only), or are overlaid directly using the subtitle filter.\n\n    .. note::\n\n        All strings that are passed to the program, e.g. ``filename`` will first be\n        internally encoded using utf-8 before handing off to FFmpeg.\n\n    .. note::\n\n        If playing or even opening multiple audio files simultaneously\n        SDL2_mixer is required. The audio parameters of the first audio file opened\n        will set the audio output parameters for all the subsequent audio files opened\n        until they are all closed and a new file is opened.\n\n    :Parameters:\n\n        `filename`: str\n            The filename or url of the media object. This can be physical files,\n            remote files or even webcam name's e.g. for direct show or Video4Linux\n            webcams. The ``f`` specifier in ``ff_opts`` can be used to indicate the\n            format needed to open the file (e.g. dshow).\n        `callback`: Function or ref to function or None\n            A function, which if not None will be called when a internal thread quits,\n            when eof is reached (as determined by whichever is the main ``sync`` stream,\n            audio or video), or when text subtitles are available. In future version it\n            may be extended.\n\n            The function takes two parameters, ``selector``, and ``value``.\n            ``selector`` can be one of:\n\n            `eof`:\n                When eof is reached. ``value`` is the empty string.\n\n            `display_sub`:\n                When a new subtitle string is available. ``value`` will be a\n                5-tuple of the form ``(text, fmt, pts, start, end)``. Where\n\n                `text`: is the unicode text\n                `fmt`: is the subtitle format e.g. 'ass'\n                `pts`: is the timestamp of the text\n                `start`: is the time in video time when to start displaying the text\n                `end`: is the time in video time when to end displaying the text\n\n            `exceptions or thread exits`:\n                In case of an exception by the internal audio, video, subtitle, or read threads,\n                or when these threads exit, it is called with a ``value`` of the error message\n                or an empty string when an error is not available.\n\n                The ``selector`` will be one of\n                ``audio:error``, ``audio:exit``, ``video:error``, ``video:exit``,\n                ``subtitle:error``, ``subtitle:exit``, ``read:error``, or ``read:exit``\n                indicating which thread called and why.\n\n            .. warning::\n\n                This functions gets called from a second internal thread.\n\n        `loglevel`: str\n            The level of logs to emit. Defaults to ``'trace'``. Its value is one of the keys\n            of :attr:`~ffpyplayer.tools.loglevels`.\n\n            Although log are also filtered globally according to the level of\n            :attr:`~ffpyplayer.tools.set_loglevel`, this is applied first to quickly filter\n            logs generated by this instance (it's not applied to internal ffmpeg logs).\n        `thread_lib`: str\n            The threading library to use internally. Can be one of 'SDL' or 'python'.\n\n            .. warning::\n\n                If the python threading library is used, care must be taken to delete\n                the player before exiting python, otherwise it may hang. The reason is\n                that the internal threads are created as non-daemon, consequently, when the\n                python main thread exits, the internal threads will keep python alive.\n                By deleting the player directly, the internal threads will be shut down\n                before python exits.\n\n        `audio_sink`: str\n            Currently it must be 'SDL'. Defaults to 'SDL'.\n        `lib_opts`: dict\n            A dictionary of options that will be passed to the ffmpeg libraries,\n            codecs, sws, swr, and formats when opening them. This accepts most of the\n            options that can be passed to FFplay. Examples are \"threads\":\"auto\",\n            \"lowres\":\"1\" etc. Both the keywords and values must be strings.\n            See :ref:`examples` for `lib_opts` usage examples.\n        `ff_opts`: dict\n            A dictionary with options for the player. Following are\n            the available options. Note, many options have identical names and meaning\n            as in the FFplay options: www.ffmpeg.org/ffplay.html :\n\n            `paused`: bool\n                If True, the player will be in a paused state after creation, otherwise,\n                it will immediately start playing. Defaults to False.\n            `cpuflags`: str\n                Similar to ffplay\n            `max_alloc`: int\n                Set the maximum size that may me allocated in one block.\n            `infbuf`: bool\n                If True, do not limit the input buffer size and read as much data as possible\n                from the input as soon as possible. Enabled by default for realtime streams,\n                where data may be dropped if not read in time. Use this option to enable\n                infinite buffers for all inputs.\n            `framedrop`: bool\n                Drop video frames if video is out of sync. Enabled by default if the master\n                clock (``sync``) is not set to video. Use this option to enable/disable frame\n                dropping for all master clock sources.\n            `loop`: int\n                Loops movie playback <number> times. 0 means forever. Defaults to 1.\n            `autoexit`: bool\n                If True, the player stops on eof. Defaults to False.\n            `lowres`: int\n                low resolution decoding, 1-> 1/2 size, 2->1/4 size, defaults to zero.\n            `drp`: int\n                let decoder reorder pts 0=off 1=on -1=auto. Defaults to 0.\n            `genpts`: bool\n                Generate missing pts even if it requires parsing future frames, defaults to False.\n            `fast`: bool\n                Enable non-spec-compliant optimizations, defaults to False.\n            `stats`: bool\n                Print several playback statistics, in particular show the stream duration,\n                the codec parameters, the current position in the stream and the audio/video\n                synchronisation drift. Defaults to False.\n            `pixel_format`: str\n                Sets the pixel format. Note, this sets the format of the input file. For the output\n                format see ``out_fmt``.\n            `t`: float\n                Play only ``t`` seconds of the audio/video. Defaults to the full audio/video.\n            `ss`: float\n                Seek to pos ``ss`` into the file when starting. Note that in most formats it is not\n                possible to seek exactly, so it will seek to the nearest seek point to ``ss``.\n                Defaults to the start of the file.\n            `sync`: str\n                Set the master clock to audio, video, or external (ext). Default is audio.\n                The master clock is used to control audio-video synchronization. Most\n                media players use audio as master clock, but in some cases (streaming or\n                high quality broadcast) it is necessary to change that. Also, setting\n                it to video can ensure the reproducibility of timestamps of video frames.\n            `acodec, vcodec, and scodec`: str\n                Forces a specific audio, video, and/or subtitle decoder. Defaults to None.\n            `ast`: str\n                Select the desired audio stream. If this option is not specified, the \"best\" audio\n                stream is selected in the program of the already selected video stream.\n                See https://ffmpeg.org/ffplay.html#Stream-specifiers-1 for the format.\n            `vst`: str\n                Select the desired video stream. If this option is not specified, the \"best\" video\n                stream is selected.\n                See https://ffmpeg.org/ffplay.html#Stream-specifiers-1 for the format.\n            `sst`: str\n                Select the desired subtitle stream. If this option is not specified, the \"best\" audio\n                stream is selected in the program of the already selected video or audio stream.\n                See https://ffmpeg.org/ffplay.html#Stream-specifiers-1 for the format.\n            `an`: bool\n                Disable audio. Default to False.\n            `vn`: bool\n                Disable video. Default to False.\n            `sn`: bool\n                Disable subtitle. Default to False.\n            `f`: str\n                Force the format to open the file with. E.g. dshow for webcams on windows.\n                See :ref:`dshow-example` for an example. Defaults to none specified.\n            `vf`: str or list of strings\n                The filtergraph(s) used to filter the video stream. A filtergraph is applied to the\n                stream, and must have a single video input and a single video output.\n                In the filtergraph, the input is associated to the label in, and the output\n                to the label out. See the ffmpeg-filters manual for more information\n                about the filtergraph syntax.\n\n                Examples are 'crop=100:100' to crop, 'vflip' to flip horizontally, 'subtitles=filename'\n                to overlay subtitles from another media or text file etc. If a list of filters is\n                specified, :meth:`select_video_filter` can be used to select the desired filter.\n\n                CONFIG_AVFILTER must be True (the default) when compiling in order to use this.\n                Defaults to no filters.\n            `af`: str\n                Similar to ``vf``. However, unlike ``vf``, ``af`` only accepts a single string\n                filter and not a list of filters.\n            `x`: int\n                The desired width of the output frames returned by :meth:`get_frame`. Accepts the\n                same values as the width parameter of :meth:`set_size`.\n            `y`: int\n                The desired height of the output frames returned by :meth:`get_frame`. Accepts the\n                same values as the height parameter of :meth:`set_size`.\n\n                CONFIG_AVFILTER must be True (the default) when compiling in order to use this.\n                Defaults to 0.\n            `out_fmt`: str\n                The desired pixel format for the data returned by :meth:`get_frame`. Accepts\n                the same value as :meth:`set_output_pix_fmt` and can be\n                one of :attr:`ffpyplayer.tools.pix_fmts`. Defaults to rgb24.\n            `autorotate`: bool\n                Whether to automatically rotate the video according to presentation metadata.\n                Defaults to True.\n            `volume`: float\n                The default volume. A value between 0.0 - 1.0.\n            `find_stream_info`: bool\n                Read and decode the streams to fill missing information with heuristics.\n                Defaults to True.\n            `filter_threads`: int\n                The number of filter threads per graph. Defaults to zero\n                (determined by the number of available CPUs).\n\n    For example, a simple player:\n\n    .. code-block:: python\n\n        from ffpyplayer.player import MediaPlayer\n        player = MediaPlayer(filename)\n        while 1:\n            frame, val = player.get_frame()\n            if val == 'eof':\n                break\n            elif frame is None:\n                time.sleep(0.01)\n            else:\n                img, t = frame\n                print val, t, img.get_pixel_format(), img.get_buffer_size()\n                time.sleep(val)\n        # which prints\n        0.0 0.0 rgb24 (929280, 0, 0, 0)\n        0.0 0.0611284 rgb24 (929280, 0, 0, 0)\n        0.0411274433136 0.1222568 rgb24 (929280, 0, 0, 0)\n        0.122380971909 0.1833852 rgb24 (929280, 0, 0, 0)\n        0.121630907059 0.2445136 rgb24 (929280, 0, 0, 0)\n        ...\n\n    See also :ref:`examples`.\n\n    .. warning::\n\n        Most of the methods of this class are not thread safe. That is, they\n        should not be called from different threads for the same instance\n        without protecting them.\n    '''\n\n    def __cinit__(self, filename, callback=None, loglevel='trace', ff_opts={},\n                  thread_lib='SDL', audio_sink='SDL', lib_opts={}, **kargs):\n        cdef unsigned flags\n        cdef VideoSettings *settings = &self.settings\n        cdef AVPixelFormat out_fmt\n        cdef int res, paused\n        ff_opts_orig = ff_opts\n        ff_opts = self.ff_opts = encode_to_bytes(deepcopy(ff_opts))\n        lib_opts = encode_to_bytes(deepcopy(lib_opts))\n        kargs = encode_to_bytes(deepcopy(kargs))\n        filename = encode_to_bytes(filename)\n\n        self.is_closed = 0\n        memset(&self.settings, 0, sizeof(VideoSettings))\n        self.ivs = None\n        PyEval_InitThreads()\n\n        settings.loglevel = loglevels[loglevel]\n        av_dict_set(&settings.sws_dict, b\"flags\", b\"bicubic\", 0)\n        # set x, or y to -1 to preserve pixel ratio\n        settings.screen_width  = ff_opts['x'] if 'x' in ff_opts else 0\n        settings.screen_height = ff_opts['y'] if 'y' in ff_opts else 0\n        if not CONFIG_AVFILTER and (settings.screen_width or settings.screen_height):\n            raise Exception('You can only set the screen size when avfilter is enabled.')\n        settings.audio_disable = bool(ff_opts['an']) if 'an' in ff_opts else 0\n        settings.video_disable = bool(ff_opts['vn']) if 'vn' in ff_opts else 0\n        settings.subtitle_disable = bool(ff_opts['sn']) if 'sn' in ff_opts else 0\n\n        settings.wanted_stream_spec[<int>AVMEDIA_TYPE_AUDIO] = \\\n        settings.wanted_stream_spec[<int>AVMEDIA_TYPE_VIDEO] = \\\n        settings.wanted_stream_spec[<int>AVMEDIA_TYPE_SUBTITLE] = NULL\n\n        if 'ast' in ff_opts:\n            settings.wanted_stream_spec[<int>AVMEDIA_TYPE_AUDIO] =  ff_opts['ast']\n        if 'vst' in ff_opts:\n            settings.wanted_stream_spec[<int>AVMEDIA_TYPE_VIDEO] =  ff_opts['vst']\n        if 'sst' in ff_opts:\n            settings.wanted_stream_spec[<int>AVMEDIA_TYPE_SUBTITLE] =  ff_opts['sst']\n        settings.start_time = ff_opts['ss'] * 1000000 if 'ss' in ff_opts else AV_NOPTS_VALUE\n        settings.duration = ff_opts['t'] * 1000000 if 't' in ff_opts else AV_NOPTS_VALUE\n        settings.autorotate = bool(ff_opts.get('autorotate', 1))\n        settings.find_stream_info = bool(ff_opts.get('find_stream_info', 1))\n        settings.filter_threads = int(ff_opts.get('filter_threads', 0))\n        settings.seek_by_bytes = -1\n        settings.file_iformat = NULL\n        if 'f' in ff_opts:\n            settings.file_iformat = av_find_input_format(ff_opts['f'])\n            if settings.file_iformat == NULL:\n                raise ValueError('Unknown input format: %s.' % ff_opts['f'])\n        if 'pixel_format' in ff_opts:\n            av_dict_set(<AVDictionary **>&settings.format_opts, \"pixel_format\", ff_opts['pixel_format'], 0)\n        settings.show_status = bool(ff_opts['stats']) if 'stats' in ff_opts else 0\n        settings.fast = bool(ff_opts['fast']) if 'fast' in ff_opts else 0\n        settings.genpts = bool(ff_opts['genpts']) if 'genpts' in ff_opts else 0\n        settings.decoder_reorder_pts = -1\n        if 'drp' in ff_opts:\n            val = ff_opts['drp']\n            if val != 1 and val != 0 and val != -1:\n                raise ValueError('Invalid drp option value.')\n            settings.decoder_reorder_pts = val\n        settings.lowres = ff_opts['lowres'] if 'lowres' in ff_opts else 0\n        settings.av_sync_type = AV_SYNC_AUDIO_MASTER\n        settings.audio_volume = av_clip(ff_opts.get('volume', 1) * SDL_MIX_MAXVOLUME, 0, SDL_MIX_MAXVOLUME)\n        if 'sync' in ff_opts_orig:\n            val = ff_opts_orig['sync']\n            if val == 'audio':\n                settings.av_sync_type = AV_SYNC_AUDIO_MASTER\n            elif val == 'video':\n                settings.av_sync_type = AV_SYNC_VIDEO_MASTER\n            elif val == 'ext':\n                settings.av_sync_type = AV_SYNC_EXTERNAL_CLOCK\n            else:\n                raise ValueError('Invalid sync option value.')\n        settings.autoexit = bool(ff_opts['autoexit']) if 'autoexit' in ff_opts else 0\n        settings.loop = ff_opts['loop'] if 'loop' in ff_opts else 1\n        settings.framedrop = bool(ff_opts['framedrop']) if 'framedrop' in ff_opts else -1\n        # -1 means not infinite, not respected if real time.\n        settings.infinite_buffer = 1 if 'infbuf' in ff_opts and ff_opts['infbuf'] else -1\n\n        IF CONFIG_AVFILTER:\n            if 'vf' in ff_opts:\n                vfilters = ff_opts['vf']\n                if isinstance(vfilters, basestring):\n                    vfilters = ff_opts['vf'] = [vfilters]\n                for vfilt in vfilters:\n                    settings.vfilters_list = <const char **>grow_array(\n                        settings.vfilters_list, sizeof(settings.vfilters_list[0]),\n                        &settings.nb_vfilters, settings.nb_vfilters + 1)\n                    settings.vfilters_list[settings.nb_vfilters - 1] = vfilt\n\n            settings.afilters = NULL\n            if 'af' in ff_opts:\n                settings.afilters = ff_opts['af']\n            settings.avfilters = NULL\n            if 'avf' in ff_opts:\n                settings.avfilters = ff_opts['avf']\n        settings.audio_codec_name = NULL\n        if 'acodec' in ff_opts:\n            settings.audio_codec_name = ff_opts['acodec']\n        settings.video_codec_name = NULL\n        if 'vcodec' in ff_opts:\n            settings.video_codec_name = ff_opts['vcodec']\n        settings.subtitle_codec_name = NULL\n        if 'scodec' in ff_opts:\n            settings.subtitle_codec_name = ff_opts['scodec']\n        if 'max_alloc' in ff_opts:\n            av_max_alloc(ff_opts['max_alloc'])\n        if 'cpuflags' in ff_opts:\n            flags = av_get_cpu_flags()\n            if av_parse_cpu_caps(&flags, ff_opts['cpuflags']) < 0:\n                raise ValueError('Invalid cpuflags option value.')\n            av_force_cpu_flags(flags)\n\n        for k, v in lib_opts.iteritems():\n            k_new = k.encode('utf8')\n            if opt_default(\n                    k_new, v, NULL, &settings.sws_dict, &settings.swr_opts,\n                    &settings.resample_opts, &settings.format_opts,\n                    &self.settings.codec_opts) < 0:\n                raise Exception('library option %s: %s not found' % (k, v))\n\n        # filename can start with pipe:\n        settings.input_filename = av_strdup(<char *>filename)\n        if settings.input_filename == NULL:\n            raise MemoryError()\n        if thread_lib == 'SDL':\n            if not CONFIG_SDL:\n                raise Exception('FFPyPlayer extension not compiled with SDL support.')\n            self.mt_gen = MTGenerator(SDL_MT)\n        elif thread_lib == 'python':\n            self.mt_gen = MTGenerator(Py_MT)\n        else:\n            raise Exception('Thread library parameter not recognized.')\n\n        settings.audio_sdl = audio_sink == 'SDL'\n        if audio_sink != 'SDL':\n            raise Exception('Audio sink \"{}\" not recognized'.format(audio_sink))\n        if callback is not None and not callable(callback):\n            raise Exception('Video sink parameter not recognized.')\n\n        if 'out_fmt' in ff_opts:\n            out_fmt = av_get_pix_fmt(ff_opts['out_fmt'])\n        else:\n            out_fmt = av_get_pix_fmt(b'rgb24')\n        if out_fmt == AV_PIX_FMT_NONE:\n            raise Exception('Unrecognized output pixel format.')\n\n        if not settings.audio_disable:\n            initialize_sdl_aud()\n\n        self.next_image = Image.__new__(Image, no_create=True)\n        self.ivs = VideoState(callback)\n        paused = ff_opts.get('paused', False)\n        with nogil:\n            self.ivs.cInit(self.mt_gen, settings, paused, out_fmt)\n\n    def __dealloc__(self):\n        self.close_player()\n\n    cpdef close_player(self):\n        '''Closes the player and all resources.\n\n        .. warning::\n\n            After calling this method, calling any other class method on this instance may\n            result in a crash or program corruption.\n        '''\n        if self.is_closed:\n            return\n        self.is_closed = 1\n\n        #XXX: cquit has to be called, otherwise the read_thread never exitsts.\n        # probably some circular referencing somewhere (in event_loop)\n        if self.ivs:\n            with nogil:\n                self.ivs.cquit()\n        self.ivs = None\n\n        av_dict_free(&self.settings.format_opts)\n        av_dict_free(&self.settings.resample_opts)\n        av_dict_free(&self.settings.codec_opts)\n        av_dict_free(&self.settings.swr_opts)\n        av_dict_free(&self.settings.sws_dict)\n        IF CONFIG_AVFILTER:\n            av_freep(&self.settings.vfilters_list)\n        # avformat_network_deinit()\n        av_free(self.settings.input_filename)\n        # if self.settings.show_status:\n        #    av_log(NULL, AV_LOG_INFO, b\"\\n\")\n        # SDL_Quit()\n        # av_log(NULL, AV_LOG_QUIET, b\"\")\n\n    def get_frame(self, force_refresh=False, show=True, *args):\n        '''Retrieves the next available frame if ready.\n\n        The frame is returned as a :class:`ffpyplayer.pic.Image`. If CONFIG_AVFILTER\n        is True when compiling, or if the video pixel format is the same as the\n        output pixel format, the Image returned is just a new reference to the internal\n        buffers and no copying occurs (see :class:`ffpyplayer.pic.Image`), otherwise\n        the buffers are newly created and copied.\n\n        :Parameters:\n\n            `force_refresh`: bool\n                If True, a new instance of the last frame will be returned again.\n                Defaults to False.\n            `show`: bool\n                If True a image is returned as normal, if False, no image will be\n                returned, even when one is available. Can be useful if we just need\n                the timestamps or when ``force_refresh`` to just get the timestamps.\n                Defaults to True.\n\n        :returns:\n\n            `A 2-tuple of (frame, val)` where\n                `frame`: is None or a 2-tuple\n                `val`: is either 'paused', 'eof', or a float\n\n            If ``val`` is either ``'paused'`` or ``'eof'`` then ``frame`` is None.\n\n            Otherwise, if ``frame`` is not None, ``val`` is the realtime time from now\n            one should wait before displaying this frame to the user to achieve a play\n            rate of 1.0.\n\n            Finally, if ``frame`` is not None then it's a 2-tuple of ``(image, pts)`` where:\n\n                `image`: The :class:`ffpyplayer.pic.Image` instance containing\n                    the frame. The size of the image can change because the output\n                    can be resized dynamically (see :meth:`set_size`). If `show` was\n                    False, it will be None.\n                `pts`: The presentation timestamp of this frame. This is the time\n                    when the frame should be displayed to the user in video time (i.e.\n                    not realtime).\n\n        .. note::\n\n            The audio plays at a normal play rate, independent of when and if\n            this function is called. Therefore, 'eof' will only be received when\n            the audio is complete, even if all the frames have been read (unless\n            audio is disabled or sync is set to video). I.e. a None frame will\n            be sent after all the frames have been read until eof.\n\n        For example, playing as soon as frames are read:\n\n        .. code-block:: python\n\n            >>> while 1:\n            ...     frame, val = player.get_frame()\n            ...     if val == 'eof':\n            ...         break\n            ...     elif frame is None:\n            ...         time.sleep(0.01)\n            ...         print 'not ready'\n            ...     else:\n            ...         img, t = frame\n            ...         print val, t, img\n            not ready\n            0.0 0.0 <ffpyplayer.pic.Image object at 0x023D17B0>\n            not ready\n            0.0351264476776 0.0611284 <ffpyplayer.pic.Image object at 0x023D1828>\n            0.096254825592 0.1222568 <ffpyplayer.pic.Image object at 0x02411800>\n            not ready\n            0.208511352539 0.1833852 <ffpyplayer.pic.Image object at 0x02411B70>\n\n        vs displaying frames at their proper times:\n\n        .. code-block:: python\n\n            >>> while 1:\n            ...     frame, val = player.get_frame()\n            ...     if val == 'eof':\n            ...         break\n            ...     elif frame is None:\n            ...         time.sleep(0.01)\n            ...         print 'not ready'\n            ...     else:\n            ...         img, t = frame\n            ...         print val, t, img\n            ...         time.sleep(val)\n            not ready\n            0.0 0.0 <ffpyplayer.pic.Image object at 0x02411800>\n            not ready\n            0.0351274013519 0.0611284 <ffpyplayer.pic.Image object at 0x02411878>\n            0.0602538585663 0.1222568 <ffpyplayer.pic.Image object at 0x024118A0>\n            0.122507572174 0.1833852 <ffpyplayer.pic.Image object at 0x024118C8>\n            ...\n            0.0607514381409 1.222568 <ffpyplayer.pic.Image object at 0x02411B70>\n            0.0618767738342 1.2836964 <ffpyplayer.pic.Image object at 0x02411B98>\n            0.0610010623932 1.3448248 <ffpyplayer.pic.Image object at 0x02411BC0>\n            0.0611264705658 1.4059532 <ffpyplayer.pic.Image object at 0x02411BE8>\n\n        Or when the output format is yuv420p:\n\n        .. code-block:: python\n\n            >>> player = MediaPlayer(filename, callback=weakref.ref(callback),\n            ... ff_opts={'out_fmt':'yuv420p'})\n            >>> while 1:\n            ...     frame, val = player.get_frame()\n            ...     if val == 'eof':\n            ...         break\n            ...     elif frame is None:\n            ...         time.sleep(0.01)\n            ...         print 'not ready'\n            ...     else:\n            ...         img, t = frame\n            ...         print val, t, img.get_pixel_format(), img.get_buffer_size()\n            ...         time.sleep(val)\n            ...\n            0.0 0.0 yuv420p (309760, 77440, 77440, 0)\n            0.0361273288727 0.0611284 yuv420p (309760, 77440, 77440, 0)\n            0.0502526760101 0.1222568 yuv420p (309760, 77440, 77440, 0)\n            0.12150645256 0.1833852 yuv420p (309760, 77440, 77440, 0)\n            0.122756242752 0.2445136 yuv420p (309760, 77440, 77440, 0)\n        '''\n        cdef Image next_image = self.next_image\n        cdef int res, f = force_refresh\n        cdef int s = show\n        cdef double pts, remaining_time\n\n        if not s:\n            next_image = None\n        with nogil:\n            res = self.ivs.video_refresh(next_image, &pts, &remaining_time, f)\n\n        if res == 1:\n            return (None, 'paused')\n        elif res == 2:\n            return (None, 'eof')\n        elif res == 3:\n            return (None, remaining_time)\n\n        if s:\n            self.next_image = Image.__new__(Image, no_create=True)\n        return ((next_image, pts), remaining_time)\n\n    def get_metadata(self):\n        '''Returns metadata of the file being played.\n\n        :returns:\n\n            dict:\n                Media file metadata. e.g. `frame_rate` is reported as a\n                numerator and denominator. src and sink video sizes correspond to\n                the frame size of the original video, and the frames returned by\n                :meth:`get_frame`, respectively. `src_pix_fmt` is the pixel format\n                of the original input stream. 'aspect_ratio' is the source to\n                display aspect ratio as a numerator and denominator. Duration\n                is the file duration and defaults to None until updated.\n\n        :\n\n        .. code-block:: python\n\n            >>> print player.get_metadata()\n            {'duration': 71.972, 'sink_vid_size': (0, 0), 'src_vid_size':\n             (704, 480), 'frame_rate': (13978, 583),\n             'title': 'The Melancholy of Haruhi Suzumiya: Special Ending',\n             'src_pix_fmt': 'yuv420p'}\n\n        .. warning::\n\n            The dictionary returned will have default values until the file is\n            open and read. Because a second thread is created and used to read\n            the file, when the constructor returns the dict might still have\n            the default values.\n\n            After the first frame is read, the dictionary entries are correct\n            with respect to the file metadata. Alternatively, you can wait\n            until the desired parameter is updated from its default value.\n            Note, the metadata dict will be updated even if the video is\n            paused.\n\n        .. note::\n\n            Some paramteres can change as the streams are manipulated (e.g. the\n            frame size and source format parameters).\n        '''\n        return self.ivs.metadata\n\n    def select_video_filter(self, index=0):\n        '''Selects the video filter to use from among the list of filters passed\n        with the ff_opts `vf` options.\n        '''\n        if (self.settings.vfilters_list == NULL or\n            index >= self.settings.nb_vfilters or index < 0):\n            raise ValueError(index)\n        self.ivs.vfilter_idx = index\n\n    def set_volume(self, volume):\n        '''Sets the volume of the audio.\n\n        :Parameters:\n\n            `volume`: float\n                A value between 0.0 - 1.0.\n        '''\n        self.settings.audio_volume = av_clip(volume * SDL_MIX_MAXVOLUME, 0, SDL_MIX_MAXVOLUME)\n        IF USE_SDL2_MIXER:\n            with nogil:\n                Mix_Volume(self.ivs.audio_dev, self.settings.audio_volume)\n\n    def get_volume(self):\n        '''Returns the volume of the audio.\n\n        :returns:\n\n            `float`: A value between 0.0 - 1.0.\n        '''\n        return self.settings.audio_volume / <double>SDL_MIX_MAXVOLUME\n\n    def set_mute(self, state):\n        '''Mutes or un-mutes the audio.\n\n        :Parameters:\n\n            `state`: bool\n                Whether to mute or unmute the audio.\n        '''\n        self.settings.muted = state\n\n    def get_mute(self):\n        '''Returns whether the player is muted.\n        '''\n        return bool(self.settings.muted)\n\n    def toggle_pause(self):\n        '''Toggles the player's pause state.\n        '''\n        with nogil:\n            self.ivs.toggle_pause()\n\n    def set_pause(self, state):\n        '''Pauses or un-pauses the file.\n\n        :Parameters:\n\n            `state`: bool\n                Whether to pause or un-pause the player.\n        '''\n        if self.ivs.paused and state or not self.ivs.paused and not state:\n            return\n        with nogil:\n            self.ivs.toggle_pause()\n\n    def get_pause(self):\n        '''Returns whether the player is paused.\n        '''\n        return bool(self.ivs.paused)\n\n    def get_pts(VideoState self):\n        '''Returns the elapsed play time.\n\n        :returns:\n\n            `float`:\n                The amount of the time that the file has been playing.\n                The time is from the clock used for the player (default is audio,\n                see ``sync`` options). If the clock is based on video, it should correspond\n                with the pts from get_frame.\n        '''\n        cdef double pos\n        cdef int sync_type = self.ivs.get_master_sync_type()\n        if (sync_type == AV_SYNC_VIDEO_MASTER and\n            self.ivs.video_stream != -1):\n            pos = self.ivs.vidclk.get_clock()\n        elif (sync_type == AV_SYNC_AUDIO_MASTER and\n            self.ivs.audio_stream != -1):\n            pos = self.ivs.audclk.get_clock()\n        else:\n            pos = self.ivs.extclk.get_clock()\n        if isnan(pos):\n            pos = <double>self.ivs.seek_pos / <double>AV_TIME_BASE\n        if (self.ivs.ic.start_time != AV_NOPTS_VALUE and\n            pos < self.ivs.ic.start_time / <double>AV_TIME_BASE):\n            pos = self.ivs.ic.start_time / <double>AV_TIME_BASE\n        return pos\n\n    def set_size(self, int width=-1, int height=-1):\n        '''Dynamically sets the size of the frames returned by :meth:`get_frame`.\n\n        :Parameters:\n\n            `width, height`: int\n                The width and height of the output frames.\n                A value of 0 will set that parameter to the source width/height.\n                A value of -1 for one of the parameters, will result in a value of that\n                parameter that maintains the original aspect ratio.\n\n        For example:\n\n        .. code-block:: python\n\n            >>> print player.get_frame()[0][0].get_size()\n            (704, 480)\n\n            >>> player.set_size(200, 200)\n            >>> print player.get_frame()[0][0].get_size()\n            (704, 480)\n            >>> print player.get_frame()[0][0].get_size()\n            (704, 480)\n            >>> print player.get_frame()[0][0].get_size()\n            (704, 480)\n            >>> print player.get_frame()[0][0].get_size()\n            (200, 200)\n\n            >>> player.set_size(200, 0)\n            >>> print player.get_frame()[0][0].get_size()\n            (200, 200)\n            >>> print player.get_frame()[0][0].get_size()\n            (200, 200)\n            >>> print player.get_frame()[0][0].get_size()\n            (200, 480)\n\n            >>> player.set_size(200, -1)\n            >>> print player.get_frame()[0][0].get_size()\n            (200, 480)\n            >>> print player.get_frame()[0][0].get_size()\n            (200, 480)\n            >>> print player.get_frame()[0][0].get_size()\n            (200, 136)\n\n        Note, that it takes a few calls to flush the old frames.\n\n        .. note::\n\n            if CONFIG_AVFILTER was False when compiling, this function will raise\n            an error.\n        '''\n        if not CONFIG_AVFILTER and (width or height):\n            raise Exception('You can only set the screen size when avfilter is enabled.')\n        self.settings.screen_width = width\n        self.settings.screen_height = height\n\n    def get_output_pix_fmt(self):\n        '''Returns the pixel fmt in which output images are returned when calling\n        :attr:`get_frame`.\n\n        You can set the output format by specifying ``out_fmt`` in ``ff_opts``\n        when creating this instance. Also, if avfilter is enabled, you can\n        change it dynamically with :meth:`set_output_pix_fmt`.\n\n        ::\n\n            >>> print(player.get_output_pix_fmt())\n            rgb24\n        '''\n        return self.ivs.get_out_pix_fmt()\n\n    def set_output_pix_fmt(self, pix_fmt):\n        '''Sets the pixel fmt in which output images are returned when calling\n        :meth:`get_frame`.\n\n        For example::\n\n            >>> player.set_output_pix_fmt('yuv420p')\n\n        sets the output format to use. This will only take effect on images that\n        have not been queued yet so it may take a few calls to :meth:`get_frame`\n        to reflect the new pixel format.\n\n        .. note::\n\n            if CONFIG_AVFILTER was False when compiling, this function will raise\n            an exception.\n        '''\n        cdef AVPixelFormat fmt\n        cdef bytes pix_fmt_b\n        if not CONFIG_AVFILTER:\n            raise Exception('You can only change the fmt when avfilter is enabled.')\n\n        pix_fmt_b = pix_fmt.encode('utf8')\n        fmt = av_get_pix_fmt(pix_fmt_b)\n        if fmt == AV_PIX_FMT_NONE:\n            raise Exception('Unrecognized output pixel format {}.'.format(pix_fmt))\n        self.ivs.set_out_pix_fmt(fmt)\n\n    # Currently, if a stream is re-opened when the stream was not open before\n    # it'l cause some seeking. We can probably remove it by setting a seek flag\n    # only for this stream and not for all, provided is not the master clock stream.\n    def request_channel(self, stream_type, action='cycle', int requested_stream=-1):\n        '''Opens or closes a stream dynamically.\n\n        This function may result in seeking when opening a new stream.\n\n        :Parameters:\n\n            `stream_type`: str\n                The stream group on which to operate. Can be one of ``'audio'``,\n                ``'video'``, or ``'subtitle'``.\n            `action`: str\n                The action to perform. Can be one of ``'open'``, ``'close'``, or\n                ``'cycle'``. A value of 'cycle' will close the current stream and\n                open the next stream in this group.\n            `requested_stream`: int\n                The stream to open next when ``action`` is ``'cycle'`` or ``'open'``.\n                If ``-1``, the next stream will be opened. Otherwise, this stream will\n                be attempted to be opened.\n        '''\n\n        cdef int stream, old_index\n        if stream_type == 'audio':\n            stream = AVMEDIA_TYPE_AUDIO\n            old_index = self.ivs.audio_stream\n        elif stream_type == 'video':\n            stream = AVMEDIA_TYPE_VIDEO\n            old_index = self.ivs.video_stream\n        elif stream_type == 'subtitle':\n            stream = AVMEDIA_TYPE_SUBTITLE\n            old_index = self.ivs.subtitle_stream\n        else:\n            raise Exception('Invalid stream type')\n\n        if action == 'cycle' or requested_stream == -1:\n            with nogil:\n                self.ivs.stream_cycle_channel(stream)\n        elif action == 'open':\n            if requested_stream < 0 or <unsigned int>requested_stream >= self.ivs.ic.nb_streams:\n                raise Exception('Stream number out of range')\n\n            with nogil:\n                self.ivs.stream_select_channel(stream, <unsigned int>requested_stream)\n        elif action == 'close':\n            with nogil:\n                self.ivs.stream_component_close(old_index)\n\n    def get_programs(self):\n        '''Returns a list of available program IDs.\n\n        ::\n\n            >>> print(player.get_programs())\n            [0, 1, 2, 3, 4]\n        '''\n\n        cdef list programs = []\n        cdef unsigned int i\n\n        i = 0\n        while i < self.ivs.ic.nb_programs:\n            programs.append(self.ivs.ic.programs[i].id)\n            i += 1\n\n        return programs\n\n    def request_program(self, int requested_program):\n        '''Opens video, audio and subtitle streams associated with a program.\n\n        This closes all current streams and opens the first video, audio and\n        subtitle streams found in the program.\n\n        :Parameters:\n\n            `requested_program`: int\n                The program ID.\n        '''\n\n        with nogil:\n            self.ivs.stream_select_program(requested_program)\n\n    def seek(self, pts, relative=True, seek_by_bytes='auto', accurate=True):\n        '''Seeks in the current streams.\n\n        Seeks to the desired timepoint as close as possible while not exceeding\n        that time.\n\n        :Parameters:\n\n            `pts`: float\n                The timestamp to seek to (in seconds).\n            `relative`: bool\n                Whether the pts parameter is interpreted as the\n                time offset from the current stream position (can be negative if True).\n            `seek_by_bytes`: bool or ``'auto'``\n                Whether we seek based on the position in bytes or in time. In some\n                instances seeking by bytes may be more accurate (don't ask me which).\n                If ``'auto'``, the default, it is automatically decided based on\n                the media.\n            `accurate`: bool\n                Whether to do finer seeking if we didn't seek directly to the requested\n                frame. This is likely to be slower because after the coarser seek,\n                we have to walk through the frames until the requested frame is\n                reached. If paused or we reached eof this is ignored. Defaults to True.\n\n        For example:\n\n        .. code-block:: python\n\n            >>> print player.get_frame()[0][1]\n            1016.392\n\n            >>> player.seek(200., accurate=False)\n            >>> player.get_frame()\n            >>> print player.get_frame()[0][1]\n            1249.876\n\n            >>> player.seek(200, relative=False, accurate=False)\n            >>> player.get_frame()\n            >>> print player.get_frame()[0][1]\n            198.49\n\n        Note that it may take a few calls to get new frames after seeking.\n        '''\n        cdef int c_relative = relative\n        cdef int c_accurate = accurate\n        cdef int c_seek_by_bytes\n        cdef double c_pts = pts\n        if seek_by_bytes == 'auto':\n            c_seek_by_bytes = self.settings.seek_by_bytes > 0\n        else:\n            c_seek_by_bytes = seek_by_bytes\n\n        with nogil:\n            self._seek(c_pts, c_relative, c_seek_by_bytes, c_accurate)\n\n    def seek_to_chapter(self, increment, accurate=True):\n        '''Seeks forwards or backwards (if negative) by ``increment`` chapters.\n\n        :Parameters:\n\n            `increment`: int\n                The number of chapters to seek forwards or backwards to.\n            `accurate`: bool\n                Whether to do finer seeking if we didn't seek directly to the requested\n                frame. This is likely to be slower because after the coarser seek,\n                we have to walk through the frames until the requested frame is\n                reached. Defaults to True.\n        '''\n        cdef int c_increment = increment\n        cdef int c_accurate = accurate\n        with nogil:\n            self.ivs.seek_chapter(c_increment, c_accurate)\n\n    cdef void _seek(self, double pts, int relative, int seek_by_bytes, int accurate) nogil:\n        '''Returns the actual pos where we wanted to seek to.\n        '''\n        cdef double incr, pos\n        cdef int64_t t_pos = 0, t_rel = 0\n\n        if relative:\n            incr = pts\n            if seek_by_bytes:\n                pos = -1\n                if self.ivs.video_stream >= 0:\n                    pos = self.ivs.pictq.frame_queue_last_pos()\n                if pos < 0 and self.ivs.audio_stream >= 0:\n                    pos = self.ivs.sampq.frame_queue_last_pos()\n                if pos < 0:\n                    pos = avio_tell(self.ivs.ic.pb)\n                if self.ivs.ic.bit_rate:\n                    incr *= self.ivs.ic.bit_rate / 8.0\n                else:\n                    incr *= 180000.0\n                pos += incr\n                t_pos = <int64_t>pos\n                t_rel = <int64_t>incr\n            else:\n                pos = self.ivs.get_master_clock()\n                if isnan(pos):\n                    # seek_pos might never have been set\n                    pos = <double>self.ivs.seek_pos / <double>AV_TIME_BASE\n                pos += incr\n                if self.ivs.ic.start_time != AV_NOPTS_VALUE and pos < self.ivs.ic.start_time / <double>AV_TIME_BASE:\n                    pos = self.ivs.ic.start_time / <double>AV_TIME_BASE\n                t_pos = <int64_t>(pos * AV_TIME_BASE)\n                t_rel = <int64_t>(incr * AV_TIME_BASE)\n        else:\n            pos = pts\n            if seek_by_bytes:\n                if self.ivs.ic.bit_rate:\n                    pos *= self.ivs.ic.bit_rate / 8.0\n                else:\n                    pos *= 180000.0\n                t_pos = <int64_t>pos\n            else:\n                t_pos = <int64_t>(pos * AV_TIME_BASE)\n                if self.ivs.ic.start_time != AV_NOPTS_VALUE and t_pos < self.ivs.ic.start_time:\n                    t_pos = self.ivs.ic.start_time\n        self.ivs.stream_seek(t_pos, t_rel, seek_by_bytes, accurate)\n"
  },
  {
    "path": "ffpyplayer/player/queue.pxd",
    "content": "\ninclude '../includes/ffmpeg.pxi'\n\nfrom ffpyplayer.threading cimport MTGenerator, MTCond\n\ncdef struct MyAVPacketList:\n    AVPacket *pkt\n    int serial\n\n\ncdef class FFPacketQueue(object):\n    cdef:\n        MTGenerator mt_gen\n        AVFifoBuffer *pkt_list\n        int nb_packets\n        int size\n        int64_t duration\n        int abort_request\n        int serial\n        MTCond cond\n\n    cdef int packet_queue_put_private(FFPacketQueue self, AVPacket *pkt) nogil except 1\n    cdef int packet_queue_put_nullpacket(FFPacketQueue self, AVPacket *pkt, int stream_index) nogil except 1\n    cdef int packet_queue_put(FFPacketQueue self, AVPacket *pkt) nogil except 1\n    cdef int packet_queue_flush(FFPacketQueue self) nogil except 1\n    cdef int packet_queue_abort(FFPacketQueue self) nogil except 1\n    cdef int packet_queue_start(FFPacketQueue self) nogil except 1\n    # return < 0 if aborted, 0 if no packet and > 0 if packet.\n    cdef int packet_queue_get(FFPacketQueue self, AVPacket *pkt, int block, int *serial) nogil except 0\n"
  },
  {
    "path": "ffpyplayer/player/queue.pyx",
    "content": "\n__all__ = ('FFPacketQueue', )\n\ninclude '../includes/ff_consts.pxi'\n\nfrom ffpyplayer.threading cimport MTGenerator, MTMutex, MTCond\n\n\ncdef class FFPacketQueue(object):\n\n    def __cinit__(FFPacketQueue self, MTGenerator mt_gen):\n        self.mt_gen = mt_gen\n        self.pkt_list = NULL\n        self.nb_packets = self.size = self.serial = 0\n        self.duration = 0\n\n        self.pkt_list = av_fifo_alloc(sizeof(MyAVPacketList))\n        if self.pkt_list == NULL:\n            raise MemoryError\n\n        self.cond = MTCond.__new__(MTCond, mt_gen.mt_src)\n        self.abort_request = 1\n\n    def __dealloc__(self):\n        if self.cond is None:\n            return\n        with nogil:\n            self.packet_queue_flush()\n            av_fifo_freep(&self.pkt_list)\n\n    cdef int packet_queue_put_private(FFPacketQueue self, AVPacket *pkt) nogil except 1:\n        cdef MyAVPacketList pkt1\n        cdef int ret\n\n        if self.abort_request:\n            return -1\n\n        if av_fifo_space(self.pkt_list) < sizeof(pkt1):\n            ret = av_fifo_grow(self.pkt_list, sizeof(pkt1))\n            if ret < 0:\n                return ret\n\n        pkt1.pkt = pkt\n        pkt1.serial = self.serial\n\n        ret = av_fifo_generic_write(self.pkt_list, &pkt1, sizeof(pkt1), NULL)\n        if ret < 0:\n            return ret\n        self.nb_packets += 1\n        self.size += pkt1.pkt.size + sizeof(pkt1)\n        self.duration += pkt1.pkt.duration\n        #/* XXX: should duplicate packet data in DV case */\n        self.cond.cond_signal()\n        return 0\n\n    cdef int packet_queue_put(FFPacketQueue self, AVPacket *pkt) nogil except 1:\n        cdef AVPacket *pkt1 = av_packet_alloc()\n        cdef int ret = -1\n\n        if pkt1 == NULL:\n            av_packet_unref(pkt)\n            return -1\n        av_packet_move_ref(pkt1, pkt)\n\n        self.cond.lock()\n        ret = self.packet_queue_put_private(pkt1)\n        self.cond.unlock()\n\n        if ret < 0:\n            av_packet_free(&pkt1)\n\n        return ret\n\n    cdef int packet_queue_put_nullpacket(FFPacketQueue self, AVPacket *pkt, int stream_index) nogil except 1:\n        pkt.stream_index = stream_index\n        return self.packet_queue_put(pkt)\n\n    cdef int packet_queue_flush(FFPacketQueue self) nogil except 1:\n        cdef MyAVPacketList pkt1\n        cdef int ret = 0\n\n        self.cond.lock()\n        while av_fifo_size(self.pkt_list) >= sizeof(pkt1):\n            ret = av_fifo_generic_read(self.pkt_list, &pkt1, sizeof(pkt1), NULL)\n            if ret < 0:\n                break\n            av_packet_free(&pkt1.pkt)\n\n        self.nb_packets = 0\n        self.size = 0\n        self.duration = 0\n        self.serial += 1\n        self.cond.unlock()\n        return ret\n\n    cdef int packet_queue_abort(FFPacketQueue self) nogil except 1:\n        self.cond.lock()\n        self.abort_request = 1\n        self.cond.cond_signal()\n        self.cond.unlock()\n        return 0\n\n    cdef int packet_queue_start(FFPacketQueue self) nogil except 1:\n        self.cond.lock()\n        self.abort_request = 0\n        self.serial += 1\n        self.cond.unlock()\n        return 0\n\n    # return < 0 if aborted, 0 if no packet and > 0 if packet.\n    cdef int packet_queue_get(FFPacketQueue self, AVPacket *pkt, int block, int *serial) nogil except 0:\n        cdef MyAVPacketList pkt1\n        cdef int ret = 0\n\n        self.cond.lock()\n\n        while True:\n            if self.abort_request:\n                ret = -1\n                break\n\n            if av_fifo_size(self.pkt_list) >= sizeof(pkt1):\n                ret = av_fifo_generic_read(self.pkt_list, &pkt1, sizeof(pkt1), NULL)\n                if ret < 0:\n                    break\n                self.nb_packets -= 1\n                self.size -= pkt1.pkt.size + sizeof(pkt1)\n                self.duration -= pkt1.pkt.duration\n\n                av_packet_move_ref(pkt, pkt1.pkt)\n                if serial != NULL:\n                    serial[0] = pkt1.serial\n                av_packet_free(&pkt1.pkt)\n                ret = 1\n                break\n            elif not block:\n                ret = -1\n                break\n            else:\n                self.cond.cond_wait()\n        self.cond.unlock()\n        return ret\n"
  },
  {
    "path": "ffpyplayer/tests/__init__.py",
    "content": ""
  },
  {
    "path": "ffpyplayer/tests/common.py",
    "content": "\r\n__all__ = ('get_media', )\r\n\r\nfrom os import environ\r\nfrom os.path import join, abspath, dirname, exists, pathsep\r\n\r\nfrom ffpyplayer.tools import set_loglevel, set_log_callback\r\nimport logging\r\n\r\nset_log_callback(logger=logging, default_only=True)\r\nset_loglevel('trace')\r\n\r\n\r\ndef get_media(fname):\r\n    if exists(fname):\r\n        return abspath(fname)\r\n\r\n    root = dirname(__file__)\r\n    if exists(join(root, fname)):\r\n        return join(root, fname)\r\n\r\n    ex = abspath(join(root, '../../examples', fname))\r\n    if exists(ex):\r\n        return ex\r\n\r\n    if 'FFPYPLAYER_TEST_DIRS' in environ:\r\n        for d in environ['FFPYPLAYER_TEST_DIRS'].split(pathsep):\r\n            d = d.strip()\r\n            if not d:\r\n                continue\r\n\r\n            if exists(join(d, fname)):\r\n                return join(d, fname)\r\n\r\n    raise IOError(\"{} doesn't exist\".format(fname))\r\n"
  },
  {
    "path": "ffpyplayer/tests/test_pic.py",
    "content": "\r\ndef create_image(size):\r\n    from ffpyplayer.pic import Image\r\n\r\n    w, h = size\r\n    size = w * h * 3\r\n    buf = bytearray([int(x * 255 / size) for x in range(size)])\r\n    return Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\r\n\r\n\r\ndef test_pic():\r\n    from ffpyplayer.pic import SWScale\r\n\r\n    size = w, h = 500, 100\r\n    img = create_image(size)\r\n\r\n    assert not img.is_ref()\r\n    assert img.get_size() == (w, h)\r\n\r\n    sws = SWScale(w, h, img.get_pixel_format(), ofmt='yuv420p')\r\n\r\n    img2 = sws.scale(img)\r\n    assert img2.get_pixel_format() == 'yuv420p'\r\n    planes = img2.to_bytearray()\r\n    assert list(map(len, planes)) == [w * h, w * h / 4, w * h / 4, 0]\r\n"
  },
  {
    "path": "ffpyplayer/tests/test_play.py",
    "content": "\r\ndef test_play():\r\n    from .common import get_media\r\n    from ffpyplayer.player import MediaPlayer\r\n    import time\r\n\r\n    error = [None, ]\r\n\r\n    def callback(selector, value):\r\n        if selector.endswith('error'):\r\n            error[0] = selector, value\r\n\r\n    # only video\r\n    ff_opts = {'an': True, 'sync': 'video'}\r\n    player = MediaPlayer(\r\n        get_media('dw11222.mp4'), callback=callback, ff_opts=ff_opts)\r\n\r\n    i = 0\r\n    while not error[0]:\r\n        frame, val = player.get_frame()\r\n        if val == 'eof':\r\n            break\r\n        elif frame is None:\r\n            time.sleep(0.001)\r\n        else:\r\n            img, t = frame\r\n            i += 1\r\n\r\n    player.close_player()\r\n    if error[0]:\r\n        raise Exception('{}: {}'.format(*error[0]))\r\n\r\n    assert i == 6077\r\n"
  },
  {
    "path": "ffpyplayer/tests/test_write.py",
    "content": "import time\r\nimport math\r\nimport pytest\r\n\r\n\r\ndef get_image(w, h):\r\n    from ffpyplayer.pic import Image\r\n\r\n    # Construct images\r\n    size = w * h * 3\r\n    buf = bytearray([int(x * 255 / size) for x in range(size)])\r\n    img = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\r\n    return img\r\n\r\n\r\ndef get_gray_image_with_val(w, h, val):\r\n    from ffpyplayer.pic import Image\r\n\r\n    # Construct images\r\n    size = w * h\r\n    buf = bytearray([int(val)] * size)\r\n    img = Image(plane_buffers=[buf], pix_fmt='gray', size=(w, h))\r\n    return img\r\n\r\n\r\ndef verify_frames(filename, timestamps, frame_vals=None):\r\n    from ffpyplayer.player import MediaPlayer\r\n    error = [None, ]\r\n\r\n    def callback(selector, value):\r\n        if selector.endswith('error'):\r\n            error[0] = selector, value\r\n\r\n    player = MediaPlayer(filename, callback=callback)\r\n\r\n    read_timestamps = set()\r\n    try:\r\n        i = -1\r\n        while not error[0]:\r\n            frame, val = player.get_frame()\r\n            if val == 'eof':\r\n                break\r\n            if val == 'paused':\r\n                raise ValueError('Got paused')\r\n            elif frame is None:\r\n                time.sleep(0.01)\r\n            else:\r\n                img, t = frame\r\n                print(i, t)\r\n                if i < 0:\r\n                    i += 1\r\n                    continue\r\n\r\n                print(i, t, timestamps[i])\r\n                read_timestamps.add(t)\r\n                assert math.isclose(t, timestamps[i], rel_tol=.1)\r\n\r\n                if frame_vals:\r\n                    assert frame_vals[i] == img.to_bytearray()[0][0]\r\n\r\n                i += 1\r\n    finally:\r\n        player.close_player()\r\n\r\n    if error[0] is not None:\r\n        raise Exception('{}: {}'.format(*error[0]))\r\n\r\n    assert len(timestamps) - 1 == i\r\n    assert len(read_timestamps) == i\r\n\r\n\r\ndef test_write_streams(tmp_path):\r\n    from ffpyplayer.writer import MediaWriter\r\n    from ffpyplayer.tools import get_supported_pixfmts, get_supported_framerates\r\n    from ffpyplayer.pic import Image\r\n    from ffpyplayer.tools import get_codecs\r\n    fname = str(tmp_path / 'test_video.avi')\r\n\r\n    lib_opts = {}\r\n    codec = 'rawvideo'\r\n    if 'libx264' in get_codecs(encode=True, video=True):\r\n        codec = 'libx264'\r\n        lib_opts = {'preset': 'slow', 'crf': '22'}\r\n\r\n    w, h = 640, 480\r\n    out_opts = {\r\n        'pix_fmt_in': 'rgb24', 'width_in': w, 'height_in': h,\r\n        'codec': codec, 'frame_rate': (5, 1)}\r\n\r\n    metadata = {\r\n        'title': 'Singing in the sun', 'author': 'Rat',\r\n        'genre': 'Animal sounds'}\r\n    writer = MediaWriter(fname, [out_opts] * 2, fmt='mp4',\r\n                         width_out=w/2, height_out=h/2, pix_fmt_out='yuv420p',\r\n                         lib_opts=lib_opts, metadata=metadata)\r\n\r\n    # Construct images\r\n    size = w * h * 3\r\n    buf = bytearray([int(x * 255 / size) for x in range(size)])\r\n    img = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\r\n\r\n    buf = bytearray([int((size - x) * 255 / size) for x in range(size)])\r\n    img2 = Image(plane_buffers=[buf], pix_fmt='rgb24', size=(w, h))\r\n\r\n    for i in range(20):\r\n        writer.write_frame(img=img, pts=i / 5., stream=0)  # stream 1\r\n        writer.write_frame(img=img2, pts=i / 5., stream=1)  # stream 2\r\n    writer.close()\r\n\r\n\r\n@pytest.mark.parametrize('fmt', [('mkv', 'matroska'), ('avi', 'avi')])\r\ndef test_write_correct_frame_rate(tmp_path, fmt):\r\n    from ffpyplayer.writer import MediaWriter\r\n    fname = str(tmp_path / 'test_frame.') + fmt[0]\r\n\r\n    w, h = 64, 64\r\n    out_opts = {\r\n        'pix_fmt_in': 'gray', 'width_in': w, 'height_in': h,\r\n        'codec': 'rawvideo', 'frame_rate': (2997, 100)}\r\n\r\n    writer = MediaWriter(fname, [out_opts], fmt=fmt[1])\r\n\r\n    timestamps = []\r\n    image_vals = []\r\n    for i in range(20):\r\n        timestamps.append(i / 29.97)\r\n        image_vals.append(i * 5)\r\n\r\n        writer.write_frame(\r\n            img=get_gray_image_with_val(w, h, i * 5), pts=i / 29.97, stream=0)\r\n    writer.close()\r\n\r\n    verify_frames(fname, timestamps, image_vals)\r\n\r\n\r\n@pytest.mark.parametrize('fmt', [('mkv', 'matroska'), ('avi', 'avi')])\r\ndef test_write_larger_than_frame_rate(tmp_path, fmt):\r\n    from ffpyplayer.writer import MediaWriter\r\n    fname = str(tmp_path / 'test_frame.') + fmt[0]\r\n\r\n    w, h = 64, 64\r\n    out_opts = {\r\n        'pix_fmt_in': 'gray', 'width_in': w, 'height_in': h,\r\n        'codec': 'rawvideo', 'frame_rate': (15, 1)}\r\n\r\n    writer = MediaWriter(fname, [out_opts], fmt=fmt[1])\r\n\r\n    timestamps = []\r\n    image_vals = []\r\n    for i in range(20):\r\n        timestamps.append(i)\r\n        image_vals.append(i * 5)\r\n\r\n        writer.write_frame(\r\n            img=get_gray_image_with_val(w, h, i * 5), pts=i, stream=0)\r\n    writer.close()\r\n\r\n    verify_frames(fname, timestamps, image_vals)\r\n\r\n\r\n@pytest.mark.parametrize('fmt', [('mkv', 'matroska'), ('avi', 'avi')])\r\ndef test_write_smaller_than_frame_rate(tmp_path, fmt):\r\n    from ffpyplayer.writer import MediaWriter\r\n    fname = str(tmp_path / 'test_frame.') + fmt[0]\r\n\r\n    w, h = 64, 64\r\n    out_opts = {\r\n        'pix_fmt_in': 'rgb24', 'width_in': w, 'height_in': h,\r\n        'codec': 'rawvideo', 'pix_fmt_out': 'yuv420p',\r\n        'frame_rate': (30, 1)}\r\n\r\n    writer = MediaWriter(fname, [out_opts], fmt=fmt[1])\r\n    img = get_image(w, h)\r\n\r\n    if fmt[0] == 'avi':\r\n        with pytest.raises(Exception):\r\n            for i in range(20):\r\n                writer.write_frame(img=img, pts=i / 300, stream=0)\r\n    else:\r\n        for i in range(20):\r\n            writer.write_frame(img=img, pts=i / 300, stream=0)\r\n    writer.close()\r\n"
  },
  {
    "path": "ffpyplayer/threading.pxd",
    "content": "\ninclude \"includes/ffmpeg.pxi\"\n\n\ncdef enum MT_lib:\n    SDL_MT,\n    Py_MT\n\ncdef class MTMutex(object):\n    cdef MT_lib lib\n    cdef void* mutex\n\n    cdef int lock(MTMutex self) nogil except 2\n    cdef int _lock_py(MTMutex self) nogil except 2\n    cdef int unlock(MTMutex self) nogil except 2\n    cdef int _unlock_py(MTMutex self) nogil except 2\n\ncdef class MTCond(object):\n    cdef MT_lib lib\n    cdef MTMutex mutex\n    cdef void *cond\n\n    cdef int lock(MTCond self) nogil except 2\n    cdef int unlock(MTCond self) nogil except 2\n    cdef int cond_signal(MTCond self) nogil except 2\n    cdef int _cond_signal_py(MTCond self) nogil except 2\n    cdef int cond_wait(MTCond self) nogil except 2\n    cdef int _cond_wait_py(MTCond self) nogil except 2\n    cdef int cond_wait_timeout(MTCond self, uint32_t val) nogil except 2\n    cdef int _cond_wait_timeout_py(MTCond self, uint32_t val) nogil except 2\n\ncdef class MTThread(object):\n    cdef MT_lib lib\n    cdef void* thread\n\n    cdef int create_thread(MTThread self, int_void_func func, const char *thread_name, void *arg) nogil except 2\n    cdef int wait_thread(MTThread self, int *status) nogil except 2\n\n\ncdef class MTGenerator(object):\n    cdef MT_lib mt_src\n\n    cdef int delay(MTGenerator self, int delay) nogil except 2\n    cdef lockmgr_func get_lockmgr(MTGenerator self) nogil\n\ncdef lockmgr_func get_lib_lockmgr(MT_lib lib) nogil\n"
  },
  {
    "path": "ffpyplayer/threading.pyx",
    "content": "\n__all__ = ('MTGenerator', )\n\ninclude \"includes/ff_consts.pxi\"\ninclude \"includes/inline_funcs.pxi\"\n\nfrom cpython.ref cimport PyObject\n\ncdef extern from \"Python.h\":\n    void Py_INCREF(PyObject *)\n    void Py_XINCREF(PyObject *)\n    void Py_DECREF(PyObject *)\n\nctypedef int (*int_cls_method)(void *) nogil\n\nimport traceback\n\ncdef int sdl_initialized = 0\ndef initialize_sdl():\n    '''Initializes sdl. Must be called before anything can be used.\n    It is automatically called by the modules that use SDL.\n    '''\n    global sdl_initialized\n    if sdl_initialized:\n        return\n    if SDL_Init(0):\n        raise ValueError('Could not initialize SDL - %s' % SDL_GetError())\n    sdl_initialized = 1\ninitialize_sdl()\n\n\ncdef class MTMutex(object):\n\n    def __cinit__(MTMutex self, MT_lib lib):\n        self.lib = lib\n        self.mutex = NULL\n        if lib == SDL_MT:\n            self.mutex = SDL_CreateMutex()\n            if self.mutex == NULL:\n                raise Exception('Cannot create mutex.')\n        elif lib == Py_MT:\n            import threading\n            mutex = threading.Lock()\n            self.mutex = <PyObject *>mutex\n            Py_INCREF(<PyObject *>self.mutex)\n\n    def __dealloc__(MTMutex self):\n        if self.lib == SDL_MT:\n            if self.mutex != NULL:\n                SDL_DestroyMutex(<SDL_mutex *>self.mutex)\n        elif self.lib == Py_MT:\n            Py_DECREF(<PyObject *>self.mutex)\n\n    cdef int lock(MTMutex self) nogil except 2:\n        if self.lib == SDL_MT:\n            return SDL_mutexP(<SDL_mutex *>self.mutex)\n        elif self.lib == Py_MT:\n            return self._lock_py()\n\n    cdef int _lock_py(MTMutex self) nogil except 2:\n        with gil:\n            return not (<object>self.mutex).acquire()\n\n    cdef int unlock(MTMutex self) nogil except 2:\n        if self.lib == SDL_MT:\n            return SDL_mutexV(<SDL_mutex *>self.mutex)\n        elif self.lib == Py_MT:\n            return self._unlock_py()\n\n    cdef int _unlock_py(MTMutex self) nogil except 2:\n        with gil:\n            (<object>self.mutex).release()\n        return 0\n\ncdef class MTCond(object):\n\n    def __cinit__(MTCond self, MT_lib lib):\n        self.lib = lib\n        self.mutex = MTMutex.__new__(MTMutex, lib)\n        self.cond = NULL\n        if self.lib == SDL_MT:\n            self.cond = SDL_CreateCond()\n            if self.cond == NULL:\n                raise Exception('Cannot create condition.')\n        elif self.lib == Py_MT:\n            import threading\n            cond = threading.Condition(<object>self.mutex.mutex)\n            self.cond = <PyObject *>cond\n            Py_INCREF(<PyObject *>self.cond)\n\n    def __dealloc__(MTCond self):\n        if self.lib == SDL_MT:\n            if self.cond != NULL:\n                SDL_DestroyCond(<SDL_cond *>self.cond)\n        elif self.lib == Py_MT:\n            Py_DECREF(<PyObject *>self.cond)\n\n    cdef int lock(MTCond self) nogil except 2:\n        self.mutex.lock()\n\n    cdef int unlock(MTCond self) nogil except 2:\n        self.mutex.unlock()\n\n    cdef int cond_signal(MTCond self) nogil except 2:\n        if self.lib == SDL_MT:\n            return SDL_CondSignal(<SDL_cond *>self.cond)\n        elif self.lib == Py_MT:\n            return self._cond_signal_py()\n\n    cdef int _cond_signal_py(MTCond self) nogil except 2:\n        with gil:\n            (<object>self.cond).notify()\n        return 0\n\n    cdef int cond_wait(MTCond self) nogil except 2:\n        if self.lib == SDL_MT:\n            return SDL_CondWait(<SDL_cond *>self.cond, <SDL_mutex *>self.mutex.mutex)\n        elif self.lib == Py_MT:\n            return self._cond_wait_py()\n\n    cdef int _cond_wait_py(MTCond self) nogil except 2:\n        with gil:\n            (<object>self.cond).wait()\n        return 0\n\n    cdef int cond_wait_timeout(MTCond self, uint32_t val) nogil except 2:\n        if self.lib == SDL_MT:\n            return SDL_CondWaitTimeout(<SDL_cond *>self.cond, <SDL_mutex *>self.mutex.mutex, val)\n        elif self.lib == Py_MT:\n            return self._cond_wait_timeout_py(val)\n\n    cdef int _cond_wait_timeout_py(MTCond self, uint32_t val) nogil except 2:\n        with gil:\n            (<object>self.cond).wait(val / 1000.)\n        return 0\n\ndef enterance_func(target_func, target_arg):\n    return (<int_void_func><uintptr_t>target_func)(<void *><uintptr_t>target_arg)\n\ncdef class MTThread(object):\n\n    def __cinit__(MTThread self, MT_lib lib):\n        self.lib = lib\n        self.thread = NULL\n\n    def __dealloc__(MTThread self):\n        if self.lib == Py_MT and self.thread != NULL:\n            Py_DECREF(<PyObject *>self.thread)\n\n    cdef int create_thread(MTThread self, int_void_func func, const char *thread_name, void *arg) nogil except 2:\n        if self.lib == SDL_MT:\n            with gil:\n                self.thread = SDL_CreateThread(func, thread_name, arg)\n                if self.thread == NULL:\n                    raise Exception('Cannot create thread.')\n        elif self.lib == Py_MT:\n            with gil:\n                import threading\n                thread = threading.Thread(group=None, target=enterance_func,\n                                          name=None, args=(<uintptr_t>func, <uintptr_t>arg), kwargs={})\n                self.thread = <PyObject *>thread\n                Py_INCREF(<PyObject *>self.thread)\n                thread.start()\n        return 0\n\n    cdef int wait_thread(MTThread self, int *status) nogil except 2:\n        if self.lib == SDL_MT:\n            if self.thread != NULL:\n                SDL_WaitThread(<SDL_Thread *>self.thread, status)\n        elif self.lib == Py_MT:\n            with gil:\n                (<object>self.thread).join()\n                if status != NULL:\n                    status[0] = 0\n        return 0\n\n\ncdef int_cls_method mutex_lock = <int_cls_method>MTMutex.lock\ncdef int_cls_method mutex_release = <int_cls_method>MTMutex.unlock\n\ncdef int _SDL_lockmgr_py(void ** mtx, int op) with gil:\n    cdef bytes msg\n    cdef int res = 1\n    cdef MTMutex mutex\n\n    try:\n        if op == FF_LOCK_CREATE:\n            mutex = MTMutex.__new__(MTMutex, SDL_MT)\n            Py_INCREF(<PyObject *>mutex)\n            mtx[0] = <PyObject *>mutex\n            res = 0\n        elif op == FF_LOCK_DESTROY:\n            if mtx[0] != NULL:\n                Py_DECREF(<PyObject *>mtx[0])\n            res = 0\n    except:\n        msg = traceback.format_exc().encode('utf8')\n        av_log(NULL, AV_LOG_ERROR, '%s', msg)\n    return res\n\ncdef int SDL_lockmgr(void ** mtx, int op) nogil:\n    if op == FF_LOCK_OBTAIN:\n        return not not mutex_lock(mtx[0])\n    elif op == FF_LOCK_RELEASE:\n        return not not mutex_release(mtx[0])\n    else:\n        return _SDL_lockmgr_py(mtx, op)\n\ncdef int Py_lockmgr(void ** mtx, int op) with gil:\n    cdef int res = 1\n    cdef bytes msg\n    cdef MTMutex mutex\n\n    try:\n        if op == FF_LOCK_CREATE:\n            mutex = MTMutex.__new__(MTMutex, Py_MT)\n            Py_INCREF(<PyObject *>mutex)\n            mtx[0] = <PyObject *>mutex\n            res = 0\n        elif op == FF_LOCK_OBTAIN:\n            mutex = <MTMutex>mtx[0]\n            res = not not mutex.lock() # force it to 0, or 1\n        elif op == FF_LOCK_RELEASE:\n            mutex = <MTMutex>mtx[0]\n            res = not not mutex.unlock()\n        elif op == FF_LOCK_DESTROY:\n            if mtx[0] != NULL:\n                Py_DECREF(<PyObject *>mtx[0])\n            res = 0\n    except:\n        msg = traceback.format_exc().encode('utf8')\n        av_log(NULL, AV_LOG_ERROR, '%s', msg)\n        res = 1\n    return res\n\n\ncdef lockmgr_func get_lib_lockmgr(MT_lib lib) nogil:\n    if lib == SDL_MT:\n        return SDL_lockmgr\n    elif lib == Py_MT:\n        return Py_lockmgr\n\n\ncdef class MTGenerator(object):\n\n    def __cinit__(MTGenerator self, MT_lib mt_src, **kwargs):\n        self.mt_src = mt_src\n\n    cdef int delay(MTGenerator self, int delay) nogil except 2:\n        if self.mt_src == SDL_MT:\n            SDL_Delay(delay)\n        elif self.mt_src == Py_MT:\n            with gil:\n                import time\n                time.sleep(delay / 1000.)\n        return 0\n\n    cdef lockmgr_func get_lockmgr(MTGenerator self) nogil:\n        return get_lib_lockmgr(self.mt_src)\n"
  },
  {
    "path": "ffpyplayer/tools.pyx",
    "content": "'''\nFFmpeg tools\n============\n\nModule for manipulating and finding information of FFmpeg formats, codecs,\ndevices, pixel formats and more.\n'''\n\n__all__ = (\n    'initialize_sdl_aud', 'loglevels', 'codecs_enc', 'codecs_dec', 'pix_fmts',\n    'formats_in', 'formats_out', 'set_log_callback', 'get_log_callback',\n    'set_loglevel', 'get_loglevel', 'get_codecs', 'get_fmts',\n    'get_format_codec',\n    'get_supported_framerates', 'get_supported_pixfmts', 'get_best_pix_fmt',\n    'emit_library_info',\n    'list_dshow_devices', 'encode_to_bytes', 'decode_to_unicode',\n    'convert_to_str', 'list_dshow_opts')\n\ninclude \"includes/ffmpeg.pxi\"\ninclude \"includes/inline_funcs.pxi\"\n\ncdef extern from \"stdlib.h\" nogil:\n    void *malloc(size_t)\n    void free(void *)\n\nfrom ffpyplayer.threading cimport Py_MT, MTMutex, get_lib_lockmgr, SDL_MT\nimport ffpyplayer.threading  # for sdl init\nimport re\nimport sys\nfrom functools import partial\n\ncdef int sdl_aud_initialized = 0\ndef initialize_sdl_aud():\n    '''Initializes sdl audio subsystem. Must be called before audio can be used.\n    It is automatically called by the modules that use SDL audio.\n    '''\n    global sdl_aud_initialized\n    if sdl_aud_initialized:\n        return\n\n    # Try to work around an occasional ALSA buffer underflow issue when the\n    # period size is NPOT due to ALSA resampling by forcing the buffer size.\n    if not SDL_getenv(\"SDL_AUDIO_ALSA_SET_BUFFER_SIZE\"):\n        SDL_setenv(\"SDL_AUDIO_ALSA_SET_BUFFER_SIZE\", \"1\", 0)\n\n    if SDL_InitSubSystem(SDL_INIT_AUDIO):\n        raise ValueError('Could not initialize SDL audio - %s' % SDL_GetError())\n    sdl_aud_initialized = 1\n\n\ncdef int ffmpeg_initialized = 0\ndef _initialize_ffmpeg():\n    '''Initializes ffmpeg libraries. Must be called before anything can be used.\n    Called automatically when importing this module.\n    '''\n    global ffmpeg_initialized\n    if not ffmpeg_initialized:\n        av_log_set_flags(AV_LOG_SKIP_REPEATED)\n        IF CONFIG_AVDEVICE:\n            avdevice_register_all()\n        avformat_network_init()\n        ffmpeg_initialized = 1\n_initialize_ffmpeg()\n\n\ndef _get_item0(x):\n    return x[0]\n\n'see http://ffmpeg.org/ffmpeg.html for log levels'\nloglevels = {\n    \"quiet\": AV_LOG_QUIET, \"panic\": AV_LOG_PANIC, \"fatal\": AV_LOG_FATAL,\n    \"error\": AV_LOG_ERROR, \"warning\": AV_LOG_WARNING, \"info\": AV_LOG_INFO,\n    \"verbose\": AV_LOG_VERBOSE, \"debug\": AV_LOG_DEBUG, \"trace\": AV_LOG_TRACE}\n'''A dictionary with all the available ffmpeg log levels. The keys are the loglevels\nand the values are their ffmpeg values. The lower the value, the more important\nthe log. Note, this is ooposite python where the higher the level the more important\nthe log.\n'''\n_loglevel_inverse = {v:k for k, v in loglevels.iteritems()}\n\ncdef object _log_callback = None\ncdef MTMutex _log_mutex= MTMutex(SDL_MT)\ncdef int log_level = AV_LOG_WARNING\ncdef int print_prefix = 1\n\ncdef void gil_call_callback(char *line, int level):\n    cdef object callback\n    callback = _log_callback\n    if callback is None:\n        return\n    callback(tcode(line), _loglevel_inverse[level])\n\ncdef void call_callback(char *line, int level) nogil:\n    with gil:\n        gil_call_callback(line, level)\n\ncdef void _log_callback_func(void* ptr, int level, const char* fmt, va_list vl) noexcept nogil:\n    cdef char line[2048]\n    if fmt == NULL or level > log_level:\n        return\n\n    av_log_format_line(ptr, level, fmt, vl, line, sizeof(line), &print_prefix)\n    call_callback(line, level)\n\ndef _logger_callback(logger_dict, message, level):\n    message = message.strip()\n    if message:\n        logger_dict[level]('FFPyPlayer: {}'.format(message))\n\ndef set_log_callback(object callback=None, logger=None, int default_only=False):\n    '''Sets a callback to be used by ffmpeg when emitting logs.\n    This function is thread safe.\n\n    See also :func:`set_loglevel`.\n\n    :Parameters:\n\n        `callback`: callable or None\n            A function which will be called with strings to be printed. It takes\n            two parameters: ``message`` and ``level``. ``message`` is the string\n            to be printed. ``level`` is the log level of the string and is one\n            of the keys of the :attr:`loglevels` dict. If ``callback`` and ``logger``\n            are None, the default ffmpeg log callback will be set, which prints to stderr.\n            Defaults to None.\n        `logger`: a python logger object or None\n            If ``callback`` is None and this is not None, this logger object's\n            ``critical``, ``error``, ``warning``, ``info``, ``debug``, and ``trace``\n            methods will be called directly to forward ffmpeg's log outputs.\n\n            .. note::\n\n                If the logger doesn't have a trace method, the trace output will be\n                redirected to debug. However, the trace level outputs a lot of logs.\n\n        `default_only`: bool\n            If True, when ``callback`` or ``logger`` are not ``None``, they\n            will only be set if a callback or logger has not already been set.\n\n    :returns:\n\n        The previous callback set (None, if it has not been set).\n\n    >>> from ffpyplayer.tools import set_log_callback, loglevels\n    >>> loglevel_emit = 'error' # This and worse errors will be emitted.\n    >>> def log_callback(message, level):\n    ...     message = message.strip()\n    ...     if message and loglevels[level] <= loglevels[loglevel_emit]:\n    ...         print '%s: %s' %(level, message.strip())\n    >>> set_log_callback(log_callback)\n    ...\n    >>> set_log_callback(None)\n    '''\n    global _log_callback\n    if callback is not None and not callable(callback):\n        raise Exception('Log callback needs to be callable.')\n\n    if callback is None and logger is not None:\n        logger_dict = {\n            'quiet': logger.critical, 'panic': logger.critical,\n            'fatal': logger.critical, 'error': logger.error, 'warning': logger.warning,\n            'info': logger.info, 'verbose': logger.debug, 'debug': logger.debug,\n            'trace': getattr(logger, 'trace', logger.debug)}\n        callback = partial(_logger_callback, logger_dict)\n\n    _log_mutex.lock()\n    old_callback = _log_callback\n    if callback is None:\n        av_log_set_callback(&av_log_default_callback)\n        _log_callback = None\n    elif not default_only or old_callback is None:\n        av_log_set_callback(&_log_callback_func)\n        _log_callback = callback\n    _log_mutex.unlock()\n    return old_callback\n\ndef get_log_callback():\n    '''Returns the last log callback set, or None if it has not been set.\n    See :func:`set_log_callback`.\n    '''\n    _log_mutex.lock()\n    old_callback = _log_callback\n    _log_mutex.unlock()\n    return old_callback\n\n\ndef set_loglevel(loglevel):\n    '''This sets the global FFmpeg log level. less important log levels are filtered\n    and not passsed on to the logger or callback set by :func:`set_log_callback`.\n    It also set the loglevel of FFmpeg if not callback or logger is set.\n\n    The global log level, if not set, defaults to ``'warning'``.\n\n    :Parameters:\n\n        `loglevel`: str\n            The log level. Can be one of the keys of :attr:`loglevels`.\n    '''\n    cdef int level\n    global log_level\n    if loglevel not in loglevels:\n        raise ValueError('Invalid loglevel {}'.format(loglevel))\n    level = loglevels[loglevel]\n    _log_mutex.lock()\n    av_log_set_level(level)\n    log_level = level\n    _log_mutex.unlock()\nset_loglevel(_loglevel_inverse[log_level])\n\ndef get_loglevel():\n    '''Returns the log level set with :func:`set_loglevel`, or the default level if not\n    set. It is one of the keys of :attr:`loglevels`.\n    '''\n    cdef int level\n    _log_mutex.lock()\n    level = log_level\n    _log_mutex.unlock()\n    return _loglevel_inverse[level]\n\n\ncpdef get_codecs(\n        int encode=False, int decode=False, int video=False, int audio=False,\n        int data=False, int subtitle=False, int attachment=False, other=False):\n    '''Returns a list of codecs (e.g. h264) that is available by ffpyplayer for\n    encoding or decoding and matches the media types, e.g. video or audio.\n\n    The parameters determine which codecs is included in the result. The parameters\n    all default to False.\n\n    :Parameters:\n\n        `encode`: bool\n            If True, includes the encoding codecs in the result. Defaults to False.\n        `decode`: bool\n            If True, includes the decoding codecs in the result. Defaults to False.\n        `video`: bool\n            If True, includes the video codecs in the result. Defaults to False.\n        `audio`: bool\n            If True, includes the audio codecs in the result. Defaults to False.\n        `data`: bool\n            If True, includes the (continuous) side data codecs in the result. Defaults to False.\n        `subtitle`: bool\n            If True, includes the subtitle codecs in the result. Defaults to False.\n        `attachment`: bool\n            If True, includes the (sparse) data attachment codecs in the result. Defaults to False.\n        `other`: bool\n            If True, returns all the codec media types.\n\n    :returns:\n\n        A sorted list of the matching codec names.\n    '''\n    cdef list codecs = []\n    cdef AVCodec *codec = NULL\n    cdef void *iter_codec = NULL\n    codec = av_codec_iterate(&iter_codec)\n\n    while codec != NULL:\n        if ((encode and av_codec_is_encoder(codec) or\n             decode and av_codec_is_decoder(codec)) and\n            (video and codec.type == AVMEDIA_TYPE_VIDEO or\n             audio and codec.type == AVMEDIA_TYPE_AUDIO or\n             data and codec.type == AVMEDIA_TYPE_DATA or\n             subtitle and codec.type == AVMEDIA_TYPE_SUBTITLE or\n             attachment and codec.type == AVMEDIA_TYPE_ATTACHMENT or\n             other)):\n            codecs.append(tcode(codec.name))\n        codec = av_codec_iterate(&iter_codec)\n    return sorted(codecs)\n\ncodecs_enc = get_codecs(encode=True, video=True)\n'''A list of all the codecs available for encoding video. '''\ncodecs_dec = get_codecs(decode=True, video=True, audio=True)\n'''A list of all the codecs available for decoding video and audio. '''\n\ncdef list list_pixfmts():\n    cdef list fmts = []\n    cdef const AVPixFmtDescriptor *desc = NULL\n    desc = av_pix_fmt_desc_next(desc)\n\n    while desc != NULL:\n        fmts.append(tcode(desc.name))\n        desc = av_pix_fmt_desc_next(desc)\n    return sorted(fmts)\n\npix_fmts = list_pixfmts()\n'''A list of all the pixel formats available to ffmpeg. '''\n\ncpdef get_fmts(int input=False, int output=False):\n    '''Returns the formats available in FFmpeg.\n\n    :Parameters:\n\n        `input`: bool\n            If True, also includes input formats in the result. Defaults to False\n        `output`: bool\n            If True, also includes output formats in the result. Defaults to False\n\n    :returns:\n\n        A 3-tuple of 3 lists, ``formats``, ``full_names``, and ``extensions``.\n        Each of the three lists are of identical length.\n\n        `formats`: list\n            A list of the names of the formats.\n        `full_names`: list\n            A list of the corresponding human readable names for each of the\n            formats. Can be the empty string if none is available.\n        `extensions`: list\n            A list of the extensions associated with the corresponding formats.\n            Each item is a (possibly empty) list of extensions names.\n    '''\n    cdef list fmts = [], full_names = [], exts = []\n    cdef AVOutputFormat *ofmt = NULL\n    cdef AVInputFormat *ifmt = NULL\n    cdef void *ifmt_opaque = NULL\n    cdef void *ofmt_opaque = NULL\n    cdef object names, full_name, ext\n\n    if output:\n        ofmt = av_muxer_iterate(&ofmt_opaque)\n        while ofmt != NULL:\n            if ofmt.name != NULL:\n                names = tcode(ofmt.name).split(',')\n                full_name = tcode(ofmt.long_name) if ofmt.long_name != NULL else ''\n                ext = tcode(ofmt.extensions).split(',') if ofmt.extensions != NULL else []\n\n                fmts.extend(names)\n                full_names.extend([full_name, ] * len(names))\n                exts.extend([ext, ] * len(names))\n            ofmt = av_muxer_iterate(&ofmt_opaque)\n\n    if input:\n        ifmt = av_demuxer_iterate(&ifmt_opaque)\n        while ifmt != NULL:\n            if ifmt.name != NULL:\n                names = tcode(ifmt.name).split(',')\n                full_name = tcode(ifmt.long_name) if ifmt.long_name != NULL else ''\n                ext = tcode(ifmt.extensions).split(',') if ifmt.extensions != NULL else []\n\n                fmts.extend(names)\n                full_names.extend([full_name, ] * len(names))\n                exts.extend([ext, ] * len(names))\n            ifmt = av_demuxer_iterate(&ifmt_opaque)\n\n    exts = [x for (y, x) in sorted(zip(fmts, exts), key=_get_item0)]\n    full_names = [x for (y, x) in sorted(zip(fmts, full_names), key=_get_item0)]\n    fmts = sorted(fmts)\n    return fmts, full_names, exts\n\nformats_in = get_fmts(input=True)[0]\n'''A list of all the formats (e.g. file formats) available for reading. '''\nformats_out = get_fmts(output=True)[0]\n'''A list of all the formats (e.g. file formats) available for writing. '''\n\ndef get_format_codec(filename=None, fmt=None):\n    '''Returns the best codec associated with the file format. The format\n    can be provided using either ``filename`` or ``fmt``.\n\n    :Parameters:\n        `filename`: str or None\n            The output filename. If provided, the extension of the filename\n            is used to guess the format.\n        `fmt`: str or None.\n            The format to use. Can be one of :attr:`ffpyplayer.tools.formats_out`.\n\n    :returns:\n\n        str:\n            The name from :attr:`ffpyplayer.tools.codecs_enc`\n            of the best codec that can be used with this format.\n\n    For example:\n\n    .. code-block:: python\n\n        >>> get_format_codecs('test.png')\n        'mjpeg'\n        >>> get_format_codecs('test.jpg')\n        'mjpeg'\n        >>> get_format_codecs('test.mkv')\n        'libx264'\n        >>> get_format_codecs(fmt='h264')\n        'libx264'\n    '''\n    cdef int res\n    cdef char *format_name = NULL\n    cdef char *name = NULL\n    cdef const AVCodec *codec_desc = NULL\n    cdef AVFormatContext *fmt_ctx = NULL\n    cdef char msg[256]\n    cdef AVCodecID codec_id\n\n    if fmt:\n        fmt = fmt.encode('utf8')\n        format_name = fmt\n    if filename:\n        filename = filename.encode('utf8')\n        name = filename\n\n    res = avformat_alloc_output_context2(&fmt_ctx, NULL, format_name, name)\n    if res < 0 or fmt_ctx == NULL or fmt_ctx.oformat == NULL:\n        raise Exception('Failed to find format: ' + tcode(emsg(res, msg, sizeof(msg))))\n\n    codec_id = fmt_ctx.oformat.video_codec\n    codec_desc = avcodec_find_encoder(codec_id)\n    if codec_desc == NULL:\n        raise Exception('Default codec not found for format')\n    return tcode(codec_desc.name)\n\n\ndef get_supported_framerates(codec_name, rate=()):\n    '''Returns the supported frame rates for encoding codecs. If a desired rate is\n    provided, it also returns the closest valid rate.\n\n    :Parameters:\n\n        `codec_name`: str\n            The name of a encoding codec.\n        `rate`: 2-tuple of ints, or empty tuple.\n            If provided, a 2-tuple where the first element is the numerator,\n            and the second the denominator of the frame rate we wish to use. E.g.\n            (2997, 100) means a frame rate of 29.97.\n\n    :returns:\n\n        (list of 2-tuples, or empty list):\n            If there are no restrictions on the frame rate (i.e. all rates are valid)\n            it returns a empty list, otherwise it returns a list with the valid\n            frame rates. If `rate` is provided and there are restrictions on the frame\n            rates, the closest frame rate is the zero'th element in the list.\n\n    For example:\n\n    .. code-block:: python\n\n        >>> print get_supported_framerates('mpeg1video')\n        [(24000, 1001), (24, 1), (25, 1), (30000, 1001), (30, 1), (50, 1),\n        (60000, 1001), (60, 1), (15, 1), (5, 1), (10, 1), (12, 1), (15, 1)]\n\n        >>> print get_supported_framerates('mpeg1video', (2997, 100))\n        [(30000, 1001), (24000, 1001), (24, 1), (25, 1), (30, 1), (50, 1),\n        (60000, 1001), (60, 1), (15, 1), (5, 1), (10, 1), (12, 1), (15, 1)]\n    '''\n    cdef AVRational rate_struct\n    cdef list rate_list = []\n    cdef int i = 0\n    cdef bytes name = codec_name if isinstance(codec_name, bytes) else codec_name.encode('utf8')\n    cdef AVCodec *codec = avcodec_find_encoder_by_name(name)\n    if codec == NULL:\n        raise Exception('Encoder codec %s not available.' % codec_name)\n    if codec.supported_framerates == NULL:\n        return rate_list\n\n    while codec.supported_framerates[i].den:\n        rate_list.append((codec.supported_framerates[i].num, codec.supported_framerates[i].den))\n        i += 1\n    if rate:\n        rate_struct.num, rate_struct.den = rate\n        i = av_find_nearest_q_idx(rate_struct, codec.supported_framerates)\n        rate = rate_list[i]\n        del rate_list[i]\n        rate_list.insert(0, rate)\n    return rate_list\n\ndef get_supported_pixfmts(codec_name, pix_fmt=''):\n    '''Returns the supported pixel formats for encoding codecs. If a desired format\n    is provided, it also returns the closest format (i.e. the format with minimum\n    conversion loss).\n\n    :Parameters:\n\n        `codec_name`: str\n            The name of a encoding codec.\n        `pix_fmt`: str\n            If not empty, the name of a pixel format we wish to use with this codec,\n            e.g. 'rgb24'.\n\n    :returns:\n\n        (list of pixel formats, or empty list):\n            If there are no restrictions on the pixel formats (i.e. all the formats\n            are valid) it returns a empty list, otherwise it returns a list with the\n            valid formats. If pix_fmt is not empty and there are restrictions to the\n            formats, the closest format which results in the minimum loss when converting\n            will be returned as the zero'th element in the list.\n\n    For example:\n\n    .. code-block:: python\n\n        >>> print get_supported_pixfmts('ffv1')\n        ['yuv420p', 'yuva420p', 'yuva422p', 'yuv444p', 'yuva444p', 'yuv440p', ...\n        'gray16le', 'gray', 'gbrp9le', 'gbrp10le', 'gbrp12le', 'gbrp14le']\n\n        >>> print get_supported_pixfmts('ffv1', 'gray')\n        ['gray', 'yuv420p', 'yuva420p', 'yuva422p', 'yuv444p', 'yuva444p', ...\n        'gray16le', 'gbrp9le', 'gbrp10le', 'gbrp12le', 'gbrp14le']\n    '''\n    cdef AVPixelFormat fmt\n    cdef bytes name = codec_name if isinstance(codec_name, bytes) else codec_name.encode('utf8')\n    cdef bytes fmt_b = pix_fmt if isinstance(pix_fmt, bytes) else pix_fmt.encode('utf8')\n    cdef list fmt_list = []\n    cdef int i = 0, loss = 0, has_alpha = 0\n    cdef AVCodec *codec = avcodec_find_encoder_by_name(name)\n    if codec == NULL:\n        raise Exception('Encoder codec %s not available.' % codec_name)\n    if pix_fmt and av_get_pix_fmt(fmt_b) == AV_PIX_FMT_NONE:\n        raise Exception('Pixel format not recognized.')\n    if codec.pix_fmts == NULL:\n        return fmt_list\n\n    while codec.pix_fmts[i] != AV_PIX_FMT_NONE:\n        fmt_list.append(tcode(av_get_pix_fmt_name(codec.pix_fmts[i])))\n        i += 1\n    if pix_fmt:\n        # XXX: fix this to check if NULL (although kinda already checked above)\n        has_alpha = av_pix_fmt_desc_get(av_get_pix_fmt(fmt_b)).nb_components % 2 == 0\n        fmt = avcodec_find_best_pix_fmt_of_list(codec.pix_fmts, av_get_pix_fmt(fmt_b),\n                                                has_alpha, &loss)\n        i = fmt_list.index(tcode(av_get_pix_fmt_name(fmt)))\n        pix = fmt_list[i]\n        del fmt_list[i]\n        fmt_list.insert(0, pix)\n    return fmt_list\n\ndef get_best_pix_fmt(pix_fmt, pix_fmts):\n    '''Returns the best pixel format with the least conversion loss from the\n    original pixel format, given a list of potential pixel formats.\n\n    :Parameters:\n\n        `pix_fmt`: str\n            The name of a original pixel format.\n        `pix_fmts`: list-type of strings\n            A list of possible pixel formats from which the best will be chosen.\n\n    :returns:\n\n        The pixel format with the least conversion loss.\n\n    .. note::\n\n        The returned pixel format seems to be somewhat sensitive to the order\n        of the input pixel formats. Higher quality pixel formats should therefore\n        be at the beginning of the list.\n\n\n    For example:\n\n    .. code-block:: python\n\n        >>> get_best_pix_fmt('yuv420p', ['rgb24', 'rgba', 'yuv444p', 'gray'])\n        'rgb24'\n        >>> get_best_pix_fmt('gray', ['rgb24', 'rgba', 'yuv444p', 'gray'])\n        'gray'\n        >>> get_best_pix_fmt('rgb8', ['rgb24', 'yuv420p', 'rgba', 'yuv444p', 'gray'])\n        'rgb24'\n    '''\n    cdef AVPixelFormat fmt, fmt_src\n    cdef bytes fmt_src_b = pix_fmt if isinstance(pix_fmt, bytes) else pix_fmt.encode('utf8')\n    cdef bytes fmt_b\n    cdef int i = 0, loss = 0, has_alpha = 0\n    cdef AVPixelFormat *fmts = NULL\n\n    if not pix_fmt or not pix_fmts:\n        raise ValueError('Invalid arguments {}, {}'.format(pix_fmt, pix_fmts))\n    fmt_src = av_get_pix_fmt(fmt_src_b)\n    if fmt_src == AV_PIX_FMT_NONE:\n        raise Exception('Pixel format {} not recognized.'.format(pix_fmt))\n\n    fmts = <AVPixelFormat *>malloc(sizeof(AVPixelFormat) * (len(pix_fmts) + 1))\n    if fmts == NULL:\n        raise MemoryError()\n\n    try:\n        fmts[len(pix_fmts)] = AV_PIX_FMT_NONE\n\n        for i, fmt_s in enumerate(pix_fmts):\n            fmt_b = fmt_s if isinstance(fmt_s, bytes) else fmt_s.encode('utf8')\n            fmts[i] = av_get_pix_fmt(fmt_b)\n            if fmts[i] == AV_PIX_FMT_NONE:\n                raise Exception('Pixel format {} not recognized.'.format(fmt_s))\n\n        has_alpha = av_pix_fmt_desc_get(fmt_src).nb_components % 2 == 0\n        fmt = avcodec_find_best_pix_fmt_of_list(fmts, fmt_src, has_alpha, &loss)\n    finally:\n        free(fmts)\n\n    return tcode(av_get_pix_fmt_name(fmt))\n\ndef emit_library_info():\n    '''Prints to the ffmpeg log all the ffmpeg library's versions and configure\n    options.\n    '''\n    print_all_libs_info(INDENT|SHOW_CONFIG,  AV_LOG_INFO)\n    print_all_libs_info(INDENT|SHOW_VERSION, AV_LOG_INFO)\n\ndef _dshow_log_callback(log, message, level):\n    message = message.encode('utf8')\n\n    if not log:\n        log.append((message, level))\n        return\n\n    last_msg, last_level = log[-1]\n    if last_level == level:\n        log[-1] = last_msg + message, level\n    else:\n        log.append((message, level))\n\n\ncpdef int list_dshow_opts(list log, bytes stream, bytes option) except 1:\n    cdef AVFormatContext *fmt = NULL\n    cdef AVDictionary* opts = NULL\n    cdef AVInputFormat *ifmt\n    cdef object old_callback\n    cdef int level\n    cdef list temp_log = []\n    cdef bytes item\n    global log_level\n\n    ifmt = av_find_input_format(b\"dshow\")\n    if ifmt == NULL:\n        raise Exception('Direct show not found.')\n\n    av_dict_set(&opts, option, b\"true\", 0)\n    _log_mutex.lock()\n    old_callback = set_log_callback(partial(_dshow_log_callback, temp_log))\n    level = log_level\n\n    av_log_set_level(AV_LOG_TRACE)\n    log_level = AV_LOG_TRACE\n    avformat_open_input(&fmt, stream, ifmt, &opts)\n\n    av_log_set_level(level)\n    log_level = level\n    set_log_callback(old_callback)\n\n    _log_mutex.unlock()\n    avformat_close_input(&fmt)\n    av_dict_free(&opts)\n\n    for item, l in temp_log:\n        for line in item.splitlines():\n            log.append((line, l))\n    return 0\n\ndef list_dshow_devices():\n    '''Returns a list of the dshow devices available.\n\n    :returns:\n\n        `3-tuple`: A 3-tuple, of (`video`, `audio`, `names`)\n\n            `video`: dict\n                A dict of all the direct show **video** devices. The keys\n                of the dict are the unique names of the available direct show devices. The values\n                are a list of the available configurations for that device. Each\n                element in the list has the following format:\n                ``(pix_fmt, codec_fmt, (frame_width, frame_height), (min_framerate, max_framerate))``\n            `audio`: dict\n                A dict of all the direct show **audio** devices. The keys\n                of the dict are the unique names of the available direct show devices. The values\n                are a list of the available configurations for that device. Each\n                element in the list has the following format:\n                ``((min_num_channels, min_num_channels), (min_bits, max_bits), (min_rate, max_rate))``.\n            `names`: dict\n                A dict mapping the unique names of the video and audio devices to\n                a more human friendly (possibly non-unique) name. Either of these\n                names can be used when opening the device. However, if using the non-unique\n                name, it's not guarenteed which of the devices sharing the name will be opened.\n\n\n    For example:\n\n    .. code-block:: python\n\n        >>> from ffpyplayer.player import MediaPlayer\n        >>> from ffpyplayer.tools import list_dshow_devices\n        >>> import time, weakref\n        >>> dev = list_dshow_devices()\n        >>> print dev\n        ({'@device_pnp_...223196\\\\global': [('bgr24', '', (160, 120), (5, 30)),\n        ('bgr24', '', (176, 144), (5, 30)), ('bgr24', '', (320, 176), (5, 30)),\n        ('bgr24', '', (320, 240), (5, 30)), ('bgr24', '', (352, 288), (5, 30)),\n        ...\n        ('yuv420p', '', (320, 240), (5, 30)), ('yuv420p', '', (352, 288), (5, 30))],\n        '@device_pnp_...223196\\\\global': [('bgr24', '', (160, 120), (30, 30)),\n        ...\n        ('yuyv422', '', (352, 288), (30, 30)),\n        ('yuyv422', '', (640, 480), (30, 30))]},\n        {'@device_cm_...2- HD Webcam C615)': [((1, 2), (8, 16), (11025, 44100))],\n        '@device_cm_...HD Webcam C615)': [((1, 2), (8, 16), (11025, 44100))]},\n        {'@device_cm_...- HD Webcam C615)': 'Microphone (2- HD Webcam C615)',\n         '@device_cm_...2- HD Webcam C615)': 'Microphone (3- HD Webcam C615)',\n        ...\n         '@device_pnp...223196\\\\global': 'HD Webcam C615',\n         '@device_pnp...223196\\\\global': 'Laptop Integrated Webcam'})\n\n    See :ref:`dshow-example` for a full example.\n    '''\n    cdef list res = []\n    cdef dict video = {}, audio = {}, curr = None\n    cdef object last\n    cdef bytes msg, msg2\n    cdef dict name_map = {}\n\n    # list devices\n    list_dshow_opts(res, b'dummy', b'list_devices')\n    # primary dev name\n    pname = re.compile(' *\\[dshow *@ *[\\w]+\\] *\"(.+)\" *\\\\((video|audio)\\\\) *')\n    # alternate dev name\n    apname = re.compile(' *\\[dshow *@ *[\\w]+\\] *Alternative name *\"(.+)\" *')\n    m = None\n    for msg, level in res:\n        message = msg.decode('utf8')\n\n        # do we match a primary name - i.e. next device\n        m_temp = pname.match(message)\n        if m_temp:\n            m = m_temp\n            curr = audio if m.group(2) == 'audio' else video\n            curr[m.group(1)] = []\n            name_map[m.group(1)] = m.group(1)\n            continue\n\n        m_temp = apname.match(message)\n        # if we match alternate name and already have primary, then we're adding it\n        if m_temp and m:\n            curr[m_temp.group(1)] = []\n            name_map[m_temp.group(1)] = m.group(1)\n            del curr[m.group(1)]\n            del name_map[m.group(1)]\n        else:\n            msg2 = message.encode('utf8')\n            av_log(NULL, loglevels[level], '%s', msg2)\n\n        m = None\n\n    # list video devices options\n    vid_opts = re.compile(' *\\[dshow *@ *[\\w]+\\] +(pixel_format|vcodec)=([\\w]+) +min +s=\\d+x\\d+ +fps=(\\d+)\\\n +max +s=(\\d+)x(\\d+) +fps=(\\d+).*')\n    pheader1 = re.compile(' *\\[dshow *@ *[\\w]+\\] *(?:Pin|Selecting pin) (?:\"Capture\"|\"Output\"|Capture|Output).*')\n    pheader2 = re.compile(' *\\[dshow *@ *[\\w]+\\] *DirectShow (?:video|audio) (?:only )?device options.*')\n    for video_stream in video:\n        res = []\n        list_dshow_opts(res, (\"video=%s\" % video_stream).encode('utf8'), b'list_options')\n\n        for msg, level in res:\n            message = msg.decode('utf8')\n            opts = vid_opts.match(message)\n\n            if not opts:\n                if not pheader1.match(message) and not pheader2.match(message):\n                    av_log(NULL, loglevels[level], '%s', msg)\n                continue\n\n            g1, g2, g3, g4, g5, g6 = opts.groups()\n            if g1 == 'pixel_format':\n                item = g2, \"\", (int(g4), int(g5)), (int(g3), int(g6))\n            else:\n                item = \"\", g2, (int(g4), int(g5)), (int(g3), int(g6))\n\n            if item not in video[video_stream]:\n                video[video_stream].append(item)\n\n        video[video_stream] = sorted(video[video_stream])\n\n    # list audio devices options\n    paud_opts = re.compile(' *\\[dshow *@ *[\\w]+\\] +ch= *(\\d+), +bits= *(\\d+),\\\n +rate= *(\\d+).*')\n    for audio_stream in audio:\n        res = []\n        list_dshow_opts(res, (\"audio=%s\" % audio_stream).encode('utf8'), b'list_options')\n        for msg, level in res:\n            message = msg.decode('utf8')\n            mopts = paud_opts.match(message)\n\n            if mopts:\n                opts = (int(mopts.group(1)), int(mopts.group(2)), int(mopts.group(3)))\n                if opts not in audio[audio_stream]:\n                    audio[audio_stream].append(opts)\n            elif (not pheader1.match(message)) and (not pheader2.match(message)):\n                av_log(NULL, loglevels[level], '%s', msg)\n        audio[audio_stream] = sorted(audio[audio_stream])\n\n    return video, audio, name_map\n\n\ncdef object encode_text(object item, int encode):\n    if isinstance(item, basestring):\n        if encode:\n            return item.encode('utf8')\n        return item.decode('utf8')\n\n    if isinstance(item, dict):\n        for k, v in item.items():\n            item[k] = encode_text(v, encode)\n        return item\n\n    try:\n        iter(item)\n    except TypeError:\n        return item\n\n    return item.__class__((encode_text(i, encode) for i in item))\n\ndef encode_to_bytes(item):\n    '''Takes the item and walks it recursively whether it's a string, int, iterable,\n    etc. and encodes all the strings to utf-8.\n\n    :Parameters:\n\n        `item`: anything\n            The object to be walked and encoded.\n\n    :returns:\n\n        An object identical to the ``item``, but with all strings encoded to utf-8.\n    '''\n    return encode_text(item, 1)\n\ndef decode_to_unicode(item):\n    '''Takes the item and walks it recursively whether it's a string, int, iterable,\n    etc. and encodes all the strings to utf-8.\n\n    :Parameters:\n\n        `item`: anything\n            The object to be walked and encoded.\n\n    :returns:\n\n        An object identical to the ``item``, but with all strings encoded to utf-8.\n    '''\n    return encode_text(item, 0)\n\ndef convert_to_str(item):\n    '''Takes the item and walks it recursively whether it's a string, int, iterable,\n    etc. and encodes all the strings to utf-8.\n\n    :Parameters:\n\n        `item`: anything\n            The object to be walked and encoded.\n\n    :returns:\n\n        An object identical to the ``item``, but with all strings encoded to utf-8.\n    '''\n    return encode_text(item, False)\n"
  },
  {
    "path": "ffpyplayer/writer.pxd",
    "content": "include 'includes/ffmpeg.pxi'\n\n\ncdef class MediaWriter(object):\n    cdef AVFormatContext *fmt_ctx\n    cdef MediaStream *streams\n    cdef int n_streams\n    cdef list config\n    cdef AVDictionary *format_opts\n    cdef int64_t total_size\n    cdef int closed\n\n    cpdef close(self)\n    cdef void clean_up(MediaWriter self) nogil\n\n\ncdef struct MediaStream:\n    # pointer to the stream to which we're adding frames.\n    AVStream *av_stream\n    int index\n    AVCodec *codec\n    AVCodecContext *codec_ctx\n    # codec used to encode video\n    AVCodecID codec_id\n    # the size of the frame passed in\n    int width_in\n    int width_out\n    # the size of the frame actually written to disk\n    int height_in\n    int height_out\n    # The denominator of the frame rate of the stream\n    int den\n    # The numerator of the frame rate of the stream\n    int num\n    # the pixel format of the frame passed in\n    AVPixelFormat pix_fmt_in\n    # the pixel format of the frame actually written to disk\n    # if it's -1 (AV_PIX_FMT_NONE) then input will be used. '''\n    AVPixelFormat pix_fmt_out\n\n    # The frame in which the final image to be written to disk is held, when we\n    # need to convert.\n    AVFrame *av_frame\n    SwsContext *sws_ctx\n    int count\n    int64_t pts\n    int sync_fmt\n\n    AVDictionary *codec_opts\n"
  },
  {
    "path": "ffpyplayer/writer.pyx",
    "content": "'''\nFFmpeg based media writer\n=========================\n\nA FFmpeg based python media writer. See :class:`MediaWriter` for details.\nCurrently writes only video.\n'''\n\n__all__ = ('MediaWriter', )\n\ninclude \"includes/inline_funcs.pxi\"\n\ncdef extern from \"string.h\" nogil:\n    void *memset(void *, int, size_t)\n\ncdef extern from \"stdlib.h\" nogil:\n    void *malloc(size_t)\n    void free(void *)\n\ncdef extern from \"math.h\" nogil:\n    double floor(double)\n\ncdef extern from \"errno.h\" nogil:\n    int ENOENT\n    int EAGAIN\n\nfrom ffpyplayer.pic cimport Image\n\nimport ffpyplayer.tools  # required to init ffmpeg\nfrom ffpyplayer.tools import encode_to_bytes, convert_to_str\nfrom copy import deepcopy\nfrom ffpyplayer.tools import get_supported_framerates, get_supported_pixfmts\n\nDEF VSYNC_PASSTHROUGH = 0\nDEF VSYNC_CFR = 1\nDEF VSYNC_VFR = 2\nDEF VSYNC_DROP = 0xff\n\ncdef int AV_ENOENT = ENOENT if ENOENT < 0 else -ENOENT\ncdef int AV_EAGAIN = EAGAIN if EAGAIN < 0 else -EAGAIN\n\n\ncdef class MediaWriter(object):\n    '''An FFmpeg based media writer class. Currently only supports video.\n\n    With this class one can write images frames stored in many different pixel\n    formats into a multi-stream video file using :meth:`write_frame`. All FFmpeg\n    codecs and pixel formats are supported.\n\n    :Parameters:\n\n        `filename`: str\n            The filename of the media file to create. Will be encoded using utf8\n            berfore passing to FFmpeg.\n        `streams`: list of dicts\n            A list of streams to create in the file. ``streams``\n            is a list of dicts, where each dict configures the corresponding stream.\n            The keywords listed below are available. One can also specify default\n            values for the keywords for all streams using ``kwargs``. Keywords also\n            found in ``streams`` will overwrite those in ``kwargs``:\n\n                `pix_fmt_in`: str\n                    The pixel format of the :class:`~ffpyplayer.pic.Image`\n                    to be passed to :meth:`write_frame` for this stream. Can be one of\n                    :attr:`ffpyplayer.tools.pix_fmts`.\n                `width_in`: int\n                    The width of the :class:`ffpyplayer.pic.Image` that will be\n                    passed to :meth:`write_frame` for this stream.\n                `height_in`: int\n                    The height of the :class:`ffpyplayer.pic.Image` that will be\n                    passed to :meth:`write_frame` for this stream.\n                `pix_fmt_out`: str\n                    The pixel format in which frames will be\n                    written to the file for this stream. Can be one of\n                    :attr:`ffpyplayer.tools.pix_fmts`. Defaults to ``pix_fmt_in``\n                    if not provided. Not every pixel format is supported for each\n                    encoding codec, see :func:`~ffpyplayer.tools.get_supported_pixfmts`\n                    for which pixel formats are supported for ``codec``.\n                `width_out`: int\n                    The width at which frames will be written to the file for this\n                    stream. Defaults to ``width_in`` if not provided.\n                `height_out`: int\n                    The height at which frames will be written to the file for this\n                    stream. Defaults to ``height_in`` if not provided.\n                `codec`: str\n                    The codec used to write the frames to the file. Can be one of\n                    the encoding codecs in :attr:`ffpyplayer.tools.codecs_enc`.\n\n                    If not provided, it defaults to the default best codec for the format\n                    provided in ``fmt`` or guessed from the ``filename``.\n                    See :func:`ffpyplayer.tools.get_format_codecs`\n                `frame_rate`: 2-tuple of ints\n                    A 2-tuple of ints representing the frame rate to be used when writing\n                    the file. The first element is the numerator, while the second is the\n                    denuminator of a ratio describing the rate. E.g. (2997, 100) describes\n                    29.97 fps.\n\n                    The timestamps of the frames written using :meth:`write_frame` do\n                    not necessarily need to be multiples of the frame rate because they might be\n                    forced to matching timestamps if required. Not every frame rate is\n                    supported for each encoding codec, see\n                    :func:`ffpyplayer.tools.get_supported_framerates` for which frame\n                    rates are supported for ``codec``.\n\n        `fmt`: str\n            The format to use for the output. Can be one of\n            :attr:`ffpyplayer.tools.formats_out`. Defaults to empty string.\n            If not provided, ``filename`` will be used determine the format,\n            otherwise this arg will be used.\n        `lib_opts`: dict or list of dicts\n            A dictionary of options that will be passed\n            to the ffmpeg libraries, codecs, sws, and formats when opening them.\n            This accepts most of the options that can be passed to ffmpeg libraries.\n            See below for examples. Both the keywords and values must be strings.\n            It can be passed a dict in which case it'll be applied to all the streams\n            or a list containing a dict for each stream.\n        `metadata`: dict or list of dicts\n            Metadata that will be written to the streams, if\n            supported by the stream. See below for examples. Both the keywords and\n            values must be strings. It can be passed a dict in which case it'll be\n            applied to all the streams or a list containing a dict for each stream.\n            If (these) metadata is not supported, it will silently fail to write them.\n        `overwrite`: bool\n            Whether we should overwrite an existing file.\n            If False, an error will be raised if the file already exists. If True,\n            the file will be overwritten if it exists.\n        `**kwargs`:\n            Accepts default values for all ``streams`` which will be used if these\n            keywords are not provided for any stream.\n\n    See :ref:`write-simple` and :ref:`write-h264` for examples.\n    '''\n\n    def __cinit__(self, filename, streams, fmt='', lib_opts={}, metadata={},\n                  overwrite=False, **kwargs):\n        cdef int res = 0, n = len(streams), r\n        cdef char *format_name = NULL\n        cdef char msg[256]\n        cdef MediaStream *s\n        cdef AVDictionaryEntry *dict_temp = NULL\n        cdef bytes msg2\n        cdef const AVCodec *codec_desc\n\n        filename = encode_to_bytes(filename)\n        streams = encode_to_bytes(deepcopy(streams))\n        if fmt:\n            fmt = fmt.encode('utf8')\n        lib_opts = encode_to_bytes(deepcopy(lib_opts))\n        metadata = encode_to_bytes(deepcopy(metadata))\n        kwargs = encode_to_bytes(deepcopy(kwargs))\n\n        self.total_size = 0\n        self.closed = 0\n        self.format_opts = NULL\n        if fmt:\n            format_name = fmt\n        if not n:\n            raise Exception('Streams parameters not provided.')\n        conf = [deepcopy(kwargs) for i in streams]\n        for r in range(n):\n            conf[r].update(streams[r])\n        self.config = conf\n\n        self.fmt_ctx = NULL\n        res = avformat_alloc_output_context2(&self.fmt_ctx, NULL, format_name, filename)\n        if res < 0 or self.fmt_ctx == NULL:\n            raise Exception('Failed to create format context: ' + tcode(emsg(res, msg, sizeof(msg))))\n        self.streams = <MediaStream *>malloc(n * sizeof(MediaStream))\n        if self.streams == NULL:\n            self.clean_up()\n            raise MemoryError()\n        s = self.streams\n        self.n_streams = n\n        memset(s, 0, n * sizeof(MediaStream))\n        if isinstance(lib_opts, dict):\n            lib_opts = [lib_opts, ] * n\n        elif len(lib_opts) == 1:\n            lib_opts = lib_opts * n\n        if isinstance(metadata, dict):\n            metadata = [metadata, ] * n\n        elif len(metadata) == 1:\n            metadata = metadata * n\n\n        for r in range(n):\n            s[r].codec_opts = NULL\n            config = conf[r]\n            if 'pix_fmt_out' not in config or not config['pix_fmt_out']:\n                config['pix_fmt_out'] = config['pix_fmt_in']\n            if 'width_out' not in config or not config['width_out']:\n                config['width_out'] = config['width_in']\n            if 'height_out' not in config or not config['height_out']:\n                config['height_out'] = config['height_in']\n            if 'codec' not in config or not config['codec']:\n                s[r].codec_id = self.fmt_ctx.oformat.video_codec\n                codec_desc = avcodec_find_encoder(s[r].codec_id)\n                if codec_desc == NULL:\n                    raise Exception('Default codec not found for output file.')\n                config['codec'] = codec_desc.name\n            else:\n                codec_desc = avcodec_find_encoder_by_name(config['codec'])\n                if codec_desc == NULL:\n                    self.clean_up()\n                    raise Exception('Encoder codec %s not available.' % config['codec'])\n                s[r].codec_id = codec_desc.id\n            s[r].width_in = config['width_in']\n            s[r].width_out = config['width_out']\n            s[r].height_in = config['height_in']\n            s[r].height_out = config['height_out']\n            s[r].num, s[r].den = config['frame_rate']\n            if av_get_pix_fmt(config['pix_fmt_in']) == AV_PIX_FMT_NONE:\n                self.clean_up()\n                raise Exception('Pixel format %s not found.' % config['pix_fmt_in'])\n            if av_get_pix_fmt(config['pix_fmt_out']) == AV_PIX_FMT_NONE:\n                self.clean_up()\n                raise Exception('Pixel format %s not found.' % config['pix_fmt_out'])\n            s[r].pix_fmt_in = av_get_pix_fmt(config['pix_fmt_in'])\n            s[r].pix_fmt_out = av_get_pix_fmt(config['pix_fmt_out'])\n\n            s[r].codec = avcodec_find_encoder(s[r].codec_id)\n            if s[r].codec == NULL:\n                self.clean_up()\n                raise Exception('Codec %s not found.' % config['codec'])\n            s[r].av_stream = avformat_new_stream(self.fmt_ctx, NULL)\n            if s[r].av_stream == NULL:\n                self.clean_up()\n                raise Exception(\"Couldn't create stream %d.\" % r)\n            s[r].index = s[r].av_stream.index\n\n            s[r].codec_ctx = avcodec_alloc_context3(s[r].codec)\n            if s[r].codec_ctx == NULL:\n                self.clean_up()\n                raise MemoryError(\"Couldn't create stream %d.\" % r)\n\n            s[r].codec_ctx.width = s[r].width_out\n            s[r].codec_ctx.height = s[r].height_out\n            supported_rates = get_supported_framerates(config['codec'], (s[r].num, s[r].den))\n            if supported_rates and supported_rates[0] != (s[r].num, s[r].den):\n                self.clean_up()\n                raise Exception('%d/%d is not a supported frame rate for codec %s, the \\\n                closest valid rate is %d/%d' % (s[r].num, s[r].den, config['codec'],\n                                                supported_rates[0][0], supported_rates[0][1]))\n            s[r].av_stream.avg_frame_rate.num = s[r].num\n            s[r].av_stream.avg_frame_rate.den = s[r].den\n            s[r].av_stream.r_frame_rate.num = s[r].num\n            s[r].av_stream.r_frame_rate.den = s[r].den\n            s[r].codec_ctx.time_base.den = s[r].num\n            s[r].codec_ctx.time_base.num = s[r].den\n            s[r].codec_ctx.pix_fmt = s[r].pix_fmt_out\n\n            for k, v in metadata[r].items():\n                k_b = k.encode('utf8')\n                res = av_dict_set(&s[r].av_stream.metadata, k_b, v, 0)\n                if res < 0:\n                    av_dict_free(&s[r].av_stream.metadata)\n                    self.clean_up()\n                    raise Exception('Failed to set option %s: %s for stream %d; %s'\n                                    % (k, v, r, tcode(emsg(res, msg, sizeof(msg)))))\n            # Some formats want stream headers to be separate\n            if self.fmt_ctx.oformat.flags & AVFMT_GLOBALHEADER:\n                s[r].codec_ctx.flags |= AV_CODEC_FLAG_GLOBAL_HEADER\n\n            supported_fmts = get_supported_pixfmts(config['codec'], config['pix_fmt_out'])\n            if supported_fmts and supported_fmts[0] != config['pix_fmt_out'].decode('utf8'):\n                self.clean_up()\n                raise Exception('%s is not a supported pixel format for codec %s, the '\n                'best valid format is %s' % (config['pix_fmt_out'], config['codec'],\n                                            supported_fmts[0]))\n\n            if (s[r].codec_ctx.pix_fmt != s[r].pix_fmt_in or s[r].codec_ctx.width != s[r].width_in or\n                s[r].codec_ctx.height != s[r].height_in):\n                s[r].av_frame = av_frame_alloc()\n                if s[r].av_frame == NULL:\n                    self.clean_up()\n                    raise MemoryError()\n                s[r].av_frame.format = s[r].pix_fmt_out\n                s[r].av_frame.width = s[r].width_out\n                s[r].av_frame.height = s[r].height_out\n                if av_frame_get_buffer(s[r].av_frame, 32) < 0:\n                    raise Exception('Cannot allocate frame buffers.')\n\n                s[r].sws_ctx = sws_getCachedContext(NULL, s[r].width_in, s[r].height_in,\\\n                s[r].pix_fmt_in, s[r].codec_ctx.width, s[r].codec_ctx.height,\\\n                s[r].codec_ctx.pix_fmt, SWS_BICUBIC, NULL, NULL, NULL)\n                if s[r].sws_ctx == NULL:\n                    self.clean_up()\n                    raise Exception('Cannot find conversion context.')\n\n            for k, v in lib_opts[r].items():\n                k_b = k.encode('utf8')\n                if opt_default(k_b, v, s[r].sws_ctx, NULL, NULL, NULL, &self.format_opts, &s[r].codec_opts) < 0:\n                    raise Exception('library option %s: %s not found' % (k, v))\n\n            res = avcodec_open2(s[r].codec_ctx, s[r].codec, &s[r].codec_opts)\n            bad_vals = ''\n            dict_temp = av_dict_get(s[r].codec_opts, b\"\", dict_temp, AV_DICT_IGNORE_SUFFIX)\n            while dict_temp != NULL:\n                bad_vals += '%s: %s, ' % (dict_temp.key, dict_temp.value)\n                dict_temp = av_dict_get(s[r].codec_opts, b\"\", dict_temp, AV_DICT_IGNORE_SUFFIX)\n            av_dict_free(&s[r].codec_opts)\n            if bad_vals:\n                msg2 = (\"The following options were not recognized: %s.\\n\" % bad_vals).encode('utf8')\n                av_log(NULL, AV_LOG_ERROR, '%s', msg2)\n            if res < 0:\n                self.clean_up()\n                raise Exception('Failed to open codec for stream %d; %s' % (r, tcode(emsg(res, msg, sizeof(msg)))))\n\n            res = avcodec_parameters_from_context(s[r].av_stream.codecpar, s[r].codec_ctx)\n            if res < 0:\n                self.clean_up()\n                raise Exception('Failed to initialize stream parameters for stream %d; %s' % (r, tcode(emsg(res, msg, sizeof(msg)))))\n\n            s[r].pts = 0\n            if self.fmt_ctx.oformat.flags & AVFMT_VARIABLE_FPS:\n                if self.fmt_ctx.oformat.flags & AVFMT_NOTIMESTAMPS:\n                    s[r].sync_fmt = VSYNC_PASSTHROUGH\n                else:\n                    s[r].sync_fmt = VSYNC_VFR\n            else:\n                s[r].sync_fmt = VSYNC_CFR\n\n        if not (self.fmt_ctx.oformat.flags & AVFMT_NOFILE):\n            res = avio_check(filename, 0)\n            if (not res) and not overwrite:\n                self.clean_up()\n                raise Exception('File %s already exists.' % filename)\n            elif res < 0 and res != AV_ENOENT:\n                self.clean_up()\n                raise Exception('File error: ' + tcode(emsg(res, msg, sizeof(msg))))\n            res = avio_open2(&self.fmt_ctx.pb, filename, AVIO_FLAG_WRITE, NULL, NULL)\n            if res < 0:\n                self.clean_up()\n                raise Exception('File error: ' + tcode(emsg(res, msg, sizeof(msg))))\n        res = avformat_write_header(self.fmt_ctx, &self.format_opts)\n        bad_vals = ''\n        dict_temp = av_dict_get(self.format_opts, b\"\", dict_temp, AV_DICT_IGNORE_SUFFIX)\n        while dict_temp != NULL:\n            bad_vals += '%s: %s, ' % (dict_temp.key, dict_temp.value)\n            dict_temp = av_dict_get(self.format_opts, \"\", dict_temp, AV_DICT_IGNORE_SUFFIX)\n        av_dict_free(&self.format_opts)\n        if bad_vals:\n            msg2 = (\"The following options were not recognized: %s.\\n\" % bad_vals).encode('utf8')\n            av_log(NULL, AV_LOG_ERROR, '%s', msg2)\n        if res < 0:\n            self.clean_up()\n            raise Exception('Error writing header: ' + tcode(emsg(res, msg, sizeof(msg))))\n\n    def __dealloc__(self):\n        self.close()\n\n    cpdef close(self):\n        '''Closes the writer and writes any frames cached and not yet written.\n\n        Until called, or until the instance is deleted (and this is implicitly called)\n        the file is not fully written.\n\n        .. warning::\n\n            After calling this method, calling any other class method on this instance may\n            result in a crash or program corruption.\n        '''\n        cdef int r, res, wrote = 0\n        cdef char msg[256]\n        cdef AVPacket pkt\n        if self.closed:\n            return\n        self.closed = 1\n\n        with nogil:\n            if self.fmt_ctx == NULL or (not self.n_streams) or self.streams[0].codec_ctx == NULL:\n                self.clean_up()\n                with gil:\n                    return\n\n            for r in range(self.n_streams):\n                if not self.streams[r].count:\n                    continue\n                wrote = 1\n\n                av_init_packet(&pkt)\n                pkt.data = NULL\n                pkt.size = 0\n\n                # flush\n                res = avcodec_send_frame(self.streams[r].codec_ctx, NULL)\n                if res < 0:\n                    with gil:\n                        raise Exception('Error sending NULL frame: ' + tcode(emsg(res, msg, sizeof(msg))))\n\n                while True:\n                    res = avcodec_receive_packet(self.streams[r].codec_ctx, &pkt)\n                    if res < 0:\n                        if res != AVERROR_EOF:\n                            with gil:\n                                raise Exception('Error getting encoded packet: ' + tcode(emsg(res, msg, sizeof(msg))))\n                        break\n\n                    if pkt.pts != AV_NOPTS_VALUE:\n                        pkt.pts = av_rescale_q(pkt.pts, self.streams[r].codec_ctx.time_base, self.streams[r].av_stream.time_base)\n                    if pkt.dts != AV_NOPTS_VALUE:\n                        pkt.dts = av_rescale_q(pkt.dts, self.streams[r].codec_ctx.time_base, self.streams[r].av_stream.time_base)\n                    pkt.stream_index = self.streams[r].av_stream.index\n                    self.total_size += pkt.size\n\n                    res = av_interleaved_write_frame(self.fmt_ctx, &pkt)\n                    if res < 0:\n                        with gil:\n                            raise Exception('Error writing packet: ' + tcode(emsg(res, msg, sizeof(msg))))\n            if wrote:\n                av_write_trailer(self.fmt_ctx)\n            self.clean_up()\n\n    def write_frame(MediaWriter self, Image img, double pts, int stream=0):\n        '''Writes a :class:`ffpyplayer.pic.Image` frame to the specified stream.\n\n        If the input data is different than the frame written to disk in either\n        size or pixel format as specified when creating the stream, the frame\n        is converted before writing. But the input image must match the size and\n        format as that specified when creating this stream.\n\n        :Parameters:\n\n            `img`: :class:`ffpyplayer.pic.Image`\n                The :class:`ffpyplayer.pic.Image` instance containing the frame\n                to be written to disk.\n            `pts`: float\n                The timestamp of this frame in video time. E.g. 0.5\n                means the frame should be displayed by a player at 0.5 seconds after\n                the video started playing. In a sense, the frame rate defines which\n                timestamps are valid timestamps. However, this is not always the\n                case, so if timestamps are invalid for a particular format, they are\n                forced to valid values, if possible.\n            `stream`: int\n                The stream number to which to write this frame. Defaults to 0.\n\n        :returns:\n\n            (int): The approximate number of bytes written to disk so far for this file.\n\n            .. note::\n\n                This is not the same as the number of bytes passed to this function\n                so far, because the encoders cache data before writing to disk.\n                So although some frames may have been passed, the return value\n                may not represent this.\n\n                An extreme example is where the same frame is passed many times\n                to h264; the encoder will only write this frame once when the Writer\n                object is closed and encoders are flushed, so this function\n                will only return 0.\n\n        See :ref:`examples` for its usage.\n        '''\n        cdef int res = 0, got_pkt\n        cdef int frame_cloned = 0\n        cdef AVFrame *frame_in = img.frame\n        cdef AVFrame *frame_out\n        cdef MediaStream *s\n        cdef double ipts, dpts\n        cdef int64_t rounded_pts\n        cdef AVPacket pkt\n        cdef char msg[256]\n        if stream >= self.n_streams:\n            raise Exception('Invalid stream number %d' % stream)\n        s = self.streams + stream\n        if (frame_in.width != s.width_in or frame_in.height != s.height_in or\n            frame_in.format != <AVPixelFormat>s.pix_fmt_in):\n            raise Exception(\"Input image doesn't match stream specified parameters.\")\n\n        with nogil:\n            if s.av_frame != NULL:\n                frame_out = s.av_frame\n                sws_scale(s.sws_ctx, <const uint8_t *const *>frame_in.data, frame_in.linesize,\n                          0, frame_in.height, frame_out.data, frame_out.linesize)\n            else:\n                frame_out = av_frame_clone(frame_in)\n                frame_cloned = 1\n                if frame_out == NULL:\n                    with gil:\n                        raise MemoryError\n\n            rounded_pts = <int64_t>floor(pts / av_q2d(s.codec_ctx.time_base) + 0.5)\n            frame_out.pict_type = AV_PICTURE_TYPE_NONE\n            frame_out.pts = rounded_pts\n\n            av_init_packet(&pkt)\n            pkt.data = NULL\n            pkt.size = 0\n\n            res = avcodec_send_frame(s.codec_ctx, frame_out)\n            if res < 0:\n                if frame_cloned:\n                    av_frame_free(&frame_out)\n                with gil:\n                    raise Exception('Error sending frame: ' + tcode(emsg(res, msg, sizeof(msg))))\n\n            while True:\n                res = avcodec_receive_packet(s.codec_ctx, &pkt)\n                if res < 0:\n                    if frame_cloned:\n                        av_frame_free(&frame_out)\n                    if res != AVERROR_EOF and res != AV_EAGAIN:\n                        with gil:\n                            raise Exception('Error getting encoded packet: ' + tcode(emsg(res, msg, sizeof(msg))))\n                    break\n\n                if pkt.pts != AV_NOPTS_VALUE:\n                    pkt.pts = av_rescale_q(pkt.pts, s.codec_ctx.time_base, s.av_stream.time_base)\n                if pkt.dts != AV_NOPTS_VALUE:\n                    pkt.dts = av_rescale_q(pkt.dts, s.codec_ctx.time_base, s.av_stream.time_base)\n                pkt.stream_index = s.av_stream.index\n                self.total_size += pkt.size\n\n                res = av_interleaved_write_frame(self.fmt_ctx, &pkt)\n                if res < 0:\n                    if frame_cloned:\n                        av_frame_free(&frame_out)\n                    with gil:\n                        raise Exception('Error writing packet: ' + tcode(emsg(res, msg, sizeof(msg))))\n\n            s.pts += 1\n            s.count += 1\n            if frame_cloned:\n                av_frame_free(&frame_out)\n        return self.total_size\n\n    def get_configuration(self):\n        '''Returns the configuration parameters used to initialize all the streams for this\n        instance.\n\n        This is not the same as the dicts passed when creating the file because\n        this uses the actual parameters used.\n\n        :returns:\n\n            list: List of dicts for each stream.\n\n        For example:\n\n        .. code-block:: python\n\n            from ffpyplayer.writer import MediaWriter\n\n            w, h = 640, 480\n            out_opts = {'pix_fmt_in':'rgb24', 'width_in':w, 'height_in':h, 'codec':'rawvideo',\n                        'frame_rate':(5, 1)}\n            writer = MediaWriter('output.avi', [out_opts] * 2, width_out=w/2, height_out=h/2)\n\n            print writer.get_configuration()\n            [{'height_in': 480, 'codec': 'rawvideo', 'width_in': 640, 'frame_rate': (5, 1),\n            'pix_fmt_in': 'rgb24', 'width_out': 320, 'height_out': 240, 'pix_fmt_out': 'rgb24'},\n            {'height_in': 480, 'codec': 'rawvideo', 'width_in': 640, 'frame_rate': (5, 1),\n            'pix_fmt_in': 'rgb24', 'width_out': 320, 'height_out': 240, 'pix_fmt_out': 'rgb24'}]\n        '''\n        return convert_to_str(deepcopy(self.config))\n\n    cdef void clean_up(MediaWriter self) nogil:\n        cdef int r\n\n        for r in range(self.n_streams):\n            # If the in and out formats are different we must delete the out frame data buffer\n            if self.streams[r].av_frame != NULL:\n                av_frame_free(&self.streams[r].av_frame)\n                self.streams[r].av_frame = NULL\n            if self.streams[r].sws_ctx != NULL:\n                sws_freeContext(self.streams[r].sws_ctx)\n                self.streams[r].sws_ctx= NULL\n            if self.streams[r].codec_opts:\n                av_dict_free(&self.streams[r].codec_opts)\n            if self.streams[r].codec_ctx:\n                avcodec_free_context(&self.streams[r].codec_ctx)\n        free(self.streams)\n        self.streams = NULL\n        self.n_streams = 0\n\n        if self.fmt_ctx != NULL:\n            if self.fmt_ctx.pb != NULL and not (self.fmt_ctx.oformat.flags & AVFMT_NOFILE):\n                avio_close(self.fmt_ctx.pb)\n            avformat_free_context(self.fmt_ctx)\n            self.fmt_ctx = NULL\n        av_dict_free(&self.format_opts)\n        self.total_size = 0\n\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[build-system]\nrequires = [\n    \"setuptools\", \"wheel\", \"cython~=3.0.11\",\n]\n"
  },
  {
    "path": "setup.py",
    "content": "from setuptools import setup, Extension\nfrom os.path import join, exists, isdir, dirname, abspath\nfrom os import environ, listdir, mkdir\nfrom distutils.command.build_ext import build_ext\nimport sys\nimport ffpyplayer\n\n\n# Determine on which platform we are\nplatform = sys.platform\n\n# detect Python for android project (http://github.com/kivy/python-for-android)\n# or kivy-ios (http://github.com/kivy/kivy-ios)\nndkplatform = environ.get('NDKPLATFORM')\nif ndkplatform is not None and environ.get('LIBLINK'):\n    platform = 'android'\nkivy_ios_root = environ.get('KIVYIOSROOT', None)\nif kivy_ios_root is not None:\n    platform = 'ios'\n\n\n# There are issues with using cython at all on some platforms;\n# exclude them from using or declaring cython.\n\n# This determines whether Cython specific functionality may be used.\ncan_use_cython = True\n# This sets whether or not Cython gets added to setup_requires.\ndeclare_cython = False\n\nif platform in ('ios', 'android'):\n    # NEVER use or declare cython on these platforms\n    print('Not using cython on %s' % platform)\n    can_use_cython = False\nelse:\n    declare_cython = True\n\nsrc_path = build_path = dirname(__file__)\nprint(f'Source/build path: {src_path}')\n\n# select which ffmpeg libraries will be available\nc_options = {\n    # If true, filters will be used'\n    'config_avfilter': True,\n    'config_avdevice': True,\n    'config_swscale': True,\n    'config_rtsp_demuxer': True,\n    'config_mmsh_protocol': True,\n    'config_postproc': platform != 'win32',\n    # whether sdl is included as an option\n    'config_sdl': True, # not implemented yet\n    'has_sdl2': True,\n    'use_sdl2_mixer': False,\n    # these should be true\n    'config_avutil':True,\n    'config_avcodec':True,\n    'config_avformat':True,\n    'config_swresample':True\n}\n\nfor key in list(c_options.keys()):\n    if key == 'has_sdl2':\n        continue\n\n    ukey = key.upper()\n    if ukey in environ:\n        value = bool(int(environ[ukey]))\n        print('Environ change {0} -> {1}'.format(key, value))\n        c_options[key] = value\n\nif (not c_options['config_avfilter']) and not c_options['config_swscale']:\n    raise Exception(\n        'At least one of config_avfilter and config_swscale must be enabled.')\n\n# if c_options['config_avfilter'] and ((not c_options['config_postproc']) or \\\n#     not c_options['config_swscale']):\n#     raise Exception(\n#         'config_avfilter requires the postproc and swscale binaries.')\nc_options['config_avutil'] = c_options['config_avutil'] = True\nc_options['config_avformat'] = c_options['config_swresample'] = True\n\n\nclass FFBuildExt(build_ext, object):\n\n    def __new__(cls, *a, **kw):\n        # Note how this class is declared as a subclass of distutils\n        # build_ext as the Cython version may not be available in the\n        # environment it is initially started in. However, if Cython\n        # can be used, setuptools will bring Cython into the environment\n        # thus its version of build_ext will become available.\n        # The reason why this is done as a __new__ rather than through a\n        # factory function is because there are distutils functions that check\n        # the values provided by cmdclass with issublcass, and so it would\n        # result in an exception.\n        # The following essentially supply a dynamically generated subclass\n        # that mix in the cython version of build_ext so that the\n        # functionality provided will also be executed.\n        if can_use_cython:\n            from Cython.Distutils import build_ext as cython_build_ext\n            build_ext_cls = type(\n                'FFBuildExt', (FFBuildExt, cython_build_ext), {})\n            return super(FFBuildExt, cls).__new__(build_ext_cls)\n        else:\n            return super(FFBuildExt, cls).__new__(cls)\n\n    def finalize_options(self):\n        retval = super(FFBuildExt, self).finalize_options()\n        global build_path\n        if (self.build_lib is not None and exists(self.build_lib) and\n                not self.inplace):\n            build_path = self.build_lib\n            print(f'Build path changed to: {src_path}')\n        return retval\n\n    def build_extensions(self):\n        compiler = self.compiler.compiler_type\n        print('Using compiler \"{}\"'.format(compiler))\n\n        args = []\n        link_args = []\n        if compiler != 'msvc':\n            args += [\"-O3\", '-fno-strict-aliasing', '-Wno-error']\n\n            if platform == 'darwin':\n                link_args.append('-headerpad_max_install_names')\n        print('Using compiler args: {}'.format(args))\n        print('Using linker args: {}'.format(link_args))\n\n        for ext in self.extensions:\n            ext.extra_compile_args = args\n            ext.extra_link_args = link_args\n        super(FFBuildExt, self).build_extensions()\n\n\ncmdclass = {'build_ext': FFBuildExt}\n\n\ndef getoutput(cmd):\n    import subprocess\n    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,\n                         stderr=subprocess.PIPE)\n    p.wait()\n    if p.returncode:  # if not returncode == 0\n        print('WARNING: A problem occured while running {0} (code {1})\\n'\n              .format(cmd, p.returncode))\n        stderr_content = p.stderr.read()\n        if stderr_content:\n            print('{0}\\n'.format(stderr_content))\n        return \"\"\n    return p.stdout.read()\n\n\ndef pkgconfig(*packages, **kw):\n    flag_map = {'-I': 'include_dirs', '-L': 'library_dirs', '-l': 'libraries'}\n    cmd = 'pkg-config --libs --cflags {}'.format(' '.join(packages))\n    results = getoutput(cmd).split()\n    for token in results:\n        ext = token[:2].decode('utf-8')\n        flag = flag_map.get(ext)\n        if not flag:\n            continue\n        kw.setdefault(flag, []).append(token[2:].decode('utf-8'))\n    return kw\n\n\ndef get_paths(name):\n    root = environ.get('{}_ROOT'.format(name))\n    print('{}_ROOT: \"{}\"'.format(name, root))\n    if root is not None and not isdir(root):\n        print('Root directory \"{}\" is not valid'.format(root))\n        root = None\n\n    if root is not None:\n        include = environ.get(\n            '{}_INCLUDE_DIR'.format(name), join(root, 'include'))\n        lib = environ.get('{}_LIB_DIR'.format(name), join(root, 'lib'))\n    else:\n        include = environ.get('{}_INCLUDE_DIR'.format(name))\n        lib = environ.get('{}_LIB_DIR'.format(name))\n\n    if include is not None and not isdir(include):\n        print('Include directory \"{}\" is not valid'.format(include))\n        include = None\n    if lib is not None and not isdir(lib):\n        print('Lib directory \"{}\" is not valid'.format(lib))\n        lib = None\n    return lib, include\n\n\nlibraries = []\nlibrary_dirs = []\ninclude_dirs = []\n\nif \"KIVYIOSROOT\" in environ:\n    # enable kivy-ios compilation\n    include_dirs = [\n        environ.get(\"SDL_INCLUDE_DIR\"),\n        environ.get(\"FFMPEG_INCLUDE_DIR\")]\n\nelif \"NDKPLATFORM\" in environ:\n    # enable python-for-android/py4a compilation\n\n    # ffmpeg:\n    ffmpeg_lib, ffmpeg_include = get_paths('FFMPEG')\n    libraries.extend([\n        'avcodec', 'avdevice', 'avfilter', 'avformat',\n        'avutil', 'swscale', 'swresample', 'm'\n    ])\n    if c_options['config_postproc']:\n        libraries.append('postproc')\n    library_dirs.append(ffmpeg_lib)\n    include_dirs.append(ffmpeg_include)\n\n    # sdl:\n    sdl_lib, sdl_include = get_paths('SDL')\n    if sdl_lib and sdl_include:\n        libraries.append('SDL2')\n        library_dirs.append(sdl_lib)\n        include_dirs.append(sdl_include)\n    else:  # old toolchain\n        raise ValueError('SDL2 not found')\n\n    # sdl2 mixer:\n    c_options['use_sdl2_mixer'] = c_options['use_sdl2_mixer']\n    if c_options['use_sdl2_mixer']:\n        _, mixer_include = get_paths('SDL2_MIXER')\n        libraries.append('SDL2_mixer')\n        include_dirs.append(mixer_include)\n\nelse:\n\n    # ffmpeg\n    objects = [\n        'avcodec', 'avdevice', 'avfilter', 'avformat',\n        'avutil', 'swscale', 'swresample'\n    ]\n    if c_options['config_postproc']:\n        objects.append('postproc')\n    for libname in objects[:]:\n        for key, val in c_options.items():\n            if key.endswith(libname) and not val:\n                objects.remove(libname)\n                break\n\n    ffmpeg_lib, ffmpeg_include = get_paths('FFMPEG')\n    flags = {'include_dirs': [], 'library_dirs': [], 'libraries': []}\n    if ffmpeg_lib is None and ffmpeg_include is None:\n        flags = pkgconfig(*['lib' + l for l in objects])\n\n    library_dirs = flags.get('library_dirs', []) if ffmpeg_lib is None \\\n        else [ffmpeg_lib]\n    include_dirs = flags.get('include_dirs', []) if ffmpeg_include is None \\\n        else [ffmpeg_include]\n    libraries = objects[:]\n\n    # sdl\n    sdl_lib, sdl_include = get_paths('SDL')\n\n    flags = {}\n    if sdl_lib is None and sdl_include is None:\n        flags = pkgconfig('sdl2')\n\n    sdl_libs = flags.get('library_dirs', []) if sdl_lib is None \\\n        else [sdl_lib]\n    sdl_includes = flags.get('include_dirs', []) if sdl_include is None \\\n        else [join(sdl_include, 'SDL2'), sdl_include]\n\n    library_dirs.extend(sdl_libs)\n    include_dirs.extend(sdl_includes)\n    libraries.extend(flags.get('libraries', ['SDL2']))\n\n    c_options['use_sdl2_mixer'] = c_options['use_sdl2_mixer']\n    if c_options['use_sdl2_mixer']:\n        flags = {}\n        if sdl_lib is None and sdl_include is None:\n            flags = pkgconfig('SDL2_mixer')\n\n        library_dirs.extend(flags.get('library_dirs', []))\n        include_dirs.extend(flags.get('include_dirs', []))\n        libraries.extend(flags.get('libraries', ['SDL2_mixer']))\n\n\ndef get_wheel_data():\n    data = []\n    ff = environ.get('FFMPEG_ROOT')\n    if ff:\n        if isdir(join(ff, 'bin')):\n            data.append(('share/ffpyplayer/ffmpeg/bin', [\n                join(ff, 'bin', f) for f in listdir(join(ff, 'bin'))]))\n        if isdir(join(ff, 'licenses')):\n            data.append(('share/ffpyplayer/ffmpeg/licenses', [\n                join(ff, 'licenses', f) for\n                f in listdir(join(ff, 'licenses'))]))\n        if exists(join(ff, 'README.txt')):\n            data.append(('share/ffpyplayer/ffmpeg', [join(ff, 'README.txt')]))\n\n    sdl = environ.get('SDL_ROOT')\n    if sdl:\n        if isdir(join(sdl, 'bin')):\n            data.append(\n                ('share/ffpyplayer/sdl/bin', [\n                    join(sdl, 'bin', f) for f in listdir(join(sdl, 'bin'))]))\n    return data\n\n\nmods = [\n    'pic', 'threading', 'tools', 'writer', 'player/clock', 'player/core',\n    'player/decoder', 'player/frame_queue', 'player/player', 'player/queue']\nc_options['use_sdl2_mixer'] = c_options['use_sdl2_mixer']\n\n\nif can_use_cython:\n    mod_suffix = '.pyx'\nelse:\n    mod_suffix = '.c'\n\nprint('Generating ffconfig.h')\nif not exists(join(src_path, 'ffpyplayer', 'includes')):\n    mkdir(join(src_path, 'ffpyplayer', 'includes'))\nwith open(join(src_path, 'ffpyplayer', 'includes', 'ffconfig.h'), 'w') as f:\n    f.write('''\n#ifndef _FFCONFIG_H\n#define _FFCONFIG_H\n\n#include \"SDL_version.h\"\n#define SDL_VERSIONNUM(X, Y, Z) ((X)*1000 + (Y)*100 + (Z))\n#define SDL_VERSION_ATLEAST(X, Y, Z) (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z))\n#if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14)\n#define MAC_REALLOC 1\n#else\n#define MAC_REALLOC 0\n#endif\n\n#if !defined(_WIN32) && !defined(__APPLE__)\n#define NOT_WIN_MAC 1\n#else\n#define NOT_WIN_MAC 0\n#endif\n\n#if defined(_WIN32)\n#define WIN_IS_DEFINED 1\n#else\n#define WIN_IS_DEFINED 0\n#endif\n\n''')\n    for k, v in c_options.items():\n        f.write('#define %s %d\\n' % (k.upper(), int(v)))\n    f.write('''\n#endif\n''')\n\nprint('Generating ffconfig.pxi')\nwith open(join(src_path, 'ffpyplayer', 'includes', 'ffconfig.pxi'), 'w') as f:\n    for k, v in c_options.items():\n        f.write('DEF %s = %d\\n' % (k.upper(), int(v)))\n\ninclude_dirs.extend(\n    [join(src_path, 'ffpyplayer'),\n     join(src_path, 'ffpyplayer', 'includes')])\nprint('Include directories: {}'.format(include_dirs))\nprint('Library directories: {}'.format(library_dirs))\next_modules = [Extension(\n    'ffpyplayer.' + src_file.replace('/', '.'),\n    sources=[join(src_path, 'ffpyplayer', *(src_file + mod_suffix).split('/')),\n             join(src_path, 'ffpyplayer', 'clib', 'misc.c')],\n    libraries=libraries,\n    include_dirs=include_dirs,\n    library_dirs=library_dirs)\n               for src_file in mods]\n\nfor e in ext_modules:\n    e.cython_directives = {\"embedsignature\": True, 'language_level': 3}\n\nwith open('README.rst') as fh:\n    long_description = fh.read()\n\nsetup_requires = []\nif declare_cython:\n    setup_requires.append('cython~=3.0.11')\n\nsetup(name='ffpyplayer',\n      version=ffpyplayer.__version__,\n      author='Matthew Einhorn',\n      author_email='matt@einhorn.dev',\n      license='LGPL3',\n      description='A cython implementation of an ffmpeg based player.',\n      url='https://matham.github.io/ffpyplayer/',\n      long_description=long_description,\n      classifiers=[\n        'License :: OSI Approved :: GNU Lesser General Public License v3 '\n        '(LGPLv3)',\n        'Topic :: Multimedia :: Video',\n        'Topic :: Multimedia :: Video :: Display',\n        'Topic :: Multimedia :: Sound/Audio :: Players',\n        'Topic :: Multimedia :: Sound/Audio :: Players :: MP3',\n        'Programming Language :: Python :: 3.7',\n        'Programming Language :: Python :: 3.8',\n        'Programming Language :: Python :: 3.9',\n        'Programming Language :: Python :: 3.10',\n        'Programming Language :: Python :: 3.11',\n        'Programming Language :: Python :: 3.12',\n        'Programming Language :: Python :: 3.13',\n        'Operating System :: MacOS :: MacOS X',\n        'Operating System :: Microsoft :: Windows',\n        'Operating System :: POSIX :: BSD :: FreeBSD',\n        'Operating System :: POSIX :: Linux',\n        'Intended Audience :: Developers'],\n      packages=['ffpyplayer', 'ffpyplayer.player', 'ffpyplayer.tests'],\n      package_data={\n        'ffpyplayer': [\n            'player/*.pxd', 'clib/misc.h', 'includes/*.pxi', 'includes/*.h',\n            '*.pxd', 'player/*.pyx', 'clib/misc.c', '*.pyx']},\n      data_files=get_wheel_data(),\n      cmdclass=cmdclass, ext_modules=ext_modules,\n      setup_requires=setup_requires)\n"
  }
]