### Description

Adds opencv-python and ffmpeg.

### Status

opencv-python is modularized with a bunch of modules, I'll keep updating the status.

- [x] Core library
- [x] JPEG
- [x] PNG
- [x] WEBP
- [x] Image processing
- [x] video processing (FFMPEG)
- [x] objectdetect
- [x] dnn
- [x] ml
- [x] calib3d
- [x] feature2d
- [x] highgui (built, but nonsense)
- [x] photo
- [x] stitching
- [x] flann
- contrib algorithms?
- extra modules?

### Checklists

<!-- Note on checklists:
     If you think some of these steps are not necessary for your PR,
     just remove those checkboxes, or mark them as checked. Otherwise,
     if some checkboxes are left unmarked, we might assume that your PR
     is not ready to be merged and we might keep you waiting -->

- [x] Add a [CHANGELOG](https://github.com/pyodide/pyodide/blob/main/docs/project/changelog.md) entry
- [x] Add / update tests

Resolve #381
Resolve #1627
PKG Add opencv-python and ffmpeg. ### Description

Adds opencv-python and ffmpeg.

### Status

opencv-python is modularized with a bunch of modules, I'll keep updating the status.

- [x] Core library
- [x] JPEG
- [x] PNG
- [x] WEBP
- [x] Image processing
- [x] video processing (FFMPEG)
- [x] objectdetect
- [x] dnn
- [x] ml
- [x] calib3d
- [x] feature2d
- [x] highgui (built, but nonsense)
- [x] photo
- [x] stitching
- [x] flann
- contrib algorithms?
- extra modules?

### Checklists

<!-- Note on checklists:
     If you think some of these steps are not necessary for your PR,
     just remove those checkboxes, or mark them as checked. Otherwise,
     if some checkboxes are left unmarked, we might assume that your PR
     is not ready to be merged and we might keep you waiting -->

- [x] Add a [CHANGELOG](https://github.com/pyodide/pyodide/blob/main/docs/project/changelog.md) entry
- [x] Add / update tests

Resolve #381
Resolve #1627
import pytest


def test_threading_import(selenium):
    # Importing threading works
    selenium.run(
        """
        from threading import Thread
        """
    )

    selenium.run(
        """
        from threading import RLock

        with RLock():
            pass
        """
    )

    selenium.run(
        """
        from threading import Lock

        with Lock():
            pass
        """
    )

    selenium.run(
        """
        import threading
        threading.local(); pass
        """
    )

    # Starting a thread doesn't work
    msg = "can't start new thread"
    with pytest.raises(selenium.JavascriptException, match=msg):
        selenium.run(
            """
            from threading import Thread

            def set_state():
                return
            th = Thread(target=set_state)
            th.start()
            """
        )


def test_multiprocessing(selenium):
    selenium.run("import multiprocessing")

    res = selenium.run(
        """
        from multiprocessing import cpu_count
        cpu_count()
        """
    )
    assert isinstance(res, int)
    assert res > 0

    msg = "Function not implemented"
    with pytest.raises(selenium.JavascriptException, match=msg):
        selenium.run(
            """
            from multiprocessing import Process

            def func():
                return
            process = Process(target=func)
            process.start()
            """
        )

import pytest


def test_threading_import(selenium):
    # Importing threading works
    selenium.run(
        """
        from threading import Thread
        """
    )

    selenium.run(
        """
        from threading import RLock

        with RLock():
            pass
        """
    )

    selenium.run(
        """
        from threading import Lock

        with Lock():
            pass
        """
    )

    selenium.run(
        """
        import threading
        threading.local(); pass
        """
    )

    # Starting a thread doesn't work
    msg = "can't start new thread"
    with pytest.raises(selenium.JavascriptException, match=msg):
        selenium.run(
            """
            from threading import Thread

            def set_state():
                return
            th = Thread(target=set_state)
            th.start()
            """
        )


def test_multiprocessing(selenium):
    selenium.run("import multiprocessing")

    res = selenium.run(
        """
        from multiprocessing import cpu_count
        cpu_count()
        """
    )
    assert isinstance(res, int)
    assert res > 0

    msg = "Function not implemented"
    with pytest.raises(selenium.JavascriptException, match=msg):
        selenium.run(
            """
            from multiprocessing import Process

            def func():
                return
            process = Process(target=func)
            process.start()
            """
        )
