PyAV-Org / PyAV

Pythonic bindings for FFmpeg's libraries.
https://pyav.basswood-io.com/
BSD 3-Clause "New" or "Revised" License
2.5k stars 364 forks source link

cuvid_264 decode conflict with other process #1471

Closed namogg closed 3 months ago

namogg commented 3 months ago

Overview

Thread A running hardware decoder with: codec = av.codec.CodecContext.create("h264_cuvid", 'r') Child Process B run cuda.init():

import pycuda.driver as cuda
cuda.init()
cuda_context_0 = cuda.Device(0).make_context()

My code was working fine with h264 but h264_cuvid cause conflict.

Expected behavior

Both process and thread doesnt confict

Actual behavior

Both the thread and the process is corrupted. Decode thread error: [Pack decode ] An exception occurred: [Errno 542398533] Generic error in an external library The other process got error: pycuda._driver.LogicError: cuInit failed: initialization error

Reproduction

import threading
import multiprocessing
import pycuda.driver as cuda
import av
import numpy as np
import time
import random

def cuda_task():
    try:
        cuda.init()
        print("CUDA initialized in process")
        # Keep the process running
        while True:
            time.sleep(1)
    except Exception as e:
        print(f"[Process] CUDA init error: {e}")

def generate_random_h264_packet():
    # Generate random bytes to simulate an H.264 packet
    packet_size = random.randint(100, 1000)  # Packet size between 100 and 1000 bytes
    return bytearray(random.getrandbits(8) for _ in range(packet_size))

def decode_task():
    try:
        codec = av.codec.CodecContext.create("h264_cuvid", 'r')
        print("Decoder initialized")

        while True:
            print("Decoding")
            # Generate random H.264 packet
            packet_data = generate_random_h264_packet()
            packet = av.packet.Packet(packet_data)

            # Decode the packet
            frames = codec.decode(packet)

            time.sleep(1)  # Simulate some processing delay
    except Exception as e:
        print(f"[Thread] Decoding error: {e}")

if __name__ == "__main__":
    # Using threading for decoding task
    thread = threading.Thread(target=decode_task, daemon=True)
    thread.start()

    # Using multiprocessing for CUDA task
    process = multiprocessing.Process(target=cuda_task)
    process.start()

    # Keep the main process running
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("Main process interrupted")
        process.terminate()
        process.join()

Investigation

Starting the cuda.init() process first adn keep running doesnt cause error for both side. Running both in process doesnt cause error

Versions



## Research

I have done the following:

- [x] Checked the [PyAV documentation](https://pyav.basswood-io.com)
- [x] Searched on [Google](https://www.google.com/search?q=pyav+how+do+I+foo)
- [x] Searched on [Stack Overflow](https://stackoverflow.com/search?q=pyav)
- [x] Looked through [old GitHub issues](https://github.com/PyAV-Org/PyAV/issues?&q=is%3Aissue)
namogg commented 3 months ago

Changing process from fork to spawn does fix the problem