Why Access Violation from using Cython function?

-1

I have been working on creating a video editing software with Tkinter and have been developing the video player. I created a class to handle playing the video, but it does not quite run fast enough for a smooth fps. So I implemented cython compiling to speed it up, but one of the functions does not work when using the 'cdef' declaration. However, declaring with just 'def' works fine. The code compiles without a problem.

The error thrown is: Exception code=0xc0000005 flags=0x0 at 0x00007FF972B54E76. Access violation - attempting to read data at address 0x0000000000000008 Fatal Python error: (pygame parachute) Segmentation Fault Python runtime state: initialized

It is thrown on the commented line in file:

#cyVideoViewer.pyx
from tkinter import Tk, Label, Button
from PIL import ImageTk, Image
import cv2
import moviepy.editor as mpy
from time import time

cdef class viewer:
    cdef object video, canvas, label, stringvar, slider, last_frame
    cdef int delay
    cdef bint pause
    cdef tuple dimensions
    cdef list tempTime
    
    def __init__(self, object video, object canvas, object label, tuple dimensions, object sv, object slider):
        self.video = video
        self.canvas = canvas
        self.label = label
        self.delay = int((1000 / int(video.fps)))
        self.pause = True
        self.dimensions = dimensions
        self.tempTime = [0, 0]
        self.setPreviewFrame()
        self.stringvar = sv
        self.slider = slider
        try:
            self.last_frame = video.get_frame(video.end)
        except Exception as e:
            self.last_frame = video.get_frame(0)

    cpdef void setPreviewFrame(self, int t=0):
        cdef object image
        try:
            image = self.video.get_frame(t)
        except:
            image = self.last_frame
        cdef object res = cv2.resize(image, dsize=self.dimensions, interpolation=cv2.INTER_CUBIC)
        cdef object frame_image = ImageTk.PhotoImage(Image.fromarray(res))
        self.label.config(image=frame_image)
        self.label.image = frame_image

    cpdef void pausePlay(self):
        if self.pause:
            self.setPause(False)
            self.dostream(self.tempTime)
        else:
            self.setPause(True)

    cpdef void dostream(self, prev_time=[0,0], skip=False):
        self.stream(prev_time, skip)

    cdef stream(self, prev_time=[0, 0], bint skip=False):
        time1 = time()
        cdef double frame
        ##
        frame = prev_time[0]             # Error
        ##        
        frame += prev_time[1]/1000
        frame += self.delay/1000
        #
        if frame >= self.video.duration:
            self.stringvar.set(str(self.video.duration))
            return

        cdef object image
        try:
            image = self.video.get_frame(frame)
        except Exception as e:
            print(e)
            self.video.close()
            return
        prev_time[1] += self.delay if skip==False else self.delay*2
        if prev_time[1] >= 1000:
            prev_time[0] += 1
            prev_time[1] = 0
        cdef object res = cv2.resize(image, dsize=self.dimensions, interpolation=cv2.INTER_CUBIC)
        cdef object frame_image = ImageTk.PhotoImage(Image.fromarray(res))
        self.label.config(image=frame_image)
        self.label.image = frame_image

        time2 = time()
        exTime = (time2 - time1) * 1000

        self.tempTime = prev_time
        self.stringvar.set("0:"+str(prev_time[0])+"."+str(prev_time[1]))
        cdef double timePerc = (prev_time[0]+prev_time[1]/1000)/self.video.duration
        cdef double loc = timePerc*798+51
        cdef int x = self.canvas.coords(self.slider)[0]
        self.canvas.move(self.slider, loc-x, 0)
        if self.pause:
            return

        if exTime >= self.delay*2:
            self.label.after(0, lambda: self.dostream(prev_time=prev_time, skip=True))
        else:
            self.label.after(int(self.delay-exTime) if self.delay>exTime else 0, lambda: self.dostream(prev_time=prev_time))

    cpdef void setPause(self, pause):
        self.pause = pause

    cpdef void setTime(self, time):
        self.tempTime = time

    cpdef void setStringVar(self, sv):
        self.stringvar = sv

    cpdef void setVideo(self, video):
        self.video = video

    cpdef object getVideo(self):
        return self.video

    cpdef object getPause(self):
        return self.pause

    cpdef object getTime(self):
        return self.prevTime

I created the "dostream()" function to prevent errors about closures when calling from lambdas.

Why does the error get thrown when assigning "frame" to a parameter, and how could I fix this while continuing to use cython ? Any help would be greatly appreciated.

python
cython
asked on Stack Overflow Aug 3, 2020 by ajfrist

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0