Upload folder using huggingface_hub (part 4)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +9 -0
- .venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/INSTALLER +1 -0
- .venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/METADATA +127 -0
- .venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/RECORD +244 -0
- .venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/REQUESTED +0 -0
- .venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/WHEEL +6 -0
- .venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/entry_points.txt +2 -0
- .venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/licenses/AUTHORS.py +182 -0
- .venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/licenses/AUTHORS.rst +129 -0
- .venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/licenses/LICENSE.txt +23 -0
- .venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/top_level.txt +1 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/codeccontext.cpython-310-darwin.so +3 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/codeccontext.pxd +8 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/codeccontext.py +146 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/codeccontext.pyi +11 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/stream.cpython-310-darwin.so +0 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/stream.pxd +6 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/stream.py +24 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/stream.pyi +9 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/subtitle.cpython-310-darwin.so +3 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/subtitle.pxd +29 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/subtitle.py +336 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/subtitles/subtitle.pyi +45 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/utils.cpython-310-darwin.so +0 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/utils.pxd +9 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/utils.py +74 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/__init__.pxd +0 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/__init__.py +2 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/__init__.pyi +17 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/codeccontext.cpython-310-darwin.so +3 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/codeccontext.pxd +21 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/codeccontext.py +396 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/codeccontext.pyi +36 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/format.cpython-310-darwin.so +3 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/format.pxd +20 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/format.py +209 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/format.pyi +30 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/frame.cpython-310-darwin.so +3 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/frame.pxd +28 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/frame.py +1631 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/frame.pyi +110 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/plane.cpython-310-darwin.so +3 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/plane.pxd +38 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/plane.py +305 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/plane.pyi +15 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/reformatter.cpython-310-darwin.so +3 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/reformatter.pxd +42 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/reformatter.py +322 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/reformatter.pyi +89 -0
- .venvs/kimodo/lib/python3.10/site-packages/av/video/stream.cpython-310-darwin.so +3 -0
.gitattributes
CHANGED
|
@@ -106,3 +106,12 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 106 |
.venvs/kimodo/lib/python3.10/site-packages/av/sidedata/motionvectors.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 107 |
.venvs/kimodo/lib/python3.10/site-packages/av/sidedata/sidedata.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 108 |
.venvs/kimodo/lib/python3.10/site-packages/av/stream.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
.venvs/kimodo/lib/python3.10/site-packages/av/sidedata/motionvectors.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 107 |
.venvs/kimodo/lib/python3.10/site-packages/av/sidedata/sidedata.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 108 |
.venvs/kimodo/lib/python3.10/site-packages/av/stream.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 109 |
+
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/codeccontext.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 110 |
+
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/subtitle.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 111 |
+
.venvs/kimodo/lib/python3.10/site-packages/av/video/codeccontext.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 112 |
+
.venvs/kimodo/lib/python3.10/site-packages/av/video/format.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 113 |
+
.venvs/kimodo/lib/python3.10/site-packages/av/video/frame.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 114 |
+
.venvs/kimodo/lib/python3.10/site-packages/av/video/plane.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 115 |
+
.venvs/kimodo/lib/python3.10/site-packages/av/video/reformatter.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 116 |
+
.venvs/kimodo/lib/python3.10/site-packages/av/video/stream.cpython-310-darwin.so filter=lfs diff=lfs merge=lfs -text
|
| 117 |
+
.venvs/kimodo/lib/python3.10/site-packages/botocore/__pycache__/utils.cpython-310.pyc filter=lfs diff=lfs merge=lfs -text
|
.venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/INSTALLER
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
uv
|
.venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/METADATA
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.4
|
| 2 |
+
Name: av
|
| 3 |
+
Version: 17.1.0
|
| 4 |
+
Summary: Pythonic bindings for FFmpeg's libraries.
|
| 5 |
+
Author-email: WyattBlue <wyattblue@auto-editor.com>, Jeremy Lainé <jeremy.laine@m4x.org>
|
| 6 |
+
License-Expression: BSD-3-Clause
|
| 7 |
+
Project-URL: Bug Tracker, https://github.com/PyAV-Org/PyAV/issues
|
| 8 |
+
Project-URL: Source Code, https://github.com/PyAV-Org/PyAV
|
| 9 |
+
Project-URL: homepage, https://pyav.basswood-io.com
|
| 10 |
+
Classifier: Development Status :: 5 - Production/Stable
|
| 11 |
+
Classifier: Intended Audience :: Developers
|
| 12 |
+
Classifier: Natural Language :: English
|
| 13 |
+
Classifier: Operating System :: MacOS :: MacOS X
|
| 14 |
+
Classifier: Operating System :: POSIX
|
| 15 |
+
Classifier: Operating System :: Unix
|
| 16 |
+
Classifier: Operating System :: Microsoft :: Windows
|
| 17 |
+
Classifier: Programming Language :: Cython
|
| 18 |
+
Classifier: Programming Language :: Python :: 3.10
|
| 19 |
+
Classifier: Programming Language :: Python :: 3.11
|
| 20 |
+
Classifier: Programming Language :: Python :: 3.12
|
| 21 |
+
Classifier: Programming Language :: Python :: 3.13
|
| 22 |
+
Classifier: Programming Language :: Python :: 3.14
|
| 23 |
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
| 24 |
+
Classifier: Topic :: Multimedia :: Sound/Audio
|
| 25 |
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Conversion
|
| 26 |
+
Classifier: Topic :: Multimedia :: Video
|
| 27 |
+
Classifier: Topic :: Multimedia :: Video :: Conversion
|
| 28 |
+
Requires-Python: >=3.10
|
| 29 |
+
Description-Content-Type: text/markdown
|
| 30 |
+
License-File: LICENSE.txt
|
| 31 |
+
License-File: AUTHORS.py
|
| 32 |
+
License-File: AUTHORS.rst
|
| 33 |
+
Dynamic: license-file
|
| 34 |
+
|
| 35 |
+
PyAV
|
| 36 |
+
====
|
| 37 |
+
|
| 38 |
+
PyAV is a Pythonic binding for the [FFmpeg][ffmpeg] libraries. We aim to provide all of the power and control of the underlying library, but manage the gritty details as much as possible.
|
| 39 |
+
|
| 40 |
+
---
|
| 41 |
+
|
| 42 |
+
[![GitHub Test Status][github-tests-badge]][github-tests] [![Documentation][docs-badge]][docs] [![Python Package Index][pypi-badge]][pypi] [![Conda Forge][conda-badge]][conda]
|
| 43 |
+
|
| 44 |
+
PyAV is for direct and precise access to your media via containers, streams, packets, codecs, and frames. It exposes a few transformations of that data, and helps you get your data to/from other packages (e.g. Numpy and Pillow).
|
| 45 |
+
|
| 46 |
+
This power does come with some responsibility as working with media is horrendously complicated and PyAV can't abstract it away or make all the best decisions for you. If the `ffmpeg` command does the job without you bending over backwards, PyAV is likely going to be more of a hindrance than a help.
|
| 47 |
+
|
| 48 |
+
But where you can't work without it, PyAV is a critical tool.
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
Installation
|
| 52 |
+
------------
|
| 53 |
+
|
| 54 |
+
Binary wheels are provided on [PyPI][pypi] for Linux, MacOS and Windows linked against the latest stable version of ffmpeg. You can install these wheels by running:
|
| 55 |
+
|
| 56 |
+
```bash
|
| 57 |
+
pip install av
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
Another way of installing PyAV is via [conda-forge][conda-forge]:
|
| 61 |
+
|
| 62 |
+
```bash
|
| 63 |
+
conda install av -c conda-forge
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
See the [Conda install][conda-install] docs to get started with (mini)Conda.
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
Alternative installation methods
|
| 70 |
+
--------------------------------
|
| 71 |
+
|
| 72 |
+
Due to the complexity of the dependencies, PyAV is not always the easiest Python package to install from source. If you want to use your existing ffmpeg (must be the correct major version), the source version of PyAV is on [PyPI][pypi]:
|
| 73 |
+
|
| 74 |
+
> [!WARNING]
|
| 75 |
+
> You must be in a posix env, and have the correct version of ffmpeg installed on your system.
|
| 76 |
+
|
| 77 |
+
```bash
|
| 78 |
+
pip install av --no-binary av
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
Installing From Source
|
| 83 |
+
----------------------
|
| 84 |
+
|
| 85 |
+
Here's how to build PyAV from source. You must use [MSYS2](https://www.msys2.org/) when using Windows.
|
| 86 |
+
|
| 87 |
+
```bash
|
| 88 |
+
git clone https://github.com/PyAV-Org/PyAV.git
|
| 89 |
+
cd PyAV
|
| 90 |
+
source scripts/activate.sh
|
| 91 |
+
|
| 92 |
+
# Build ffmpeg from source. You can skip this step
|
| 93 |
+
# if ffmpeg is already installed.
|
| 94 |
+
./scripts/build-deps
|
| 95 |
+
|
| 96 |
+
# Build PyAV
|
| 97 |
+
make
|
| 98 |
+
|
| 99 |
+
# Testing
|
| 100 |
+
make test
|
| 101 |
+
|
| 102 |
+
# Install globally
|
| 103 |
+
deactivate
|
| 104 |
+
pip install .
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
---
|
| 108 |
+
|
| 109 |
+
Have fun, [read the docs][docs], [come chat with us][discuss], and good luck!
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
[conda-badge]: https://img.shields.io/conda/vn/conda-forge/av.svg?colorB=CCB39A
|
| 114 |
+
[conda]: https://anaconda.org/conda-forge/av
|
| 115 |
+
[docs-badge]: https://img.shields.io/badge/docs-on%20pyav.basswood--io.com-blue.svg
|
| 116 |
+
[docs]: https://pyav.basswood-io.com
|
| 117 |
+
[pypi-badge]: https://img.shields.io/pypi/v/av.svg?colorB=CCB39A
|
| 118 |
+
[pypi]: https://pypi.org/project/av
|
| 119 |
+
[discuss]: https://github.com/PyAV-Org/PyAV/discussions
|
| 120 |
+
|
| 121 |
+
[github-tests-badge]: https://github.com/PyAV-Org/PyAV/workflows/tests/badge.svg
|
| 122 |
+
[github-tests]: https://github.com/PyAV-Org/PyAV/actions?workflow=tests
|
| 123 |
+
[github]: https://github.com/PyAV-Org/PyAV
|
| 124 |
+
|
| 125 |
+
[ffmpeg]: https://ffmpeg.org/
|
| 126 |
+
[conda-forge]: https://conda-forge.github.io/
|
| 127 |
+
[conda-install]: https://docs.conda.io/projects/conda/en/latest/user-guide/install/index.html
|
.venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/RECORD
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
../../../bin/pyav,sha256=cELpQkXIcZFyrpocYv7ltcCyWc94_s-_vkLMxGOUpCY,358
|
| 2 |
+
av-17.1.0.dist-info/INSTALLER,sha256=5hhM4Q4mYTT9z6QB6PGpUAW81PGNFrYrdXMj4oM_6ak,2
|
| 3 |
+
av-17.1.0.dist-info/METADATA,sha256=icLfisEQuey0LC6JWPu26d3P56lMXX3MJ3dfQ8dCxBA,4597
|
| 4 |
+
av-17.1.0.dist-info/RECORD,,
|
| 5 |
+
av-17.1.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 6 |
+
av-17.1.0.dist-info/WHEEL,sha256=GMlGfk9_-EKG_D0ClpCsWj7ncE2uKUvKdCS--Fq7w1Q,136
|
| 7 |
+
av-17.1.0.dist-info/entry_points.txt,sha256=3XMdM30ih673nLSRVzDsHLBmGYNlt7wQ1xyW8xoHAzg,42
|
| 8 |
+
av-17.1.0.dist-info/licenses/AUTHORS.py,sha256=Tsbg3KPQcDrr77OG0-tu0UoF2W_osKoItSwtKVGBf-w,5558
|
| 9 |
+
av-17.1.0.dist-info/licenses/AUTHORS.rst,sha256=rbOps1qLdLtZcybex3XXSp95tN7KxU2iZqndsgtdoUI,5996
|
| 10 |
+
av-17.1.0.dist-info/licenses/LICENSE.txt,sha256=dq8EYf-5LhnxwURJ6VVX2Dot-qG68gLUnl8dh0bA2hk,1505
|
| 11 |
+
av-17.1.0.dist-info/top_level.txt,sha256=TuQF-stvFHN8ilfr36ctqc7_MR5IOhUqrR0i6i5gNR8,3
|
| 12 |
+
av/.dylibs/libSvtAv1Enc.4.1.0.dylib,sha256=03_ynPMqGaSmMPeJ0c4BfB3LRhOsNSNZZEWXytArJlM,3794416
|
| 13 |
+
av/.dylibs/libavcodec.62.28.101.dylib,sha256=uiuyGtMvKW8fWrYmRtH5tSmQbQt9ok_fBpC4d5GQLN8,12895552
|
| 14 |
+
av/.dylibs/libavdevice.62.3.101.dylib,sha256=k5nEzJxW_6xzAYFIIe5TbHesWnXHElsGj4ClwpiMgxE,117504
|
| 15 |
+
av/.dylibs/libavfilter.11.14.101.dylib,sha256=tEZ_r5VT2eX_Njmicb24q1v78dOdLjSfZRxTaADulag,3677904
|
| 16 |
+
av/.dylibs/libavformat.62.12.101.dylib,sha256=ol2UYQh_MD7BYTWsynflRuUO45xPPx6F9B1S1L9ZmnI,2590944
|
| 17 |
+
av/.dylibs/libavutil.60.26.101.dylib,sha256=9hnr5BVSx3iBTHZMZ_bChOg9-stoftjtmWfjQc8g9CY,743952
|
| 18 |
+
av/.dylibs/libdav1d.7.dylib,sha256=eY_I1aOt9fOzzzqov4lc4sK16ALdk6oLFwSHFrzbF5E,733792
|
| 19 |
+
av/.dylibs/libmp3lame.0.dylib,sha256=_w1pfG7MimNiQPxn1WfgdDQfmYhn0inHhrE8phFdaMU,365152
|
| 20 |
+
av/.dylibs/libopencore-amrnb.0.dylib,sha256=GAEGPnUEyHAtKhzubm70SS2WK54Fy3_FJRXtQV28kS0,267664
|
| 21 |
+
av/.dylibs/libopencore-amrwb.0.dylib,sha256=sTpU9uw9rvpoKJt3dAXssGJx4JAGhivB96FXBZAiCXI,134800
|
| 22 |
+
av/.dylibs/libopus.0.dylib,sha256=3KErgbd49R3FzsvHif_6rEct4JsQKhZNU0izYLI4ogI,636800
|
| 23 |
+
av/.dylibs/libsharpyuv.0.1.2.dylib,sha256=bKMch2QGYuX2rvBGDzuCThktAcWhnLmtENRY2HCXGeQ,85424
|
| 24 |
+
av/.dylibs/libswresample.6.3.101.dylib,sha256=dpZgyuVvnmAod7VXSikVA3KzEz74M-yM0J6ef2feKIg,121632
|
| 25 |
+
av/.dylibs/libswscale.9.5.101.dylib,sha256=Jy_qF8kE9GoReq_GQuYltxiXd72_2uAqX5f7d_gqkcc,1051952
|
| 26 |
+
av/.dylibs/libvpx.12.dylib,sha256=s7b9AW8tpp2ZK91eNf7gx5Z2YWS1RFN9ciogRKLx82Y,1711056
|
| 27 |
+
av/.dylibs/libwebp.7.2.0.dylib,sha256=xjcBQyJkSVMckWMclBuFDFN_8cGGK764apkb12hxQg0,471632
|
| 28 |
+
av/.dylibs/libwebpmux.3.1.2.dylib,sha256=YAXXzM-UE5iY9cXiD3WvCgGQUBRMtgFdRksDTyb8c3U,88112
|
| 29 |
+
av/.dylibs/libx264.165.dylib,sha256=WVUzAsgpqbszMdWc3Jx7czecRh_Dkm4a-a7VM-gHqRs,1545728
|
| 30 |
+
av/.dylibs/libx265.216.dylib,sha256=MONYlYmRtXmyXYFPbii9MMkr15dCWy4jKXqt1UdUNSc,6867472
|
| 31 |
+
av/__init__.pxd,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 32 |
+
av/__init__.py,sha256=vyggkKciHoepXPZUQvVpRRpN-EXIGWAxLkZRZkMMhKI,2249
|
| 33 |
+
av/__main__.py,sha256=x6yMMfLGUHLly2_PlYwsHr1fsZIvaauzPVe3ZAVAuCM,1568
|
| 34 |
+
av/_core.cpython-310-darwin.so,sha256=0dcxA730Zv5XAN9LnGjkGpjVJ0MTkKuXI8xwHFTDLVs,94640
|
| 35 |
+
av/_core.pxd,sha256=uMyjqyDhhL57NCdDjWp-s-1HCxG8E0ebfrjfwQ00qpA,316
|
| 36 |
+
av/_core.py,sha256=M2OoJt4fkxgYYXNOvbvk8OsV4D7dd3gv0TZhs10_3wA,1945
|
| 37 |
+
av/_core.pyi,sha256=FAlEwvbG4HgiXmupnWpi1jebTWRqVvE8QFOTxZhqbp0,251
|
| 38 |
+
av/about.py,sha256=xUHx-wsQuyzyIcA8cLOlUeTP4tcLv4ugTAke4mQ8onY,23
|
| 39 |
+
av/audio/__init__.pxd,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 40 |
+
av/audio/__init__.py,sha256=cKjwtg1eO9LUrcUit-ELFZH1wVtPv8NFLpiyufJA680,91
|
| 41 |
+
av/audio/__init__.pyi,sha256=dl9gWskpaZ1gGDhi3L1tFUPyDFeLmk26DQ1D17jX1yY,259
|
| 42 |
+
av/audio/codeccontext.cpython-310-darwin.so,sha256=-O53UEN_1-Lm8fPpUU4f9FuS2eanTZ0Mr7gxc7guC4g,114464
|
| 43 |
+
av/audio/codeccontext.pxd,sha256=Yf6KxyJRo33v_ceKrqlk404otGtTvxZY-q3W_TISF6M,334
|
| 44 |
+
av/audio/codeccontext.py,sha256=bEDbidpCHIgdSYPu_sTNs9jjQFTPf9AyOORLoGIOElk,3033
|
| 45 |
+
av/audio/codeccontext.pyi,sha256=k-_y8gFQGb8PfDRQQrQ3ygXpLKNRWv1VlcL8Keua-58,1014
|
| 46 |
+
av/audio/fifo.cpython-310-darwin.so,sha256=QbFb00liu7nn8okfaicnCDCadsvnc-fERgcHFF6OB2g,116048
|
| 47 |
+
av/audio/fifo.pxd,sha256=ZTO40EMP15fO1Adm34Qh4TzgQDXeVLLAn08DQlF5Q9c,461
|
| 48 |
+
av/audio/fifo.py,sha256=k9s4mdnTO6BPE56O-ASXigBUyvZd1zTYCEQ__aFPPxg,7200
|
| 49 |
+
av/audio/fifo.pyi,sha256=I_nzPMFexnhzLcPZVjFQvIMevxrEHsEQxSjKmBdvh4E,712
|
| 50 |
+
av/audio/format.cpython-310-darwin.so,sha256=nZXeL2qrgawz3EhvKy-5iE91KBU8UqbLrAk2LMN0uAs,113728
|
| 51 |
+
av/audio/format.pxd,sha256=vDyHNUlO76PM9Yo8mMxMxJPsa2KRJg4d9_Klq84PNW4,148
|
| 52 |
+
av/audio/format.py,sha256=2kB8ndKkELpN7E803KnY13Q1DD0JiQAvYmqezKhdKqQ,3629
|
| 53 |
+
av/audio/format.pyi,sha256=SrRDgZkJ8kzKtywq2htlbJKK3d2ae9PIL-Qcnyoui8s,236
|
| 54 |
+
av/audio/frame.cpython-310-darwin.so,sha256=EsD35r3YxCrVISyVuuuFoFtfAjAR1HhGOtXSbSr7z9A,136672
|
| 55 |
+
av/audio/frame.pxd,sha256=yRuyThzIm-1HI5qCGAQkhawW77vKaDTADBfb793C5Zc,739
|
| 56 |
+
av/audio/frame.py,sha256=ErZJplmdIDZlLdJ__RyZSqyEQE7wPeJbg4_cQkFlTSw,6076
|
| 57 |
+
av/audio/frame.pyi,sha256=p1VeBhOkXSn7X87pT1wRvbkidKdQoWy4CV8eWXCqYoM,1419
|
| 58 |
+
av/audio/layout.cpython-310-darwin.so,sha256=UBV4H-85sNPLkpiyB-ZUx4Co5cqdbf_x0YTke5J8_Kg,120880
|
| 59 |
+
av/audio/layout.pxd,sha256=YQDkPvukGLIRgvHmWFpMKYCqyYWbpMZoQdGmMuy9peE,148
|
| 60 |
+
av/audio/layout.py,sha256=9X-epVscUsJn44i7QDpB9MP7x08XjWyPYRl6DI_e0X4,3227
|
| 61 |
+
av/audio/layout.pyi,sha256=cc0Y9RCsei824HWwZUt00tYAus92FKgIHuUk07lpEZw,250
|
| 62 |
+
av/audio/plane.cpython-310-darwin.so,sha256=llrfNGx3dwRgzzmLPv9ui-zjDPNQOa-ShCx1yGKSBYg,95104
|
| 63 |
+
av/audio/plane.pxd,sha256=H1vKYhmpwMOlz47ba0HeeMamzgeFfvxX7y_M1fZqrr0,132
|
| 64 |
+
av/audio/plane.py,sha256=7tPNSBKjRk5q4zqciYZr8TPFsXL7d_Afs7gAlvaHfIk,421
|
| 65 |
+
av/audio/plane.pyi,sha256=84IuSlDcyAhLh1wR-QPer4s0mfFVvF-yc88v0qfPntQ,74
|
| 66 |
+
av/audio/resampler.cpython-310-darwin.so,sha256=cGVKqGgXUXb3AqTxEGKm6UBWPIAc6plfHQfsWKLfKQ0,133200
|
| 67 |
+
av/audio/resampler.pxd,sha256=SbWg7wXGtLNTs34Bc4Hh-5mhmFdTq45Qc4AuzBgdBGE,490
|
| 68 |
+
av/audio/resampler.py,sha256=khcRspEQq9j9nt1MaNBzT-rAWNtH1q4FFFYEU5v_Ro0,4089
|
| 69 |
+
av/audio/resampler.pyi,sha256=dVyEvLOJ3IUN3AXsSYfg77H2Yaz2sIW38sJASH5fHRg,542
|
| 70 |
+
av/audio/stream.cpython-310-darwin.so,sha256=6B98kSPcQWw_kdugqOXra954v8N9GsG95IF6pbj8FY8,114192
|
| 71 |
+
av/audio/stream.pxd,sha256=E38lNdZrVkiNbVLUJo8sgqFLQYb_UVTjOLmhM-cjbbg,209
|
| 72 |
+
av/audio/stream.py,sha256=Evy2eYCN-wBw7EyFbJFmTVVADRPrtVszVwwuWUS8Q9g,1628
|
| 73 |
+
av/audio/stream.pyi,sha256=9OcxV5qNCwxGBN1vrommvbMfDwHtuumEPsujVw2ysbI,989
|
| 74 |
+
av/bitstream.cpython-310-darwin.so,sha256=zmUSpQRTgmsnFE8mW2drnCE6YN0EvxLnbptbvzQsbKM,112608
|
| 75 |
+
av/bitstream.pxd,sha256=hi30kwIdgdCQEVjtUqXo2L4gioHU_1_yWgKu3SqCgTc,184
|
| 76 |
+
av/bitstream.py,sha256=jaDTJdPFYu4M14FA9hioVjuevfOmxR1-A9ZEhnVgkV0,3313
|
| 77 |
+
av/bitstream.pyi,sha256=CuumhPlDJV91iKtUpJDcuvPxighE9q2FzYmc0qtIN7A,389
|
| 78 |
+
av/buffer.cpython-310-darwin.so,sha256=noqlSrH7YncV4nHluSk2RWD4qlajjCwpV8IexVMMMGQ,116576
|
| 79 |
+
av/buffer.pxd,sha256=KYPVOIDVZ-RTj-tSPRrYxyGIgrekKXt3kQSquZb6Ycw,363
|
| 80 |
+
av/buffer.py,sha256=2cUibrqxK1jPPYAqehLzYY8RYplDdpHsMRDxBzAosvM,2900
|
| 81 |
+
av/buffer.pyi,sha256=0JCfkCBhhP3a3-_1AIhMf4sbNYJ1Uyy8GOrQ5-U4EVs,316
|
| 82 |
+
av/codec/__init__.pxd,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 83 |
+
av/codec/__init__.py,sha256=vOJ3lfD1Z0iSXqq4bED5mCDocxBo7YJCujk3-1N9SYQ,298
|
| 84 |
+
av/codec/codec.cpython-310-darwin.so,sha256=7XINcriu-LdckMGeIJrwTmJ7GpsT754uzAVd4vgNC9w,155760
|
| 85 |
+
av/codec/codec.pxd,sha256=0yZubvg-MpyJ4t2JalN-BIxKB_zJM1VcG4s3iZpy_Is,263
|
| 86 |
+
av/codec/codec.py,sha256=-U_OeiGpajjVJvCc4vB3l1sO7_ZXM7EGaeIM0EFNMgc,13948
|
| 87 |
+
av/codec/codec.pyi,sha256=6PSfYZ1zKzm3Ks7HA4k06dK9tNqiUezDGi3GxXxBJBk,4716
|
| 88 |
+
av/codec/context.cpython-310-darwin.so,sha256=sKq8AJCh_YV5MiMcPnebnVAECDspKdoZTS7hOOOd90c,201488
|
| 89 |
+
av/codec/context.pxd,sha256=s9aYw4PhlB_1eLk3_xO0PKmNwY49D--sya9cCLs6Tio,2500
|
| 90 |
+
av/codec/context.py,sha256=rZXwZl-PUKRVJMITUKOhKR39T6-4Ks8KPk_9Maigf2g,24736
|
| 91 |
+
av/codec/context.pyi,sha256=7NgxSKjx8ha9XpTSDufWNNlOp8CEpRaeSlRPEHBNtao,3489
|
| 92 |
+
av/codec/hwaccel.cpython-310-darwin.so,sha256=LacZACRRTchlGNvKiKd4DxHsTKm1o6zuOa9Ub5HAZI4,137600
|
| 93 |
+
av/codec/hwaccel.pxd,sha256=TkULWTlVpZLOh1jO4BsoqsXy-5WNVXsYWYLR0G_UmWQ,595
|
| 94 |
+
av/codec/hwaccel.py,sha256=szSAcz08Vv7x-QhoaLXKn4uTKrD09y_lf4x60QihqQE,5989
|
| 95 |
+
av/codec/hwaccel.pyi,sha256=41bocToAsL_EGlqZ1TmuMlj5oZtW7VCCbPnKyErZieY,1493
|
| 96 |
+
av/container/__init__.pxd,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 97 |
+
av/container/__init__.py,sha256=_GTpNeXz0bo93otTZ3v6fhS9238ZjOobn3CRQv2dd94,148
|
| 98 |
+
av/container/__init__.pyi,sha256=OvEGnWBxXGuuGVG9n8raY8mfhsO5JKM7PiG9NF1xHzQ,63
|
| 99 |
+
av/container/core.cpython-310-darwin.so,sha256=7JrW4G3UUl8fx5ApDsLsAgXs2h0MUOR6dMaS_3xz3YI,195888
|
| 100 |
+
av/container/core.pxd,sha256=4XQTllGfo_8SlO0PUaflJwgiTmAxEO5UuOAYGmn5gGU,1342
|
| 101 |
+
av/container/core.py,sha256=k-h5nHbTvgYl51Cin1kbe1S1pIPyUFIOVo0en_OG9-A,22015
|
| 102 |
+
av/container/core.pyi,sha256=P78wYuSBoJbzyMDVzFU9S-mCVzpqmW-PShl4vkOZ_Ng,5310
|
| 103 |
+
av/container/input.cpython-310-darwin.so,sha256=rakxQieyt5B4JXo1z-qTnbmz52tL574fzGsTHRsRq20,157504
|
| 104 |
+
av/container/input.pxd,sha256=57CHqOcDRcXRvPinfLwG8Z83FI3hjGGTT07SDQqNMws,162
|
| 105 |
+
av/container/input.py,sha256=KXzU_WsZxbW1HZAdmgx9Gz2MOSIyTshS84aRftHkD6g,12032
|
| 106 |
+
av/container/input.pyi,sha256=wIl7b-Mb0AWG9YX0eAuIH0IXxMlykrbCrfdXORPiVY8,3083
|
| 107 |
+
av/container/output.cpython-310-darwin.so,sha256=wFhdcdUxCSLDoAGY1gkAd3VOjBxKxRi8s4VNmdEthi8,156176
|
| 108 |
+
av/container/output.pxd,sha256=5A0l7ZNR0SOrA5PjwHIYllKYcnaWxSHBgtmOjyqObM8,199
|
| 109 |
+
av/container/output.py,sha256=L_PkvUyvo-4oO_g13NEK2NlCIim4DJAuABnrLAre5zU,22698
|
| 110 |
+
av/container/output.pyi,sha256=ZgWgGOlxILO55JUUGQV-xp6qHDeJArBTRxhIgU6ozjw,2113
|
| 111 |
+
av/container/pyio.cpython-310-darwin.so,sha256=7ojK51QvYR0uKSw3ftyUzwzX7SPmtbSrW2LWqk7RLwc,113696
|
| 112 |
+
av/container/pyio.pxd,sha256=Q1wOsyR09k5h4dS-wjk_CjkASabD3hDQ71W8FXvGjTQ,729
|
| 113 |
+
av/container/pyio.py,sha256=yoa1EhrDWPYPIZml_Hp320vghWLR2bSYTNlwEuwGa-c,6329
|
| 114 |
+
av/container/streams.cpython-310-darwin.so,sha256=pD9DGzuH9sKLYMecx3QjTcIw8rO5Ua_p3PP-fC4RQXE,159696
|
| 115 |
+
av/container/streams.pxd,sha256=iHkTkzM1Ybs6VIuRfPuRkXFK1gayI3li95G-euLEmSY,151
|
| 116 |
+
av/container/streams.py,sha256=ulTig1f-lCmycDJ5WuBGFpYucaszcKvNC8M0NiNGZMY,5312
|
| 117 |
+
av/container/streams.pyi,sha256=iuiJVhIlU-j6CtknPXxmxtePZ1aj7Ad0HnKsl4mTe_M,1140
|
| 118 |
+
av/datasets.py,sha256=crxN4-UwGSOG6eHNfli7kSnOgwc3SK8fnY-p8Hje4Cc,3094
|
| 119 |
+
av/device.cpython-310-darwin.so,sha256=rkfPyS-aPzimOoguv2WxVS_toosqhwPMxu7WOElP8o0,137344
|
| 120 |
+
av/device.py,sha256=HBpdY2GDcrq24V3R4UYn6kumlOIhJTOJc9Euc6RiHRg,6334
|
| 121 |
+
av/device.pyi,sha256=Ak39HPSoHGutW2UYt6_kxcZU7izvegAZf8axEOpv208,516
|
| 122 |
+
av/dictionary.cpython-310-darwin.so,sha256=gfhhvXn0PUoCMCzQDQQYMzrAnbfUABjJgpB2x-2OXGY,138416
|
| 123 |
+
av/dictionary.pxd,sha256=zNNJW_zfBKILR23fwcUffhXjK2SFS316H_bbbKGOa2Y,168
|
| 124 |
+
av/dictionary.py,sha256=odsCuz3YOn21-I0IaX4tCPQ9bZ28xOWM9VF25O3Ehbk,2299
|
| 125 |
+
av/dictionary.pyi,sha256=bf3eGEu0DwMJvWm4ulnVkJrqHFMqREa76SDceO-wVks,605
|
| 126 |
+
av/error.cpython-310-darwin.so,sha256=3fokdi0E_REPCGXBbTja8Ww7aZVAg-bDZwsrx8QOpFw,227344
|
| 127 |
+
av/error.pxd,sha256=pIFybV6fBCAI3IveFVMnEv_9S_f8xv1ZCwRYHvbLaVQ,88
|
| 128 |
+
av/error.py,sha256=5T9fI20pP-RbJmeb5yEc0CBeNUcIrPm_LaBM2cKzMGc,11999
|
| 129 |
+
av/error.pyi,sha256=ohKxnWMullPZ8ntE2inFQ7FrGNmitxNxFWW3Q3hdYDc,3213
|
| 130 |
+
av/filter/__init__.pxd,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 131 |
+
av/filter/__init__.py,sha256=3PhVQg5b52PMmAaJf2pmMKbScTvo7cvKSa_1Zprd0gk,117
|
| 132 |
+
av/filter/__init__.pyi,sha256=Jkfg79hkGdMuvHM5_rIK_YyP1flJJqlpSrV6w-znzig,90
|
| 133 |
+
av/filter/context.cpython-310-darwin.so,sha256=EyC2fvDnLI1So6pN6m6M0s8ZyRoWvdFkf2Uq1_xzBwU,217984
|
| 134 |
+
av/filter/context.pxd,sha256=ytFXp6WCjHWm89b2hs4xQpVEv9H9MqiOQFtYhrCyxho,388
|
| 135 |
+
av/filter/context.py,sha256=l2SRAc6_M6C9VYA-f1OnyFhLRIkqpqG7sYHY8zA_AS4,5873
|
| 136 |
+
av/filter/context.pyi,sha256=Mm1IwQXDdSoQjnebdIE5EDInxWHWj9HPDNSbFrVtOzg,559
|
| 137 |
+
av/filter/filter.cpython-310-darwin.so,sha256=QD_GRFtmhjc2EL4eVpLt8_JMMrT8PxeDjNAJCpyH0u0,95680
|
| 138 |
+
av/filter/filter.pxd,sha256=5w87wK9ugRAc8qUHPJ5f-iB0MW3aIHXk1BiaF4jqTNM,175
|
| 139 |
+
av/filter/filter.py,sha256=h0OMjEcDdu4hCdP2fEuPj-V_1IPmAgTkr1MYRzmVZAc,1639
|
| 140 |
+
av/filter/filter.pyi,sha256=Poi6pctZayAf1g23SAzu8LqZCXUuzn74Zv7m966YL58,141
|
| 141 |
+
av/filter/graph.cpython-310-darwin.so,sha256=qaSzzFjOMN4yQZCvG1BfFg5g0TDgj8htLp0tPWYK-ts,153712
|
| 142 |
+
av/filter/graph.pxd,sha256=cd1UIcvghDMORxJ-qtm0fsTc3rtTEIvUKdM65BH0KSo,600
|
| 143 |
+
av/filter/graph.py,sha256=4cSbAxm1o7I8PzPEQGy_a9oaqkMiUlJjEfEQJVXUB60,9379
|
| 144 |
+
av/filter/graph.pyi,sha256=VZN2ltBYNMBjcjfaNO5vZG9wfZDAYYXAZjZUxX0ih10,1677
|
| 145 |
+
av/filter/link.cpython-310-darwin.so,sha256=tRIVVDGaSXC1jCP5lMzMx1H6mfIXSWzQ7SDybIDg5Rw,117872
|
| 146 |
+
av/filter/link.pxd,sha256=qyA9oQF1M975aafIF1X5JpD6TW-3R8B8VTHckbQKEZU,786
|
| 147 |
+
av/filter/link.py,sha256=UmXTU3ZtwM3100Mut1B0h6kjyqbQA_HGWnHQwlawiMk,4537
|
| 148 |
+
av/filter/link.pyi,sha256=UtgqwA_9EV5w311swXpS9pwZzruTl-nHtU7-hpEt5u4,27
|
| 149 |
+
av/filter/loudnorm.cpython-310-darwin.so,sha256=xN2cqxMS0dFQiQUkobv3wHXLRZ5f0GDldkZVUzKnCSs,113856
|
| 150 |
+
av/filter/loudnorm.pxd,sha256=mrKiGSe6WnIrMkDJU8uj1fs0Iwz_kxFPDL_NmnveyUE,464
|
| 151 |
+
av/filter/loudnorm.py,sha256=OuTHzqHjkKOkOcKP3Pus2SXr_Giw4ZwaDToHxo5sfvU,1439
|
| 152 |
+
av/filter/loudnorm.pyi,sha256=N_HuXpQlTaZLpnKjfqMk68ac3djymdy3x_9en33sA74,106
|
| 153 |
+
av/filter/loudnorm_impl.c,sha256=2ixg15rxo_m92kdwuCvYhkQF8NB_LV_RSEVNyZKtVRw,6251
|
| 154 |
+
av/filter/loudnorm_impl.h,sha256=QmUqnvobMbPSmas5haev86WCVAs_a6iXaAZPwx-iVAk,240
|
| 155 |
+
av/format.cpython-310-darwin.so,sha256=YCM-84krV0Wf9C0GaNsj6v1f0OlHHO0cw_m5UsHgekc,115568
|
| 156 |
+
av/format.pxd,sha256=VbCPLqdb49zGSiOdyc4nk1IQA7JD1VChFyshmjV8mu4,258
|
| 157 |
+
av/format.py,sha256=7bz0zL_-2EjpQUR1Hg0qkJkIwo0kZEXHpGvIU7DXV4E,5571
|
| 158 |
+
av/format.pyi,sha256=dh49OMLec0IadFEiQxZ0-VKyu9eP0NDI1yDk8HrU6RY,1403
|
| 159 |
+
av/frame.cpython-310-darwin.so,sha256=Au5VkoaZTw4lOSmoQhOUDmvmf6t9qBE4op5Xt5haxh4,116304
|
| 160 |
+
av/frame.pxd,sha256=MdtAffABVLDFi_c5oQFm3lT-n6xVbya8IBEsppbf6tU,411
|
| 161 |
+
av/frame.py,sha256=vObiqHSJK26RP2AdL8pC9q3XvvRqgog_yUd6BUFOl_M,5801
|
| 162 |
+
av/frame.pyi,sha256=tyk7ffzDSOY6IiOXDeu1GThIguICv9Eb_wwZjULFMLE,532
|
| 163 |
+
av/index.cpython-310-darwin.so,sha256=NsSL-LYeR-1wOHd3nq0ROX8h_K9tos1mYcFsCsEAKG0,139264
|
| 164 |
+
av/index.pxd,sha256=rPkSQuLLTZfmLFnRCzhEoj_y1WIDsflw2zmMy2YNCIw,290
|
| 165 |
+
av/index.py,sha256=E_SscIwgHeKGTbZk1ywpuMdreK1i8w-QQCKA5Xvb5k4,4288
|
| 166 |
+
av/index.pyi,sha256=Y7Y-_CoaScDyAzZWVW4uURzwD1Z6cRBBawD-R43Mv_Y,559
|
| 167 |
+
av/logging.cpython-310-darwin.so,sha256=eKt-4Tow3dhRs31mstgy2_b4hUnUdxVjMCdOlB9Gv4Y,154192
|
| 168 |
+
av/logging.pxd,sha256=tFpeiXuAHyp6bhB0pBnmpHqG3gL3mXW4pNl6SSXQeNI,319
|
| 169 |
+
av/logging.py,sha256=ybuJeXaQJPQcpyG4gReUMn2wparbWGSLB8CI5GLil0M,10388
|
| 170 |
+
av/logging.pyi,sha256=Afqq5ud46eh617UM6b_D3xpIisdz9uyxvKK4rK1n6RA,885
|
| 171 |
+
av/opaque.cpython-310-darwin.so,sha256=WZxW0r5A6FfvgJ7sfbWg_ZC9QAMZ5PrvR2m_CBHUeW0,95040
|
| 172 |
+
av/opaque.pxd,sha256=vRgs17rMhB8CuiZ450z30WmSi6VMTiirDQr8ykLPwJs,236
|
| 173 |
+
av/opaque.py,sha256=9YwOMEm3CfLK2eq-F59XXqdRQ1uIo1MDjYHU4U177og,1741
|
| 174 |
+
av/packet.cpython-310-darwin.so,sha256=l_iZ6-iUrtmYL3jqS0RwxMG2vlMick5BIy-18dKUyFw,164224
|
| 175 |
+
av/packet.pxd,sha256=7L5wqv7vzE4yZUwAAcducxIdIVMvVXrqSKprNrTGiIo,561
|
| 176 |
+
av/packet.py,sha256=KX91fT4iKg1cBLPjPYU-bhSiHRc5U1ZzEwHwbL3C3-g,14054
|
| 177 |
+
av/packet.pyi,sha256=s91OVOX0OK65OF0zC-d2e1tlwjA2vSJF7inTQIO1zto,3232
|
| 178 |
+
av/plane.cpython-310-darwin.so,sha256=LlkYLgNwShD43ACDvJfCNpve3y1O7rPv8d2NqpDr2Go,112624
|
| 179 |
+
av/plane.pxd,sha256=eOzjPaCDVvvaygHiTXmm477_bmwZZ5bDo4gqKZczvxE,194
|
| 180 |
+
av/plane.py,sha256=FFCfzCS3XmzjQuHjFhmWWtPkoxMIirsz-O980CGn-nQ,626
|
| 181 |
+
av/plane.pyi,sha256=qJLw7M73ekThXf05LqTllf1BLIfF3gckxEy6rEjKx4U,169
|
| 182 |
+
av/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 183 |
+
av/sidedata/__init__.pxd,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 184 |
+
av/sidedata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 185 |
+
av/sidedata/encparams.cpython-310-darwin.so,sha256=jyj0xVH7NsTDhxmNklir8CHF1k4ytJ3OSoUm3vxOsgI,135280
|
| 186 |
+
av/sidedata/encparams.pxd,sha256=1ovAOjIZKwCm9KV_lxtY9kmUqNuuwmWI0nktf4hiRe0,181
|
| 187 |
+
av/sidedata/encparams.py,sha256=Xg86RTjso4gXAwaIdSHmvOjO2VuBrWG5wUJadWbfVvE,6047
|
| 188 |
+
av/sidedata/encparams.pyi,sha256=BebTdGqqzNLY8_7hkrW2poXWMuIeY4O-kBSXVvh0mUo,571
|
| 189 |
+
av/sidedata/motionvectors.cpython-310-darwin.so,sha256=X2bNO91DOrbaAYVX02PTjjgPpicx6wUAWgORvMJBaOs,142240
|
| 190 |
+
av/sidedata/motionvectors.pxd,sha256=QetgIOGElsOMJokp9KIvYM0pH2L8x5cR995HaNZc1Eo,269
|
| 191 |
+
av/sidedata/motionvectors.py,sha256=Toavw_91yx92lleFT8U0FZowmeQSN3k95wrrIQkL0uU,3557
|
| 192 |
+
av/sidedata/motionvectors.pyi,sha256=p_9dVgneh52OdrdK4CRdZYg2ACZHrlRwEcbrbLH3rqA,536
|
| 193 |
+
av/sidedata/sidedata.cpython-310-darwin.so,sha256=xE9qQGHVIYdkPKFbl8EuZjmTaQ9ztgbEVOYqviY-9Ao,137056
|
| 194 |
+
av/sidedata/sidedata.pxd,sha256=OWx1tWeGoYHPLgRzFZbVBAe9WPHvLSeDVv4Wd5Q06AY,447
|
| 195 |
+
av/sidedata/sidedata.py,sha256=Fsmqu4ESFUH5J9F4czb54AR8jmUGIEOQ9N6KPM_Ot64,4671
|
| 196 |
+
av/sidedata/sidedata.pyi,sha256=MaoM-BKdFEQoZ2muFfC4Qxkg3Q4b_sFyGXY7tGLRjHs,1969
|
| 197 |
+
av/stream.cpython-310-darwin.so,sha256=HOxBV_gl-8Tx6J93pn6PtFGd9Nqjoj9w9csvk_UDi44,137712
|
| 198 |
+
av/stream.pxd,sha256=kV-xU37bzdL1PMCPh66SYuPfZbqYHH5MLFv2EIj8WcA,768
|
| 199 |
+
av/stream.py,sha256=UuZhLDj3dWz2TKGnYHORoU554ggoqWfkNGhkRTQVabo,9932
|
| 200 |
+
av/stream.pyi,sha256=7frqrvvwTOk6ImtQ_iKsdep0wW1_FlVMjAopeykKjUY,1966
|
| 201 |
+
av/subtitles/__init__.pxd,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 202 |
+
av/subtitles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 203 |
+
av/subtitles/codeccontext.cpython-310-darwin.so,sha256=H6LVP3STJq2QU4h2tEhzyay4GF-S-mIVH1Kjepq651s,113952
|
| 204 |
+
av/subtitles/codeccontext.pxd,sha256=lrG4G4JEvUyWbVFtqXv7u_9f8SH1kTgBLNqAJHvclbk,235
|
| 205 |
+
av/subtitles/codeccontext.py,sha256=IzfeuX5NEJmWeBaYuQMNGKDG5ukFtc2VTjpL1kclkY8,4722
|
| 206 |
+
av/subtitles/codeccontext.pyi,sha256=HcPuzR5BuwD0Ph4OnUHfIUXJFqeuN6pjo1N0886v0ao,385
|
| 207 |
+
av/subtitles/stream.cpython-310-darwin.so,sha256=nd_SW2u6xdTDTKxFzRccb0YM7yeJngv4C7ieivg7P_Q,95312
|
| 208 |
+
av/subtitles/stream.pxd,sha256=Lo4RBTTOWErzKgNqc07AoNDaAgkUsF_Q25DJaAIo52Y,137
|
| 209 |
+
av/subtitles/stream.py,sha256=r0gPhz3vP5VRiOuGM_sL8uS3nDRmSlPp9h8MiscWoDI,645
|
| 210 |
+
av/subtitles/stream.pyi,sha256=rGoPESxKYF9DD9f0PeMkLd-QwT01D-GA-dhwF60gtwM,343
|
| 211 |
+
av/subtitles/subtitle.cpython-310-darwin.so,sha256=wH6wmH_8MiJGBPalm3qKH5EaRCIviGvLm_6l3R7ydPc,184416
|
| 212 |
+
av/subtitles/subtitle.pxd,sha256=N_QwXo5kimdZY-T2SxIowRkqiD38qHA4MEjOaZD619A,590
|
| 213 |
+
av/subtitles/subtitle.py,sha256=Vef8bw1ffc5UbxdjX8NA0ro9c2-rP3_8AeFlq8opsVo,10151
|
| 214 |
+
av/subtitles/subtitle.pyi,sha256=DXZ_0nKzZcGOnzKlS1AWGXPdAb8FiG5xdJqDQx-SgLk,984
|
| 215 |
+
av/utils.cpython-310-darwin.so,sha256=j_11r0SmVV1aDttlx7ONyaDXW7isw1LAcGkb4mNxehk,94560
|
| 216 |
+
av/utils.pxd,sha256=NGyU6Ve4JWjw2Epk0-8se5D3FRUm56VhL72j-V6AJiA,366
|
| 217 |
+
av/utils.py,sha256=F1DNSuNIRbtF9-1blgXPKgBlCVSCPpD3vPFyGvnify4,2008
|
| 218 |
+
av/video/__init__.pxd,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 219 |
+
av/video/__init__.py,sha256=Vq396L7PMjMhTDhvFZPbcLqU9mgdAR82NWk1K08QH64,91
|
| 220 |
+
av/video/__init__.pyi,sha256=zTUgi5b-SF1D9iR0IFZjjWmnrWikVSk6Sn5P4NAj0mA,262
|
| 221 |
+
av/video/codeccontext.cpython-310-darwin.so,sha256=b5Yl8QxUpJlzj_2XUzF_9LzPhgw2d7IPzbGKcoFH7nc,137680
|
| 222 |
+
av/video/codeccontext.pxd,sha256=vLe2JHf4XxfOwXmJOFLAcVBfe4Me773ZnXpiLngmD2c,875
|
| 223 |
+
av/video/codeccontext.py,sha256=fvVox-YN84itXJs34wH-BSQkuPAqEJS5jKVNNzecR7g,11860
|
| 224 |
+
av/video/codeccontext.pyi,sha256=ord9zvT5MUveSivTg1hWrHOACywxNf5qDlrrTwjGcmY,991
|
| 225 |
+
av/video/format.cpython-310-darwin.so,sha256=Ou0sGl6sqzBvROZuBthDMkSmLqFctirH6_VFeTu8YUA,142592
|
| 226 |
+
av/video/format.pxd,sha256=hUqOV0DEGy8yRhfX1e2I246BcBwaGOWrixhNazO2v-g,686
|
| 227 |
+
av/video/format.py,sha256=d4T5dvkIT7aE1bZcddD2MiesAwf2Lzh9BB29ZijvEL8,6175
|
| 228 |
+
av/video/format.pyi,sha256=XGTdOgcr5YMTR30ozRd9A8KC0NZVhXHl5hh9CxDdcjY,805
|
| 229 |
+
av/video/frame.cpython-310-darwin.so,sha256=Gsvbfzo2qz66XNyg19S11fTlmmV6oCT6A17irgYMX4g,413152
|
| 230 |
+
av/video/frame.pxd,sha256=3VYbrytXp62lxGauju6ormIkLK9mL7yOFdvGVxAk-TQ,869
|
| 231 |
+
av/video/frame.py,sha256=oOJV95C5zdZA9S4hc1RnTBlpjF5YFHzPLzzmc8igg3Y,59254
|
| 232 |
+
av/video/frame.pyi,sha256=_d8xiGAmlt-YEvA4C7fkFsUr9UGmYoNKJBbxKPZL2fQ,3067
|
| 233 |
+
av/video/plane.cpython-310-darwin.so,sha256=oKBQt-liVQR5_ihBjDdzFgHTzNNInFdP7yOx2my772I,117184
|
| 234 |
+
av/video/plane.pxd,sha256=g3qjx6-1cSlBNnFS2Mif4iBkD_VvHA92D_SvbUTd3DY,772
|
| 235 |
+
av/video/plane.py,sha256=ICLTU998bK-un16p8stBAPvPzRuHPIzc5mVzFxHbhAU,10667
|
| 236 |
+
av/video/plane.pyi,sha256=26hYzC63EN31pFyR3GTndf5uYc43vH2zWMaXLS_wMl0,385
|
| 237 |
+
av/video/reformatter.cpython-310-darwin.so,sha256=j75MGLhaZZi2w-2AdR4I056bwfjbpUtj0asoY2zoIks,131616
|
| 238 |
+
av/video/reformatter.pxd,sha256=vR4FvP-xns3o6U8tKN65lNOOrCUZowYAy7HvRk72dv0,1291
|
| 239 |
+
av/video/reformatter.py,sha256=Z-aXlQ92e2eSBhef3mHst9f3IHo6jrBubOVUQSn0uFY,12697
|
| 240 |
+
av/video/reformatter.pyi,sha256=0ikHmHcxY0B3LcQ5X-OBoyqag93qIpoin79q-t82p10,2466
|
| 241 |
+
av/video/stream.cpython-310-darwin.so,sha256=GX-giICn9YYUds8eFpnORhy_h6vIB5a-aVFY4a0A64o,135440
|
| 242 |
+
av/video/stream.pxd,sha256=6z65wy60rKFRpN0rjWd4smgnPOd6P6EzNh3umZenD9c,528
|
| 243 |
+
av/video/stream.py,sha256=xFGIjd-R24ja_Y-hrd3CrCa8vpiKFGtRHfM46qtzwiE,6884
|
| 244 |
+
av/video/stream.pyi,sha256=bFX706QESMaHSi3A2d-wEKaAM4TN-a5vqEQmOuadb50,1416
|
.venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/REQUESTED
ADDED
|
File without changes
|
.venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/WHEEL
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Wheel-Version: 1.0
|
| 2 |
+
Generator: setuptools (82.0.1)
|
| 3 |
+
Root-Is-Purelib: false
|
| 4 |
+
Tag: cp310-cp310-macosx_14_0_arm64
|
| 5 |
+
Generator: delocate 0.13.0
|
| 6 |
+
|
.venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/entry_points.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[console_scripts]
|
| 2 |
+
pyav = av.__main__:main
|
.venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/licenses/AUTHORS.py
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
""" Generate the AUTHORS.rst file from git commit history.
|
| 2 |
+
|
| 3 |
+
This module reads git commit logs and produces a formatted list of contributors
|
| 4 |
+
grouped by their contribution count, mapping email aliases and GitHub usernames.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
from dataclasses import dataclass
|
| 8 |
+
import math
|
| 9 |
+
import subprocess # noqa: S404
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def main() -> None:
|
| 13 |
+
""" Generate and print the AUTHORS.rst content. """
|
| 14 |
+
|
| 15 |
+
contributors = get_git_contributors()
|
| 16 |
+
print_contributors(contributors)
|
| 17 |
+
# ------------------------------------------------------------------------------
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
EMAIL_ALIASES: dict[str, str | None] = {
|
| 21 |
+
# Maintainers.
|
| 22 |
+
"git@mikeboers.com": "github@mikeboers.com",
|
| 23 |
+
"mboers@keypics.com": "github@mikeboers.com",
|
| 24 |
+
"mikeb@loftysky.com": "github@mikeboers.com",
|
| 25 |
+
"mikeb@markmedia.co": "github@mikeboers.com",
|
| 26 |
+
"westernx@mikeboers.com": "github@mikeboers.com",
|
| 27 |
+
# Junk.
|
| 28 |
+
"mark@mark-VirtualBox.(none)": None,
|
| 29 |
+
# Aliases.
|
| 30 |
+
"a.davoudi@aut.ac.ir": "davoudialireza@gmail.com",
|
| 31 |
+
"tcaswell@bnl.gov": "tcaswell@gmail.com",
|
| 32 |
+
"xxr3376@gmail.com": "xxr@megvii.com",
|
| 33 |
+
"dallan@pha.jhu.edu": "daniel.b.allan@gmail.com",
|
| 34 |
+
"61652821+laggykiller@users.noreply.github.com": "chaudominic2@gmail.com",
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
CANONICAL_NAMES: dict[str, str] = {
|
| 38 |
+
"caspervdw@gmail.com": "Casper van der Wel",
|
| 39 |
+
"daniel.b.allan@gmail.com": "Dan Allan",
|
| 40 |
+
"mgoacolou@cls.fr": "Manuel Goacolou",
|
| 41 |
+
"mindmark@gmail.com": "Mark Reid",
|
| 42 |
+
"moritzkassner@gmail.com": "Moritz Kassner",
|
| 43 |
+
"vidartf@gmail.com": "Vidar Tonaas Fauske",
|
| 44 |
+
"xxr@megvii.com": "Xinran Xu",
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
GITHUB_USERNAMES: dict[str, str] = {
|
| 48 |
+
"billy.shambrook@gmail.com": "billyshambrook",
|
| 49 |
+
"daniel.b.allan@gmail.com": "danielballan",
|
| 50 |
+
"davoudialireza@gmail.com": "adavoudi",
|
| 51 |
+
"github@mikeboers.com": "mikeboers",
|
| 52 |
+
"jeremy.laine@m4x.org": "jlaine",
|
| 53 |
+
"kalle.litterfeldt@gmail.com": "litterfeldt",
|
| 54 |
+
"mindmark@gmail.com": "markreidvfx",
|
| 55 |
+
"moritzkassner@gmail.com": "mkassner",
|
| 56 |
+
"rush@logic.cz": "radek-senfeld",
|
| 57 |
+
"self@brendanlong.com": "brendanlong",
|
| 58 |
+
"tcaswell@gmail.com": "tacaswell",
|
| 59 |
+
"ulrik.mikaelsson@magine.com": "rawler",
|
| 60 |
+
"vidartf@gmail.com": "vidartf",
|
| 61 |
+
"willpatera@gmail.com": "willpatera",
|
| 62 |
+
"xxr@megvii.com": "xxr3376",
|
| 63 |
+
"chaudominic2@gmail.com": "laggykiller",
|
| 64 |
+
"wyattblue@auto-editor.com": "WyattBlue",
|
| 65 |
+
"Curtis@GreenKey.net": "dotysan",
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
@dataclass
|
| 70 |
+
class Contributor:
|
| 71 |
+
""" Represents a contributor with their email, names, and GitHub username. """
|
| 72 |
+
|
| 73 |
+
email: str
|
| 74 |
+
names: set[str]
|
| 75 |
+
github: str | None = None
|
| 76 |
+
commit_count: int = 0
|
| 77 |
+
|
| 78 |
+
@property
|
| 79 |
+
def display_name(self) -> str:
|
| 80 |
+
""" Return the formatted display name for the contributor.
|
| 81 |
+
|
| 82 |
+
Returns:
|
| 83 |
+
Comma-separated sorted list of contributor names.
|
| 84 |
+
"""
|
| 85 |
+
|
| 86 |
+
return ", ".join(sorted(self.names))
|
| 87 |
+
|
| 88 |
+
def format_line(self, bullet: str) -> str:
|
| 89 |
+
""" Format the contributor line for RST output.
|
| 90 |
+
|
| 91 |
+
Args:
|
| 92 |
+
bullet: The bullet character to use (- or *).
|
| 93 |
+
|
| 94 |
+
Returns:
|
| 95 |
+
Formatted RST line with contributor info.
|
| 96 |
+
"""
|
| 97 |
+
|
| 98 |
+
if self.github:
|
| 99 |
+
return (
|
| 100 |
+
f"{bullet} {self.display_name} <{self.email}>; "
|
| 101 |
+
f"`@{self.github} <https://github.com/{self.github}>`_"
|
| 102 |
+
)
|
| 103 |
+
return f"{bullet} {self.display_name} <{self.email}>"
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
def get_git_contributors() -> dict[str, Contributor]:
|
| 107 |
+
""" Parse git log and return contributors grouped by canonical email.
|
| 108 |
+
|
| 109 |
+
Returns:
|
| 110 |
+
Dictionary mapping canonical emails to Contributor objects.
|
| 111 |
+
"""
|
| 112 |
+
|
| 113 |
+
contributors: dict[str, Contributor] = {}
|
| 114 |
+
git_log = subprocess.check_output(
|
| 115 |
+
["git", "log", "--format=%aN,%aE"], # noqa: S607
|
| 116 |
+
text=True,
|
| 117 |
+
).splitlines()
|
| 118 |
+
|
| 119 |
+
for line in git_log:
|
| 120 |
+
name, email = line.strip().rsplit(",", 1)
|
| 121 |
+
canonical_email = EMAIL_ALIASES.get(email, email)
|
| 122 |
+
|
| 123 |
+
if not canonical_email:
|
| 124 |
+
continue
|
| 125 |
+
|
| 126 |
+
if canonical_email not in contributors:
|
| 127 |
+
contributors[canonical_email] = Contributor(
|
| 128 |
+
email=canonical_email,
|
| 129 |
+
names=set(),
|
| 130 |
+
github=GITHUB_USERNAMES.get(canonical_email),
|
| 131 |
+
)
|
| 132 |
+
|
| 133 |
+
contributor = contributors[canonical_email]
|
| 134 |
+
contributor.names.add(name)
|
| 135 |
+
contributor.commit_count += 1
|
| 136 |
+
|
| 137 |
+
for email, canonical_name in CANONICAL_NAMES.items():
|
| 138 |
+
if email in contributors:
|
| 139 |
+
contributors[email].names = {canonical_name}
|
| 140 |
+
|
| 141 |
+
return contributors
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
def print_contributors(contributors: dict[str, Contributor]) -> None:
|
| 145 |
+
"""Print contributors grouped by logarithmic order of commits.
|
| 146 |
+
|
| 147 |
+
Args:
|
| 148 |
+
contributors: Dictionary of contributors to print.
|
| 149 |
+
"""
|
| 150 |
+
|
| 151 |
+
print("""\
|
| 152 |
+
Contributors
|
| 153 |
+
============
|
| 154 |
+
|
| 155 |
+
All contributors (by number of commits):
|
| 156 |
+
""".replace(" ", ""))
|
| 157 |
+
|
| 158 |
+
sorted_contributors = sorted(
|
| 159 |
+
contributors.values(),
|
| 160 |
+
key=lambda c: (-c.commit_count, c.email),
|
| 161 |
+
)
|
| 162 |
+
|
| 163 |
+
last_order: int | None = None
|
| 164 |
+
block_index = 0
|
| 165 |
+
|
| 166 |
+
for contributor in sorted_contributors:
|
| 167 |
+
# This is the natural log, because of course it should be. ;)
|
| 168 |
+
order = int(math.log(contributor.commit_count))
|
| 169 |
+
|
| 170 |
+
if last_order and last_order != order:
|
| 171 |
+
block_index += 1
|
| 172 |
+
print()
|
| 173 |
+
last_order = order
|
| 174 |
+
|
| 175 |
+
# The '-' vs '*' is so that Sphinx treats them as different lists, and
|
| 176 |
+
# introduces a gap between them.
|
| 177 |
+
bullet = "-*"[block_index % 2]
|
| 178 |
+
print(contributor.format_line(bullet))
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
if __name__ == "__main__":
|
| 182 |
+
main()
|
.venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/licenses/AUTHORS.rst
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Contributors
|
| 2 |
+
============
|
| 3 |
+
|
| 4 |
+
All contributors (by number of commits):
|
| 5 |
+
|
| 6 |
+
- Mike Boers <github@mikeboers.com>; `@mikeboers <https://github.com/mikeboers>`_
|
| 7 |
+
- WyattBlue <wyattblue@auto-editor.com>; `@WyattBlue <https://github.com/WyattBlue>`_
|
| 8 |
+
|
| 9 |
+
* Jeremy Lainé <jeremy.laine@m4x.org>; `@jlaine <https://github.com/jlaine>`_
|
| 10 |
+
|
| 11 |
+
- Mark Reid <mindmark@gmail.com>; `@markreidvfx <https://github.com/markreidvfx>`_
|
| 12 |
+
|
| 13 |
+
* Lukas Geiger <lukas.geiger94@gmail.com>
|
| 14 |
+
|
| 15 |
+
- Vidar Tonaas Fauske <vidartf@gmail.com>; `@vidartf <https://github.com/vidartf>`_
|
| 16 |
+
- laggykiller <chaudominic2@gmail.com>; `@laggykiller <https://github.com/laggykiller>`_
|
| 17 |
+
- Billy Shambrook <billy.shambrook@gmail.com>; `@billyshambrook <https://github.com/billyshambrook>`_
|
| 18 |
+
- Casper van der Wel <caspervdw@gmail.com>
|
| 19 |
+
- Philip de Nier <philipn@rd.bbc.co.uk>
|
| 20 |
+
- Tadas Dailyda <tadas@dailyda.com>
|
| 21 |
+
- Dave Johansen <davejohansen@gmail.com>
|
| 22 |
+
- Mark Harfouche <mark.harfouche@gmail.com>
|
| 23 |
+
- JoeUgly <41972063+JoeUgly@users.noreply.github.com>
|
| 24 |
+
- Justin Wong <46082645+uvjustin@users.noreply.github.com>
|
| 25 |
+
- Santtu Keskinen <santtu.keskinen@gmail.com>
|
| 26 |
+
|
| 27 |
+
* Alba Mendez <me@alba.sh>
|
| 28 |
+
* Curtis Doty <Curtis@GreenKey.net>; `@dotysan <https://github.com/dotysan>`_
|
| 29 |
+
* Xinran Xu <xxr@megvii.com>; `@xxr3376 <https://github.com/xxr3376>`_
|
| 30 |
+
* z-khan <zohaibkh_27@yahoo.com>
|
| 31 |
+
* Marc Mueller <30130371+cdce8p@users.noreply.github.com>
|
| 32 |
+
* Dan Allan <daniel.b.allan@gmail.com>; `@danielballan <https://github.com/danielballan>`_
|
| 33 |
+
* Moonsik Park <moonsik.park@estsoft.com>
|
| 34 |
+
* velsinki <40809145+velsinki@users.noreply.github.com>
|
| 35 |
+
* Christoph Rackwitz <christoph.rackwitz@gmail.com>
|
| 36 |
+
* David Plowman <david.plowman@raspberrypi.com>
|
| 37 |
+
* Alireza Davoudi <davoudialireza@gmail.com>; `@adavoudi <https://github.com/adavoudi>`_
|
| 38 |
+
* Jonathan Drolet <jonathan.drolet@riedel.net>
|
| 39 |
+
* Matthew Lai <m@matthewlai.ca>
|
| 40 |
+
* Kim Minjong <make.dirty.code@gmail.com>
|
| 41 |
+
* Moritz Kassner <moritzkassner@gmail.com>; `@mkassner <https://github.com/mkassner>`_
|
| 42 |
+
* Thomas A Caswell <tcaswell@gmail.com>; `@tacaswell <https://github.com/tacaswell>`_
|
| 43 |
+
* Ulrik Mikaelsson <ulrik.mikaelsson@magine.com>; `@rawler <https://github.com/rawler>`_
|
| 44 |
+
* Wel C. van der <wel@Physics.LeidenUniv.nl>
|
| 45 |
+
* Will Patera <willpatera@gmail.com>; `@willpatera <https://github.com/willpatera>`_
|
| 46 |
+
|
| 47 |
+
- zzjjbb <31069326+zzjjbb@users.noreply.github.com>
|
| 48 |
+
- Joe Schiff <41972063+JoeSchiff@users.noreply.github.com>
|
| 49 |
+
- Nils DEYBACH <68770774+ndeybach@users.noreply.github.com>
|
| 50 |
+
- Dexer <73297572+DexerBR@users.noreply.github.com>
|
| 51 |
+
- DE-AI <81620697+DE-AI@users.noreply.github.com>
|
| 52 |
+
- rutsh <Eugene.Krokhalev@gmail.com>
|
| 53 |
+
- Felix Vollmer <FelixVollmer@gmail.com>
|
| 54 |
+
- Benedikt Lorch, benedikt-grl <benedikt@getreallabs.com>
|
| 55 |
+
- Santiago Castro <bryant1410@gmail.com>
|
| 56 |
+
- Christian Clauss <cclauss@me.com>
|
| 57 |
+
- Ihor Liubymov <ihor.liubymov@ring.com>
|
| 58 |
+
- Johannes Erdfelt <johannes@erdfelt.com>
|
| 59 |
+
- Karl Litterfeldt <kalle.litterfeldt@gmail.com>; `@litterfeldt <https://github.com/litterfeldt>`_
|
| 60 |
+
- Leon White <l.white@interstellarlab.earth>
|
| 61 |
+
- Martin Larralde <martin.larralde@ens-cachan.fr>
|
| 62 |
+
- Simon-Martin Schröder <martin.schroeder@nerdluecht.de>
|
| 63 |
+
- Matteo Destro <matteo.est@gmail.com>
|
| 64 |
+
- Mattias Wadman <mattias.wadman@gmail.com>
|
| 65 |
+
- mephi42 <mephi42@gmail.com>
|
| 66 |
+
- Miles Kaufmann <mkfmnn@gmail.com>
|
| 67 |
+
- Nathan Goldbaum <nathan.goldbaum@gmail.com>
|
| 68 |
+
- Pablo Prietz <pablo@prietz.org>
|
| 69 |
+
- Andrew Wason <rectalogic@rectalogic.com>
|
| 70 |
+
- Radek Senfeld <rush@logic.cz>; `@radek-senfeld <https://github.com/radek-senfeld>`_
|
| 71 |
+
- robinechuca <serveurpython.oz@gmail.com>
|
| 72 |
+
- Nick <24689722+ntjohnson1@users.noreply.github.com>
|
| 73 |
+
- Benjamin Chrétien <2742231+bchretien@users.noreply.github.com>
|
| 74 |
+
- 吴小白 <296015668@qq.com>
|
| 75 |
+
- davidplowman <38045873+davidplowman@users.noreply.github.com>
|
| 76 |
+
- Hanz <40712686+HanzCEO@users.noreply.github.com>
|
| 77 |
+
- Clay Castronovo <42858023+clayy24@users.noreply.github.com>
|
| 78 |
+
- Kesh Ikuma <79113787+tikuma-lsuhsc@users.noreply.github.com>
|
| 79 |
+
- Artturin <Artturin@artturin.com>
|
| 80 |
+
- Ian Lee <IanLee1521@gmail.com>
|
| 81 |
+
- Ryan Huang <NPN@users.noreply.github.com>
|
| 82 |
+
- Arthur Barros <arthbarros@gmail.com>
|
| 83 |
+
- bdavid-evertz <bdavid@evertz.com>
|
| 84 |
+
- Carlos Ruiz <carlos.r.domin@gmail.com>
|
| 85 |
+
- Carlos Ruiz <carlos.ruiz.dominguez@west.cmu.edu>
|
| 86 |
+
- Maxime Desroches <desroches.maxime@gmail.com>
|
| 87 |
+
- egao1980 <egao1980@gmail.com>
|
| 88 |
+
- Eric Kalosa-Kenyon <ekalosak@gmail.com>
|
| 89 |
+
- elxy <elxy@outlook.com>
|
| 90 |
+
- Gemfield <gemfield@civilnet.cn>
|
| 91 |
+
- henri-gasc <henri.gasc@eurecom.fr>
|
| 92 |
+
- Jonathan Martin <homerunisgood@hotmail.com>
|
| 93 |
+
- HotariTobu <hotari24tools@gmail.com>
|
| 94 |
+
- Joshua <jbree@users.noreply.github.com>
|
| 95 |
+
- Johan Jeppsson Karlin <johjep@gmail.com>
|
| 96 |
+
- Kazuki Oikawa <k@oikw.org>
|
| 97 |
+
- Kian-Meng Ang <kianmeng@cpan.org>
|
| 98 |
+
- Philipp Klaus <klaus@physik.uni-frankfurt.de>
|
| 99 |
+
- Marcell Pardavi <marcell.pardavi@gmail.com>
|
| 100 |
+
- Matteo Destro <matteo@cerrion.com>
|
| 101 |
+
- Max Ehrlich <max.ehr@gmail.com>
|
| 102 |
+
- Manuel Goacolou <mgoacolou@cls.fr>
|
| 103 |
+
- Julian Schweizer <neuneck@gmail.com>
|
| 104 |
+
- Nikhil Idiculla <nikhilidiculla@gmail.com>
|
| 105 |
+
- Ömer Sezgin Uğurlu <omer@ugurlu.org>
|
| 106 |
+
- Orivej Desh <orivej@gmx.fr>
|
| 107 |
+
- Philipp Krähenbühl <philkr@users.noreply.github.com>
|
| 108 |
+
- Mattia Procopio <promat85@gmail.com>
|
| 109 |
+
- Max Ehrlich <queuecumber@protonmail.com>
|
| 110 |
+
- ramoncaldeira <ramoncaldeira_328@hotmail.com>
|
| 111 |
+
- Roland van Laar <roland@rolandvanlaar.nl>
|
| 112 |
+
- Santiago Castro <sacastro@umich.edu>
|
| 113 |
+
- Kengo Sawatsu <seattleserv0@gmail.com>
|
| 114 |
+
- FirefoxMetzger <sebastian@wallkoetter.net>
|
| 115 |
+
- hyenal <sebastien.ehrhardt@gmail.com>
|
| 116 |
+
- Brendan Long <self@brendanlong.com>; `@brendanlong <https://github.com/brendanlong>`_
|
| 117 |
+
- Семён Марьясин <simeon@maryasin.name>
|
| 118 |
+
- Stephen.Y <stepheny@users.noreply.github.com>
|
| 119 |
+
- Tom Flanagan <theknio@gmail.com>
|
| 120 |
+
- Tim O'Shea <tim.oshea753@gmail.com>
|
| 121 |
+
- Tim Ahpee <timah@blackmagicdesign.com>
|
| 122 |
+
- Jonas Tingeborn <tinjon@gmail.com>
|
| 123 |
+
- Pino Toscano <toscano.pino@tiscali.it>
|
| 124 |
+
- Ulrik Mikaelsson <ulrikm@spotify.com>
|
| 125 |
+
- Vasiliy Kotov <vasiliy.kotov@itechart-group.com>
|
| 126 |
+
- Koichi Akabe <vbkaisetsu@gmail.com>
|
| 127 |
+
- David Joy <videan42@gmail.com>
|
| 128 |
+
- Sviatoslav Sydorenko (Святослав Сидоренко) <webknjaz@redhat.com>
|
| 129 |
+
- Jiabei Zhu <zjb@bu.edu>
|
.venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/licenses/LICENSE.txt
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright retained by original committers. All rights reserved.
|
| 2 |
+
|
| 3 |
+
Redistribution and use in source and binary forms, with or without
|
| 4 |
+
modification, are permitted provided that the following conditions are met:
|
| 5 |
+
* Redistributions of source code must retain the above copyright
|
| 6 |
+
notice, this list of conditions and the following disclaimer.
|
| 7 |
+
* Redistributions in binary form must reproduce the above copyright
|
| 8 |
+
notice, this list of conditions and the following disclaimer in the
|
| 9 |
+
documentation and/or other materials provided with the distribution.
|
| 10 |
+
* Neither the name of the project nor the names of its contributors may be
|
| 11 |
+
used to endorse or promote products derived from this software without
|
| 12 |
+
specific prior written permission.
|
| 13 |
+
|
| 14 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
| 15 |
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
| 16 |
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 17 |
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT,
|
| 18 |
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
| 19 |
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| 20 |
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
| 21 |
+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
| 22 |
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
| 23 |
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.venvs/kimodo/lib/python3.10/site-packages/av-17.1.0.dist-info/top_level.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
av
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/codeccontext.cpython-310-darwin.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1fa2d53f749326ad90538876b44873c9acb8185f92fa62151f52a37a9abae75b
|
| 3 |
+
size 113952
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/codeccontext.pxd
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from av.codec.context cimport CodecContext
|
| 2 |
+
from av.packet cimport Packet
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
cdef class SubtitleCodecContext(CodecContext):
|
| 6 |
+
cdef bint subtitle_header_set
|
| 7 |
+
cpdef decode(self, Packet packet=?)
|
| 8 |
+
cpdef decode2(self, Packet packet)
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/codeccontext.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import cython
|
| 2 |
+
from cython.cimports import libav as lib
|
| 3 |
+
from cython.cimports.av.buffer import ByteSource, bytesource
|
| 4 |
+
from cython.cimports.av.codec.context import CodecContext
|
| 5 |
+
from cython.cimports.av.error import err_check
|
| 6 |
+
from cython.cimports.av.packet import Packet
|
| 7 |
+
from cython.cimports.av.subtitles.subtitle import SubtitleProxy, SubtitleSet
|
| 8 |
+
from cython.cimports.cpython.bytes import PyBytes_FromStringAndSize
|
| 9 |
+
from cython.cimports.libc.string import memcpy
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
@cython.final
|
| 13 |
+
@cython.cclass
|
| 14 |
+
class SubtitleCodecContext(CodecContext):
|
| 15 |
+
@property
|
| 16 |
+
def subtitle_header(self) -> bytes | None:
|
| 17 |
+
"""Get the subtitle header data (ASS/SSA format for text subtitles)."""
|
| 18 |
+
if (
|
| 19 |
+
self.ptr.subtitle_header == cython.NULL
|
| 20 |
+
or self.ptr.subtitle_header_size <= 0
|
| 21 |
+
):
|
| 22 |
+
return None
|
| 23 |
+
return PyBytes_FromStringAndSize(
|
| 24 |
+
cython.cast(cython.p_char, self.ptr.subtitle_header),
|
| 25 |
+
self.ptr.subtitle_header_size,
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
@subtitle_header.setter
|
| 29 |
+
def subtitle_header(self, data: bytes | None) -> None:
|
| 30 |
+
"""Set the subtitle header data."""
|
| 31 |
+
source: ByteSource
|
| 32 |
+
if data is None:
|
| 33 |
+
lib.av_freep(cython.address(self.ptr.subtitle_header))
|
| 34 |
+
self.ptr.subtitle_header_size = 0
|
| 35 |
+
else:
|
| 36 |
+
source = bytesource(data)
|
| 37 |
+
self.ptr.subtitle_header = cython.cast(
|
| 38 |
+
cython.p_uchar,
|
| 39 |
+
lib.av_realloc(
|
| 40 |
+
self.ptr.subtitle_header,
|
| 41 |
+
source.length + lib.AV_INPUT_BUFFER_PADDING_SIZE,
|
| 42 |
+
),
|
| 43 |
+
)
|
| 44 |
+
if not self.ptr.subtitle_header:
|
| 45 |
+
raise MemoryError("Cannot allocate subtitle_header")
|
| 46 |
+
memcpy(self.ptr.subtitle_header, source.ptr, source.length)
|
| 47 |
+
self.ptr.subtitle_header_size = source.length
|
| 48 |
+
self.subtitle_header_set = True
|
| 49 |
+
|
| 50 |
+
def __dealloc__(self) -> None:
|
| 51 |
+
if self.ptr and self.subtitle_header_set:
|
| 52 |
+
lib.av_freep(cython.address(self.ptr.subtitle_header))
|
| 53 |
+
|
| 54 |
+
def encode_subtitle(self, subtitle: SubtitleSet) -> Packet:
|
| 55 |
+
"""
|
| 56 |
+
Encode a SubtitleSet into a Packet.
|
| 57 |
+
|
| 58 |
+
Args:
|
| 59 |
+
subtitle: The SubtitleSet to encode
|
| 60 |
+
|
| 61 |
+
Returns:
|
| 62 |
+
A Packet containing the encoded subtitle data
|
| 63 |
+
"""
|
| 64 |
+
if not self.codec.ptr:
|
| 65 |
+
raise ValueError("Cannot encode with unknown codec")
|
| 66 |
+
|
| 67 |
+
self.open(strict=False)
|
| 68 |
+
|
| 69 |
+
buf: cython.p_uchar = cython.cast(cython.p_uchar, lib.av_malloc(1024 * 1024))
|
| 70 |
+
if buf == cython.NULL:
|
| 71 |
+
raise MemoryError()
|
| 72 |
+
|
| 73 |
+
ret: cython.int = lib.avcodec_encode_subtitle(
|
| 74 |
+
self.ptr,
|
| 75 |
+
buf,
|
| 76 |
+
1024 * 1024,
|
| 77 |
+
cython.address(subtitle.proxy.struct),
|
| 78 |
+
)
|
| 79 |
+
if ret < 0:
|
| 80 |
+
lib.av_free(buf)
|
| 81 |
+
err_check(ret, "avcodec_encode_subtitle()")
|
| 82 |
+
|
| 83 |
+
packet: Packet = Packet(ret)
|
| 84 |
+
memcpy(packet.ptr.data, buf, ret)
|
| 85 |
+
lib.av_free(buf)
|
| 86 |
+
packet.ptr.pts = subtitle.proxy.struct.pts
|
| 87 |
+
packet.ptr.dts = subtitle.proxy.struct.pts
|
| 88 |
+
packet.ptr.duration = (
|
| 89 |
+
subtitle.proxy.struct.end_display_time
|
| 90 |
+
- subtitle.proxy.struct.start_display_time
|
| 91 |
+
)
|
| 92 |
+
|
| 93 |
+
return packet
|
| 94 |
+
|
| 95 |
+
@cython.ccall
|
| 96 |
+
def decode(self, packet: Packet | None = None):
|
| 97 |
+
"""Decode a subtitle packet, returning a list of :class:`.Subtitle` objects
|
| 98 |
+
if a subtitle was decoded, or an empty list otherwise."""
|
| 99 |
+
if not self.codec.ptr:
|
| 100 |
+
raise ValueError("cannot decode unknown codec")
|
| 101 |
+
|
| 102 |
+
if packet is None:
|
| 103 |
+
raise RuntimeError("packet cannot be None")
|
| 104 |
+
|
| 105 |
+
self.open(strict=False)
|
| 106 |
+
proxy: SubtitleProxy = SubtitleProxy()
|
| 107 |
+
got_frame: cython.int = 0
|
| 108 |
+
|
| 109 |
+
err_check(
|
| 110 |
+
lib.avcodec_decode_subtitle2(
|
| 111 |
+
self.ptr,
|
| 112 |
+
cython.address(proxy.struct),
|
| 113 |
+
cython.address(got_frame),
|
| 114 |
+
packet.ptr,
|
| 115 |
+
)
|
| 116 |
+
)
|
| 117 |
+
|
| 118 |
+
if got_frame:
|
| 119 |
+
return list(SubtitleSet(proxy))
|
| 120 |
+
return []
|
| 121 |
+
|
| 122 |
+
@cython.ccall
|
| 123 |
+
def decode2(self, packet: Packet):
|
| 124 |
+
"""
|
| 125 |
+
Returns SubtitleSet if you really need it.
|
| 126 |
+
"""
|
| 127 |
+
if not self.codec.ptr:
|
| 128 |
+
raise ValueError("cannot decode unknown codec")
|
| 129 |
+
|
| 130 |
+
self.open(strict=False)
|
| 131 |
+
|
| 132 |
+
proxy: SubtitleProxy = SubtitleProxy()
|
| 133 |
+
got_frame: cython.int = 0
|
| 134 |
+
|
| 135 |
+
err_check(
|
| 136 |
+
lib.avcodec_decode_subtitle2(
|
| 137 |
+
self.ptr,
|
| 138 |
+
cython.address(proxy.struct),
|
| 139 |
+
cython.address(got_frame),
|
| 140 |
+
packet.ptr,
|
| 141 |
+
)
|
| 142 |
+
)
|
| 143 |
+
|
| 144 |
+
if got_frame:
|
| 145 |
+
return SubtitleSet(proxy)
|
| 146 |
+
return None
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/codeccontext.pyi
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Literal
|
| 2 |
+
|
| 3 |
+
from av.codec.context import CodecContext
|
| 4 |
+
from av.packet import Packet
|
| 5 |
+
from av.subtitles.subtitle import SubtitleSet
|
| 6 |
+
|
| 7 |
+
class SubtitleCodecContext(CodecContext):
|
| 8 |
+
type: Literal["subtitle"]
|
| 9 |
+
subtitle_header: bytes | None
|
| 10 |
+
def decode2(self, packet: Packet) -> SubtitleSet | None: ...
|
| 11 |
+
def encode_subtitle(self, subtitle: SubtitleSet) -> Packet: ...
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/stream.cpython-310-darwin.so
ADDED
|
Binary file (95.3 kB). View file
|
|
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/stream.pxd
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from av.packet cimport Packet
|
| 2 |
+
from av.stream cimport Stream
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
cdef class SubtitleStream(Stream):
|
| 6 |
+
cpdef decode(self, Packet packet=?)
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/stream.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import cython
|
| 2 |
+
from cython.cimports.av.packet import Packet
|
| 3 |
+
from cython.cimports.av.stream import Stream
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
@cython.final
|
| 7 |
+
@cython.cclass
|
| 8 |
+
class SubtitleStream(Stream):
|
| 9 |
+
def __getattr__(self, name):
|
| 10 |
+
return getattr(self.codec_context, name)
|
| 11 |
+
|
| 12 |
+
@cython.ccall
|
| 13 |
+
def decode(self, packet: Packet | None = None):
|
| 14 |
+
"""
|
| 15 |
+
Decode a :class:`.Packet` and returns a subtitle object.
|
| 16 |
+
|
| 17 |
+
:rtype: list[AssSubtitle] | list[BitmapSubtitle]
|
| 18 |
+
|
| 19 |
+
.. seealso:: This is a passthrough to :meth:`.CodecContext.decode`.
|
| 20 |
+
"""
|
| 21 |
+
if not packet:
|
| 22 |
+
packet = Packet()
|
| 23 |
+
|
| 24 |
+
return self.codec_context.decode(packet)
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/stream.pyi
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from av.packet import Packet
|
| 2 |
+
from av.stream import Stream
|
| 3 |
+
from av.subtitles.subtitle import AssSubtitle, BitmapSubtitle, SubtitleSet
|
| 4 |
+
|
| 5 |
+
class SubtitleStream(Stream):
|
| 6 |
+
def decode(
|
| 7 |
+
self, packet: Packet | None = None
|
| 8 |
+
) -> list[AssSubtitle] | list[BitmapSubtitle]: ...
|
| 9 |
+
def decode2(self, packet: Packet) -> SubtitleSet | None: ...
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/subtitle.cpython-310-darwin.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c07eb0987ffc32224604f6a59b7a8a1f911a44222f886bcb9bfea5dd1ef274f7
|
| 3 |
+
size 184416
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/subtitle.pxd
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cimport libav as lib
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
cdef class SubtitleProxy:
|
| 5 |
+
cdef lib.AVSubtitle struct
|
| 6 |
+
|
| 7 |
+
cdef class SubtitleSet:
|
| 8 |
+
cdef SubtitleProxy proxy
|
| 9 |
+
cdef readonly tuple rects
|
| 10 |
+
|
| 11 |
+
cdef class Subtitle:
|
| 12 |
+
cdef SubtitleProxy proxy
|
| 13 |
+
cdef lib.AVSubtitleRect *ptr
|
| 14 |
+
cdef readonly bytes type
|
| 15 |
+
|
| 16 |
+
cdef class TextSubtitle(Subtitle):
|
| 17 |
+
pass
|
| 18 |
+
|
| 19 |
+
cdef class ASSSubtitle(Subtitle):
|
| 20 |
+
pass
|
| 21 |
+
|
| 22 |
+
cdef class BitmapSubtitle(Subtitle):
|
| 23 |
+
cdef readonly planes
|
| 24 |
+
|
| 25 |
+
cdef class BitmapSubtitlePlane:
|
| 26 |
+
cdef readonly BitmapSubtitle subtitle
|
| 27 |
+
cdef readonly int index
|
| 28 |
+
cdef readonly long buffer_size
|
| 29 |
+
cdef void *_buffer
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/subtitle.py
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import cython
|
| 2 |
+
from cython.cimports.cpython import PyBuffer_FillInfo, PyBytes_FromString
|
| 3 |
+
from cython.cimports.libc.string import memcpy
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
@cython.final
|
| 7 |
+
@cython.cclass
|
| 8 |
+
class SubtitleProxy:
|
| 9 |
+
def __dealloc__(self):
|
| 10 |
+
lib.avsubtitle_free(cython.address(self.struct))
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
_cinit_bypass_sentinel = cython.declare(object, object())
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
@cython.final
|
| 17 |
+
@cython.cclass
|
| 18 |
+
class SubtitleSet:
|
| 19 |
+
"""
|
| 20 |
+
A :class:`SubtitleSet` can contain many :class:`Subtitle` objects.
|
| 21 |
+
|
| 22 |
+
Wraps :ffmpeg:`AVSubtitle`.
|
| 23 |
+
"""
|
| 24 |
+
|
| 25 |
+
def __cinit__(self, proxy_or_sentinel=None):
|
| 26 |
+
if proxy_or_sentinel is _cinit_bypass_sentinel:
|
| 27 |
+
# Creating empty SubtitleSet for encoding
|
| 28 |
+
self.proxy = SubtitleProxy()
|
| 29 |
+
self.rects = ()
|
| 30 |
+
elif isinstance(proxy_or_sentinel, SubtitleProxy):
|
| 31 |
+
# Creating from decoded subtitle
|
| 32 |
+
self.proxy = proxy_or_sentinel
|
| 33 |
+
self.rects = tuple(
|
| 34 |
+
build_subtitle(self, i) for i in range(self.proxy.struct.num_rects)
|
| 35 |
+
)
|
| 36 |
+
else:
|
| 37 |
+
raise TypeError(
|
| 38 |
+
"SubtitleSet requires a SubtitleProxy or use SubtitleSet.create()"
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
+
@staticmethod
|
| 42 |
+
def create(
|
| 43 |
+
text: bytes,
|
| 44 |
+
start: int,
|
| 45 |
+
end: int,
|
| 46 |
+
pts: int = 0,
|
| 47 |
+
subtitle_format: int = 1,
|
| 48 |
+
) -> SubtitleSet:
|
| 49 |
+
"""
|
| 50 |
+
Create a SubtitleSet for encoding.
|
| 51 |
+
|
| 52 |
+
:param text: The subtitle text in ASS dialogue format
|
| 53 |
+
(e.g. ``b"0,0,Default,,0,0,0,,Hello World"``)
|
| 54 |
+
:param start: Start display time as offset from pts (typically 0)
|
| 55 |
+
:param end: End display time as offset from pts (i.e., duration)
|
| 56 |
+
:param pts: Presentation timestamp in stream time_base units
|
| 57 |
+
:param subtitle_format: Subtitle format (default 1 for text)
|
| 58 |
+
:return: A SubtitleSet ready for encoding
|
| 59 |
+
|
| 60 |
+
.. note::
|
| 61 |
+
All timing values should be in stream time_base units.
|
| 62 |
+
For MKV (time_base=1/1000), units are milliseconds.
|
| 63 |
+
For MP4 (time_base=1/1000000), units are microseconds.
|
| 64 |
+
"""
|
| 65 |
+
subset: SubtitleSet = SubtitleSet(_cinit_bypass_sentinel)
|
| 66 |
+
|
| 67 |
+
subset.proxy.struct.format = subtitle_format
|
| 68 |
+
subset.proxy.struct.start_display_time = start
|
| 69 |
+
subset.proxy.struct.end_display_time = end
|
| 70 |
+
subset.proxy.struct.pts = pts
|
| 71 |
+
|
| 72 |
+
subset.proxy.struct.num_rects = 1
|
| 73 |
+
subset.proxy.struct.rects = cython.cast(
|
| 74 |
+
cython.pointer[cython.pointer[lib.AVSubtitleRect]],
|
| 75 |
+
lib.av_mallocz(cython.sizeof(cython.pointer[lib.AVSubtitleRect])),
|
| 76 |
+
)
|
| 77 |
+
if subset.proxy.struct.rects == cython.NULL:
|
| 78 |
+
raise MemoryError("Failed to allocate subtitle rects array")
|
| 79 |
+
|
| 80 |
+
rect: cython.pointer[lib.AVSubtitleRect] = cython.cast(
|
| 81 |
+
cython.pointer[lib.AVSubtitleRect],
|
| 82 |
+
lib.av_mallocz(cython.sizeof(lib.AVSubtitleRect)),
|
| 83 |
+
)
|
| 84 |
+
if rect == cython.NULL:
|
| 85 |
+
lib.av_free(subset.proxy.struct.rects)
|
| 86 |
+
subset.proxy.struct.rects = cython.NULL
|
| 87 |
+
raise MemoryError("Failed to allocate subtitle rect")
|
| 88 |
+
|
| 89 |
+
subset.proxy.struct.rects[0] = rect
|
| 90 |
+
|
| 91 |
+
rect.x = 0
|
| 92 |
+
rect.y = 0
|
| 93 |
+
rect.w = 0
|
| 94 |
+
rect.h = 0
|
| 95 |
+
rect.nb_colors = 0
|
| 96 |
+
rect.type = lib.SUBTITLE_ASS
|
| 97 |
+
rect.text = cython.NULL
|
| 98 |
+
rect.flags = 0
|
| 99 |
+
|
| 100 |
+
text_len: cython.Py_ssize_t = len(text)
|
| 101 |
+
rect.ass = cython.cast(cython.p_char, lib.av_malloc(text_len + 1))
|
| 102 |
+
if rect.ass == cython.NULL:
|
| 103 |
+
raise MemoryError("Failed to allocate subtitle text")
|
| 104 |
+
memcpy(rect.ass, cython.cast(cython.p_char, text), text_len)
|
| 105 |
+
rect.ass[text_len] = 0
|
| 106 |
+
|
| 107 |
+
subset.rects = (AssSubtitle(subset, 0),)
|
| 108 |
+
|
| 109 |
+
return subset
|
| 110 |
+
|
| 111 |
+
def __repr__(self):
|
| 112 |
+
return (
|
| 113 |
+
f"<{self.__class__.__module__}.{self.__class__.__name__} at 0x{id(self):x}>"
|
| 114 |
+
)
|
| 115 |
+
|
| 116 |
+
@property
|
| 117 |
+
def format(self):
|
| 118 |
+
return self.proxy.struct.format
|
| 119 |
+
|
| 120 |
+
@format.setter
|
| 121 |
+
def format(self, value: int):
|
| 122 |
+
self.proxy.struct.format = value
|
| 123 |
+
|
| 124 |
+
@property
|
| 125 |
+
def start_display_time(self):
|
| 126 |
+
return self.proxy.struct.start_display_time
|
| 127 |
+
|
| 128 |
+
@start_display_time.setter
|
| 129 |
+
def start_display_time(self, value: int):
|
| 130 |
+
self.proxy.struct.start_display_time = value
|
| 131 |
+
|
| 132 |
+
@property
|
| 133 |
+
def end_display_time(self):
|
| 134 |
+
return self.proxy.struct.end_display_time
|
| 135 |
+
|
| 136 |
+
@end_display_time.setter
|
| 137 |
+
def end_display_time(self, value: int):
|
| 138 |
+
self.proxy.struct.end_display_time = value
|
| 139 |
+
|
| 140 |
+
@property
|
| 141 |
+
def pts(self):
|
| 142 |
+
"""Same as packet pts, in av.time_base."""
|
| 143 |
+
return self.proxy.struct.pts
|
| 144 |
+
|
| 145 |
+
@pts.setter
|
| 146 |
+
def pts(self, value: int):
|
| 147 |
+
self.proxy.struct.pts = value
|
| 148 |
+
|
| 149 |
+
def __len__(self):
|
| 150 |
+
return len(self.rects)
|
| 151 |
+
|
| 152 |
+
def __iter__(self):
|
| 153 |
+
return iter(self.rects)
|
| 154 |
+
|
| 155 |
+
def __getitem__(self, i):
|
| 156 |
+
return self.rects[i]
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
@cython.cfunc
|
| 160 |
+
def build_subtitle(subtitle: SubtitleSet, index: cython.int) -> Subtitle:
|
| 161 |
+
"""Build an av.Stream for an existing AVStream.
|
| 162 |
+
|
| 163 |
+
The AVStream MUST be fully constructed and ready for use before this is called.
|
| 164 |
+
"""
|
| 165 |
+
if index < 0 or cython.cast(cython.uint, index) >= subtitle.proxy.struct.num_rects:
|
| 166 |
+
raise ValueError("subtitle rect index out of range")
|
| 167 |
+
|
| 168 |
+
ptr: cython.pointer[lib.AVSubtitleRect] = subtitle.proxy.struct.rects[index]
|
| 169 |
+
|
| 170 |
+
if ptr.type == lib.SUBTITLE_BITMAP:
|
| 171 |
+
return BitmapSubtitle(subtitle, index)
|
| 172 |
+
if ptr.type == lib.SUBTITLE_ASS or ptr.type == lib.SUBTITLE_TEXT:
|
| 173 |
+
return AssSubtitle(subtitle, index)
|
| 174 |
+
|
| 175 |
+
raise ValueError("unknown subtitle type %r" % ptr.type)
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
@cython.cclass
|
| 179 |
+
class Subtitle:
|
| 180 |
+
"""
|
| 181 |
+
An abstract base class for each concrete type of subtitle.
|
| 182 |
+
Wraps :ffmpeg:`AVSubtitleRect`
|
| 183 |
+
"""
|
| 184 |
+
|
| 185 |
+
def __cinit__(self, subtitle: SubtitleSet, index: cython.int):
|
| 186 |
+
if (
|
| 187 |
+
index < 0
|
| 188 |
+
or cython.cast(cython.uint, index) >= subtitle.proxy.struct.num_rects
|
| 189 |
+
):
|
| 190 |
+
raise ValueError("subtitle rect index out of range")
|
| 191 |
+
self.proxy = subtitle.proxy
|
| 192 |
+
self.ptr = self.proxy.struct.rects[index]
|
| 193 |
+
|
| 194 |
+
if self.ptr.type == lib.SUBTITLE_NONE:
|
| 195 |
+
self.type = b"none"
|
| 196 |
+
elif self.ptr.type == lib.SUBTITLE_BITMAP:
|
| 197 |
+
self.type = b"bitmap"
|
| 198 |
+
elif self.ptr.type == lib.SUBTITLE_TEXT:
|
| 199 |
+
self.type = b"text"
|
| 200 |
+
elif self.ptr.type == lib.SUBTITLE_ASS:
|
| 201 |
+
self.type = b"ass"
|
| 202 |
+
else:
|
| 203 |
+
raise ValueError(f"unknown subtitle type {self.ptr.type!r}")
|
| 204 |
+
|
| 205 |
+
def __repr__(self):
|
| 206 |
+
return f"<av.{self.__class__.__name__} at 0x{id(self):x}>"
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
@cython.final
|
| 210 |
+
@cython.cclass
|
| 211 |
+
class BitmapSubtitle(Subtitle):
|
| 212 |
+
def __cinit__(self, subtitle: SubtitleSet, index: cython.int):
|
| 213 |
+
self.planes = tuple(
|
| 214 |
+
BitmapSubtitlePlane(self, i) for i in range(4) if self.ptr.linesize[i]
|
| 215 |
+
)
|
| 216 |
+
|
| 217 |
+
def __repr__(self):
|
| 218 |
+
return (
|
| 219 |
+
f"<{self.__class__.__module__}.{self.__class__.__name__} "
|
| 220 |
+
f"{self.width}x{self.height} at {self.x},{self.y}; at 0x{id(self):x}>"
|
| 221 |
+
)
|
| 222 |
+
|
| 223 |
+
@property
|
| 224 |
+
def x(self):
|
| 225 |
+
return self.ptr.x
|
| 226 |
+
|
| 227 |
+
@property
|
| 228 |
+
def y(self):
|
| 229 |
+
return self.ptr.y
|
| 230 |
+
|
| 231 |
+
@property
|
| 232 |
+
def width(self):
|
| 233 |
+
return self.ptr.w
|
| 234 |
+
|
| 235 |
+
@property
|
| 236 |
+
def height(self):
|
| 237 |
+
return self.ptr.h
|
| 238 |
+
|
| 239 |
+
@property
|
| 240 |
+
def nb_colors(self):
|
| 241 |
+
return self.ptr.nb_colors
|
| 242 |
+
|
| 243 |
+
def __len__(self):
|
| 244 |
+
return len(self.planes)
|
| 245 |
+
|
| 246 |
+
def __iter__(self):
|
| 247 |
+
return iter(self.planes)
|
| 248 |
+
|
| 249 |
+
def __getitem__(self, i):
|
| 250 |
+
return self.planes[i]
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
@cython.final
|
| 254 |
+
@cython.cclass
|
| 255 |
+
class BitmapSubtitlePlane:
|
| 256 |
+
def __cinit__(self, subtitle: BitmapSubtitle, index: cython.int):
|
| 257 |
+
if index >= 4:
|
| 258 |
+
raise ValueError("BitmapSubtitles have only 4 planes")
|
| 259 |
+
if not subtitle.ptr.linesize[index]:
|
| 260 |
+
raise ValueError("plane does not exist")
|
| 261 |
+
|
| 262 |
+
self.subtitle = subtitle
|
| 263 |
+
self.index = index
|
| 264 |
+
self.buffer_size = subtitle.ptr.w * subtitle.ptr.h
|
| 265 |
+
self._buffer = cython.cast(cython.p_void, subtitle.ptr.data[index])
|
| 266 |
+
|
| 267 |
+
# New-style buffer support.
|
| 268 |
+
def __getbuffer__(self, view: cython.pointer[Py_buffer], flags: cython.int):
|
| 269 |
+
PyBuffer_FillInfo(view, self, self._buffer, self.buffer_size, 0, flags)
|
| 270 |
+
|
| 271 |
+
|
| 272 |
+
@cython.final
|
| 273 |
+
@cython.cclass
|
| 274 |
+
class AssSubtitle(Subtitle):
|
| 275 |
+
"""
|
| 276 |
+
Represents an ASS/Text subtitle format, as opposed to a bitmap Subtitle format.
|
| 277 |
+
"""
|
| 278 |
+
|
| 279 |
+
def __repr__(self):
|
| 280 |
+
return f"<av.AssSubtitle {self.dialogue!r} at 0x{id(self):x}>"
|
| 281 |
+
|
| 282 |
+
@property
|
| 283 |
+
def ass(self):
|
| 284 |
+
"""
|
| 285 |
+
Returns the subtitle in the ASS/SSA format. Used by the vast majority of subtitle formats.
|
| 286 |
+
"""
|
| 287 |
+
if self.ptr.ass is not cython.NULL:
|
| 288 |
+
return PyBytes_FromString(self.ptr.ass)
|
| 289 |
+
return b""
|
| 290 |
+
|
| 291 |
+
@property
|
| 292 |
+
def dialogue(self):
|
| 293 |
+
"""
|
| 294 |
+
Extract the dialogue from the ass format. Strip comments.
|
| 295 |
+
"""
|
| 296 |
+
comma_count: cython.short = 0
|
| 297 |
+
i: cython.Py_ssize_t = 0
|
| 298 |
+
state: cython.bint = False
|
| 299 |
+
ass_text: bytes = self.ass
|
| 300 |
+
char, next_char = cython.declare(cython.uchar)
|
| 301 |
+
result: bytearray = bytearray()
|
| 302 |
+
text_len: cython.Py_ssize_t = len(ass_text)
|
| 303 |
+
|
| 304 |
+
while comma_count < 8 and i < text_len:
|
| 305 |
+
if ass_text[i] == b","[0]:
|
| 306 |
+
comma_count += 1
|
| 307 |
+
i += 1
|
| 308 |
+
|
| 309 |
+
while i < text_len:
|
| 310 |
+
char = ass_text[i]
|
| 311 |
+
next_char = 0 if i + 1 >= text_len else ass_text[i + 1]
|
| 312 |
+
|
| 313 |
+
if char == b"\\"[0] and next_char == b"N"[0]:
|
| 314 |
+
result.append(b"\n"[0])
|
| 315 |
+
i += 2
|
| 316 |
+
continue
|
| 317 |
+
|
| 318 |
+
if not state:
|
| 319 |
+
if char == b"{"[0] and next_char != b"\\"[0]:
|
| 320 |
+
state = True
|
| 321 |
+
else:
|
| 322 |
+
result.append(char)
|
| 323 |
+
elif char == b"}"[0]:
|
| 324 |
+
state = False
|
| 325 |
+
i += 1
|
| 326 |
+
|
| 327 |
+
return bytes(result)
|
| 328 |
+
|
| 329 |
+
@property
|
| 330 |
+
def text(self):
|
| 331 |
+
"""
|
| 332 |
+
Rarely used attribute. You're probably looking for dialogue.
|
| 333 |
+
"""
|
| 334 |
+
if self.ptr.text is not cython.NULL:
|
| 335 |
+
return PyBytes_FromString(self.ptr.text)
|
| 336 |
+
return b""
|
.venvs/kimodo/lib/python3.10/site-packages/av/subtitles/subtitle.pyi
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Iterator, Literal
|
| 2 |
+
|
| 3 |
+
class SubtitleSet:
|
| 4 |
+
format: int
|
| 5 |
+
start_display_time: int
|
| 6 |
+
end_display_time: int
|
| 7 |
+
pts: int
|
| 8 |
+
rects: tuple[Subtitle, ...]
|
| 9 |
+
|
| 10 |
+
@staticmethod
|
| 11 |
+
def create(
|
| 12 |
+
text: bytes,
|
| 13 |
+
start: int,
|
| 14 |
+
end: int,
|
| 15 |
+
pts: int = 0,
|
| 16 |
+
subtitle_format: int = 1,
|
| 17 |
+
) -> SubtitleSet: ...
|
| 18 |
+
def __len__(self) -> int: ...
|
| 19 |
+
def __iter__(self) -> Iterator[Subtitle]: ...
|
| 20 |
+
def __getitem__(self, i: int) -> Subtitle: ...
|
| 21 |
+
|
| 22 |
+
class Subtitle: ...
|
| 23 |
+
|
| 24 |
+
class BitmapSubtitle(Subtitle):
|
| 25 |
+
type: Literal[b"bitmap"]
|
| 26 |
+
x: int
|
| 27 |
+
y: int
|
| 28 |
+
width: int
|
| 29 |
+
height: int
|
| 30 |
+
nb_colors: int
|
| 31 |
+
planes: tuple[BitmapSubtitlePlane, ...]
|
| 32 |
+
|
| 33 |
+
class BitmapSubtitlePlane:
|
| 34 |
+
subtitle: BitmapSubtitle
|
| 35 |
+
index: int
|
| 36 |
+
buffer_size: int
|
| 37 |
+
|
| 38 |
+
class AssSubtitle(Subtitle):
|
| 39 |
+
type: Literal[b"ass", b"text"]
|
| 40 |
+
@property
|
| 41 |
+
def ass(self) -> bytes: ...
|
| 42 |
+
@property
|
| 43 |
+
def dialogue(self) -> bytes: ...
|
| 44 |
+
@property
|
| 45 |
+
def text(self) -> bytes: ...
|
.venvs/kimodo/lib/python3.10/site-packages/av/utils.cpython-310-darwin.so
ADDED
|
Binary file (94.6 kB). View file
|
|
|
.venvs/kimodo/lib/python3.10/site-packages/av/utils.pxd
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cimport libav as lib
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
cdef dict avdict_to_dict(lib.AVDictionary *input, str encoding, str errors)
|
| 5 |
+
cdef dict_to_avdict(lib.AVDictionary **dst, dict src, str encoding, str errors)
|
| 6 |
+
|
| 7 |
+
cdef object avrational_to_fraction(const lib.AVRational *input)
|
| 8 |
+
cdef void to_avrational(object frac, lib.AVRational *input)
|
| 9 |
+
cdef void check_ndarray(object array, object dtype, int ndim)
|
.venvs/kimodo/lib/python3.10/site-packages/av/utils.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# type: ignore
|
| 2 |
+
from fractions import Fraction
|
| 3 |
+
|
| 4 |
+
import cython
|
| 5 |
+
from cython.cimports import libav as lib
|
| 6 |
+
from cython.cimports.av.error import err_check
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
@cython.cfunc
|
| 10 |
+
def _decode(s: cython.pointer[cython.char], encoding, errors) -> str:
|
| 11 |
+
return cython.cast(bytes, s).decode(encoding, errors)
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
@cython.cfunc
|
| 15 |
+
def avdict_to_dict(
|
| 16 |
+
input: cython.pointer[lib.AVDictionary], encoding: str, errors: str
|
| 17 |
+
) -> dict:
|
| 18 |
+
element: cython.pointer[lib.AVDictionaryEntry] = cython.NULL
|
| 19 |
+
output: dict = {}
|
| 20 |
+
while True:
|
| 21 |
+
element = lib.av_dict_get(input, "", element, lib.AV_DICT_IGNORE_SUFFIX)
|
| 22 |
+
if element == cython.NULL:
|
| 23 |
+
break
|
| 24 |
+
output[_decode(element.key, encoding, errors)] = _decode(
|
| 25 |
+
element.value, encoding, errors
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
return output
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
@cython.cfunc
|
| 32 |
+
def dict_to_avdict(
|
| 33 |
+
dst: cython.pointer[cython.pointer[lib.AVDictionary]],
|
| 34 |
+
src: dict,
|
| 35 |
+
encoding: str,
|
| 36 |
+
errors: str,
|
| 37 |
+
):
|
| 38 |
+
lib.av_dict_free(dst)
|
| 39 |
+
for key, value in src.items():
|
| 40 |
+
err_check(
|
| 41 |
+
lib.av_dict_set(
|
| 42 |
+
dst, key.encode(encoding, errors), value.encode(encoding, errors), 0
|
| 43 |
+
)
|
| 44 |
+
)
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
@cython.cfunc
|
| 48 |
+
def avrational_to_fraction(
|
| 49 |
+
input: cython.pointer[cython.const[lib.AVRational]],
|
| 50 |
+
) -> object:
|
| 51 |
+
if input.num and input.den:
|
| 52 |
+
return Fraction(input.num, input.den)
|
| 53 |
+
return None
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
@cython.cfunc
|
| 57 |
+
def to_avrational(frac: object, input: cython.pointer[lib.AVRational]) -> cython.void:
|
| 58 |
+
input.num = frac.numerator
|
| 59 |
+
input.den = frac.denominator
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
@cython.cfunc
|
| 63 |
+
def check_ndarray(array: object, dtype: object, ndim: cython.int) -> cython.void:
|
| 64 |
+
"""
|
| 65 |
+
Check a numpy array has the expected data type and number of dimensions.
|
| 66 |
+
"""
|
| 67 |
+
if array.dtype != dtype:
|
| 68 |
+
raise ValueError(
|
| 69 |
+
f"Expected numpy array with dtype `{dtype}` but got `{array.dtype}`"
|
| 70 |
+
)
|
| 71 |
+
if array.ndim != ndim:
|
| 72 |
+
raise ValueError(
|
| 73 |
+
f"Expected numpy array with ndim `{ndim}` but got `{array.ndim}`"
|
| 74 |
+
)
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/__init__.pxd
ADDED
|
File without changes
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/__init__.py
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .frame import VideoFrame as VideoFrame
|
| 2 |
+
from .stream import VideoStream as VideoStream
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/__init__.pyi
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Literal
|
| 2 |
+
|
| 3 |
+
from .frame import VideoFrame
|
| 4 |
+
from .stream import VideoStream
|
| 5 |
+
|
| 6 |
+
_VideoCodecName = Literal[
|
| 7 |
+
"gif",
|
| 8 |
+
"h264",
|
| 9 |
+
"hevc",
|
| 10 |
+
"libvpx",
|
| 11 |
+
"libx264",
|
| 12 |
+
"mpeg4",
|
| 13 |
+
"png",
|
| 14 |
+
"qtrle",
|
| 15 |
+
]
|
| 16 |
+
|
| 17 |
+
__all__ = ("VideoFrame", "VideoStream")
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/codeccontext.cpython-310-darwin.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6f9625f10c54a499738ffd9753317ff4bccf860c3677b20fcdb18a728147ee77
|
| 3 |
+
size 137680
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/codeccontext.pxd
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cimport libav as lib
|
| 2 |
+
|
| 3 |
+
from av.codec.context cimport CodecContext
|
| 4 |
+
from av.video.format cimport VideoFormat
|
| 5 |
+
from av.video.frame cimport VideoFrame
|
| 6 |
+
from av.video.reformatter cimport VideoReformatter
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
# The get_format callback in AVCodecContext is called by the decoder to pick a format out of a list.
|
| 10 |
+
# When we want accelerated decoding, we need to figure out ahead of time what the format should be,
|
| 11 |
+
# and find a way to pass that into our callback so we can return it to the decoder. We use the 'opaque'
|
| 12 |
+
# user data field in AVCodecContext for that. This is the struct we store a pointer to in that field.
|
| 13 |
+
cdef struct AVCodecPrivateData:
|
| 14 |
+
lib.AVPixelFormat hardware_pix_fmt
|
| 15 |
+
bint allow_software_fallback
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
cdef class VideoCodecContext(CodecContext):
|
| 19 |
+
cdef AVCodecPrivateData _private_data
|
| 20 |
+
cdef readonly VideoReformatter reformatter
|
| 21 |
+
cdef VideoFrame next_frame
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/codeccontext.py
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import cython
|
| 2 |
+
import cython.cimports.libav as lib
|
| 3 |
+
from cython.cimports.av.codec.context import CodecContext
|
| 4 |
+
from cython.cimports.av.codec.hwaccel import HWAccel
|
| 5 |
+
from cython.cimports.av.error import err_check
|
| 6 |
+
from cython.cimports.av.frame import Frame
|
| 7 |
+
from cython.cimports.av.packet import Packet
|
| 8 |
+
from cython.cimports.av.utils import avrational_to_fraction, to_avrational
|
| 9 |
+
from cython.cimports.av.video.format import VideoFormat, get_pix_fmt, get_video_format
|
| 10 |
+
from cython.cimports.av.video.frame import VideoFrame, alloc_video_frame
|
| 11 |
+
from cython.cimports.av.video.reformatter import VideoReformatter
|
| 12 |
+
from cython.cimports.libc.stdint import int64_t
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
@cython.cfunc
|
| 16 |
+
@cython.exceptval(check=False)
|
| 17 |
+
def _get_hw_format(
|
| 18 |
+
ctx: cython.pointer[lib.AVCodecContext],
|
| 19 |
+
pix_fmts: cython.pointer[cython.const[lib.AVPixelFormat]],
|
| 20 |
+
) -> lib.AVPixelFormat:
|
| 21 |
+
# In the case where we requested accelerated decoding, the decoder first calls this function
|
| 22 |
+
# with a list that includes both the hardware format and software formats.
|
| 23 |
+
# First we try to pick the hardware format if it's in the list.
|
| 24 |
+
# However, if the decoder fails to initialize the hardware, it will call this function again,
|
| 25 |
+
# with only software formats in pix_fmts. We return ctx->sw_pix_fmt regardless in this case,
|
| 26 |
+
# because that should be in the candidate list. If not, we are out of ideas anyways.
|
| 27 |
+
private_data: cython.pointer[AVCodecPrivateData] = cython.cast(
|
| 28 |
+
cython.pointer[AVCodecPrivateData], ctx.opaque
|
| 29 |
+
)
|
| 30 |
+
i: cython.int = 0
|
| 31 |
+
while pix_fmts[i] != -1:
|
| 32 |
+
if pix_fmts[i] == private_data.hardware_pix_fmt:
|
| 33 |
+
return pix_fmts[i]
|
| 34 |
+
i += 1
|
| 35 |
+
return (
|
| 36 |
+
ctx.sw_pix_fmt if private_data.allow_software_fallback else lib.AV_PIX_FMT_NONE
|
| 37 |
+
)
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
@cython.final
|
| 41 |
+
@cython.cclass
|
| 42 |
+
class VideoCodecContext(CodecContext):
|
| 43 |
+
@cython.cfunc
|
| 44 |
+
def _init(
|
| 45 |
+
self,
|
| 46 |
+
ptr: cython.pointer[lib.AVCodecContext],
|
| 47 |
+
codec: cython.pointer[cython.const[lib.AVCodec]],
|
| 48 |
+
hwaccel: HWAccel | None,
|
| 49 |
+
):
|
| 50 |
+
CodecContext._init(self, ptr, codec, hwaccel)
|
| 51 |
+
|
| 52 |
+
if hwaccel is not None:
|
| 53 |
+
try:
|
| 54 |
+
self.hwaccel_ctx = hwaccel.create(self.codec)
|
| 55 |
+
self.ptr.hw_device_ctx = lib.av_buffer_ref(self.hwaccel_ctx.ptr)
|
| 56 |
+
self.ptr.pix_fmt = self.hwaccel_ctx.config.ptr.pix_fmt
|
| 57 |
+
self.ptr.get_format = _get_hw_format
|
| 58 |
+
self._private_data.hardware_pix_fmt = (
|
| 59 |
+
self.hwaccel_ctx.config.ptr.pix_fmt
|
| 60 |
+
)
|
| 61 |
+
self._private_data.allow_software_fallback = (
|
| 62 |
+
self.hwaccel.allow_software_fallback
|
| 63 |
+
)
|
| 64 |
+
self.ptr.opaque = cython.address(self._private_data)
|
| 65 |
+
except NotImplementedError:
|
| 66 |
+
# Some streams may not have a hardware decoder. For example, many action
|
| 67 |
+
# cam videos have a low resolution mjpeg stream, which is usually not
|
| 68 |
+
# compatible with hardware decoders.
|
| 69 |
+
# The user may have passed in a hwaccel because they want to decode the main
|
| 70 |
+
# stream with it, so we shouldn't abort even if we find a stream that can't
|
| 71 |
+
# be HW decoded.
|
| 72 |
+
# If the user wants to make sure hwaccel is actually used, they can check with the
|
| 73 |
+
# is_hwaccel() function on each stream's codec context.
|
| 74 |
+
self.hwaccel_ctx = None
|
| 75 |
+
|
| 76 |
+
@cython.cfunc
|
| 77 |
+
def _prepare_frames_for_encode(self, input: Frame | None) -> list:
|
| 78 |
+
if input is None or not input:
|
| 79 |
+
return [None]
|
| 80 |
+
|
| 81 |
+
vframe: VideoFrame = input
|
| 82 |
+
if (
|
| 83 |
+
vframe.format.pix_fmt != self.pix_fmt
|
| 84 |
+
or vframe.width != self.ptr.width
|
| 85 |
+
or vframe.height != self.ptr.height
|
| 86 |
+
):
|
| 87 |
+
if not self.reformatter:
|
| 88 |
+
self.reformatter = VideoReformatter()
|
| 89 |
+
|
| 90 |
+
vframe = self.reformatter.reformat(
|
| 91 |
+
vframe,
|
| 92 |
+
self.ptr.width,
|
| 93 |
+
self.ptr.height,
|
| 94 |
+
self.format,
|
| 95 |
+
threads=self.ptr.thread_count,
|
| 96 |
+
)
|
| 97 |
+
|
| 98 |
+
if vframe.ptr.pts == lib.AV_NOPTS_VALUE:
|
| 99 |
+
vframe.ptr.pts = self.ptr.frame_num
|
| 100 |
+
|
| 101 |
+
return [vframe]
|
| 102 |
+
|
| 103 |
+
@cython.cfunc
|
| 104 |
+
def _alloc_next_frame(self) -> Frame:
|
| 105 |
+
return alloc_video_frame()
|
| 106 |
+
|
| 107 |
+
@cython.cfunc
|
| 108 |
+
def _setup_decoded_frame(self, frame: Frame, packet: Packet):
|
| 109 |
+
CodecContext._setup_decoded_frame(self, frame, packet)
|
| 110 |
+
vframe: VideoFrame = frame
|
| 111 |
+
vframe._init_user_attributes()
|
| 112 |
+
|
| 113 |
+
@cython.cfunc
|
| 114 |
+
def _transfer_hwframe(self, frame: Frame):
|
| 115 |
+
if self.hwaccel_ctx is None:
|
| 116 |
+
return frame
|
| 117 |
+
if frame.ptr.format != self.hwaccel_ctx.config.ptr.pix_fmt:
|
| 118 |
+
# If we get a software frame, that means we are in software fallback mode, and don't actually
|
| 119 |
+
# need to transfer.
|
| 120 |
+
return frame
|
| 121 |
+
|
| 122 |
+
if self.hwaccel_ctx.is_hw_owned:
|
| 123 |
+
cython.cast(VideoFrame, frame)._device_id = self.hwaccel_ctx.device_id
|
| 124 |
+
return frame
|
| 125 |
+
|
| 126 |
+
frame_sw: Frame = self._alloc_next_frame()
|
| 127 |
+
err_check(lib.av_hwframe_transfer_data(frame_sw.ptr, frame.ptr, 0))
|
| 128 |
+
# TODO: Is there anything else to transfer?
|
| 129 |
+
frame_sw.pts = frame.pts
|
| 130 |
+
return frame_sw
|
| 131 |
+
|
| 132 |
+
@property
|
| 133 |
+
def format(self):
|
| 134 |
+
return get_video_format(
|
| 135 |
+
cython.cast(lib.AVPixelFormat, self.ptr.pix_fmt),
|
| 136 |
+
self.ptr.width,
|
| 137 |
+
self.ptr.height,
|
| 138 |
+
)
|
| 139 |
+
|
| 140 |
+
@format.setter
|
| 141 |
+
def format(self, format: VideoFormat):
|
| 142 |
+
self.ptr.pix_fmt = format.pix_fmt
|
| 143 |
+
self.ptr.width = format.width
|
| 144 |
+
self.ptr.height = format.height
|
| 145 |
+
|
| 146 |
+
@property
|
| 147 |
+
def width(self):
|
| 148 |
+
if self.ptr is cython.NULL:
|
| 149 |
+
return 0
|
| 150 |
+
return self.ptr.width
|
| 151 |
+
|
| 152 |
+
@width.setter
|
| 153 |
+
def width(self, value: cython.uint):
|
| 154 |
+
self.ptr.width = value
|
| 155 |
+
|
| 156 |
+
@property
|
| 157 |
+
def height(self):
|
| 158 |
+
if self.ptr is cython.NULL:
|
| 159 |
+
return 0
|
| 160 |
+
return self.ptr.height
|
| 161 |
+
|
| 162 |
+
@height.setter
|
| 163 |
+
def height(self, value: cython.uint):
|
| 164 |
+
self.ptr.height = value
|
| 165 |
+
|
| 166 |
+
@property
|
| 167 |
+
def bits_per_coded_sample(self):
|
| 168 |
+
"""
|
| 169 |
+
The number of bits per sample in the codedwords. It's mandatory for this to be set for some formats to decode properly.
|
| 170 |
+
|
| 171 |
+
Wraps :ffmpeg:`AVCodecContext.bits_per_coded_sample`.
|
| 172 |
+
|
| 173 |
+
:type: int
|
| 174 |
+
"""
|
| 175 |
+
return self.ptr.bits_per_coded_sample
|
| 176 |
+
|
| 177 |
+
@bits_per_coded_sample.setter
|
| 178 |
+
def bits_per_coded_sample(self, value: cython.int):
|
| 179 |
+
if self.is_encoder:
|
| 180 |
+
raise ValueError("Not supported for encoders")
|
| 181 |
+
|
| 182 |
+
self.ptr.bits_per_coded_sample = value
|
| 183 |
+
|
| 184 |
+
@property
|
| 185 |
+
def pix_fmt(self):
|
| 186 |
+
"""
|
| 187 |
+
The pixel format's name.
|
| 188 |
+
|
| 189 |
+
:type: str | None
|
| 190 |
+
"""
|
| 191 |
+
desc: cython.pointer[cython.const[lib.AVPixFmtDescriptor]] = (
|
| 192 |
+
lib.av_pix_fmt_desc_get(cython.cast(lib.AVPixelFormat, self.ptr.pix_fmt))
|
| 193 |
+
)
|
| 194 |
+
return cython.cast(str, desc.name)
|
| 195 |
+
|
| 196 |
+
@pix_fmt.setter
|
| 197 |
+
def pix_fmt(self, value):
|
| 198 |
+
self.ptr.pix_fmt = get_pix_fmt(value)
|
| 199 |
+
|
| 200 |
+
@property
|
| 201 |
+
def framerate(self):
|
| 202 |
+
"""
|
| 203 |
+
The frame rate, in frames per second.
|
| 204 |
+
|
| 205 |
+
:type: fractions.Fraction
|
| 206 |
+
"""
|
| 207 |
+
return avrational_to_fraction(cython.address(self.ptr.framerate))
|
| 208 |
+
|
| 209 |
+
@framerate.setter
|
| 210 |
+
def framerate(self, value):
|
| 211 |
+
to_avrational(value, cython.address(self.ptr.framerate))
|
| 212 |
+
|
| 213 |
+
@property
|
| 214 |
+
def rate(self):
|
| 215 |
+
"""Another name for :attr:`framerate`."""
|
| 216 |
+
return self.framerate
|
| 217 |
+
|
| 218 |
+
@rate.setter
|
| 219 |
+
def rate(self, value):
|
| 220 |
+
self.framerate = value
|
| 221 |
+
|
| 222 |
+
@property
|
| 223 |
+
def gop_size(self):
|
| 224 |
+
"""
|
| 225 |
+
Sets the number of frames between keyframes. Used only for encoding.
|
| 226 |
+
|
| 227 |
+
:type: int
|
| 228 |
+
"""
|
| 229 |
+
if self.is_decoder:
|
| 230 |
+
raise RuntimeError("Cannot access 'gop_size' as a decoder")
|
| 231 |
+
return self.ptr.gop_size
|
| 232 |
+
|
| 233 |
+
@gop_size.setter
|
| 234 |
+
def gop_size(self, value: cython.int):
|
| 235 |
+
if self.is_decoder:
|
| 236 |
+
raise RuntimeError("Cannot access 'gop_size' as a decoder")
|
| 237 |
+
self.ptr.gop_size = value
|
| 238 |
+
|
| 239 |
+
@property
|
| 240 |
+
def sample_aspect_ratio(self):
|
| 241 |
+
return avrational_to_fraction(cython.address(self.ptr.sample_aspect_ratio))
|
| 242 |
+
|
| 243 |
+
@sample_aspect_ratio.setter
|
| 244 |
+
def sample_aspect_ratio(self, value):
|
| 245 |
+
to_avrational(value, cython.address(self.ptr.sample_aspect_ratio))
|
| 246 |
+
|
| 247 |
+
@property
|
| 248 |
+
def display_aspect_ratio(self):
|
| 249 |
+
dar: lib.AVRational
|
| 250 |
+
lib.av_reduce(
|
| 251 |
+
cython.address(dar.num),
|
| 252 |
+
cython.address(dar.den),
|
| 253 |
+
self.ptr.width * self.ptr.sample_aspect_ratio.num,
|
| 254 |
+
self.ptr.height * self.ptr.sample_aspect_ratio.den,
|
| 255 |
+
1024 * 1024,
|
| 256 |
+
)
|
| 257 |
+
|
| 258 |
+
return avrational_to_fraction(cython.address(dar))
|
| 259 |
+
|
| 260 |
+
@property
|
| 261 |
+
def has_b_frames(self):
|
| 262 |
+
"""
|
| 263 |
+
:type: bool
|
| 264 |
+
"""
|
| 265 |
+
return bool(self.ptr.has_b_frames)
|
| 266 |
+
|
| 267 |
+
@property
|
| 268 |
+
def reorder_depth(self):
|
| 269 |
+
"""Raw ``has_b_frames`` value from FFmpeg (int, not bool).
|
| 270 |
+
|
| 271 |
+
After :meth:`flush_buffers`, FFmpeg may reset the internal reorder
|
| 272 |
+
heuristic. Set this to the known reorder depth *after* seeking to
|
| 273 |
+
avoid dropped hierarchical B-frames.
|
| 274 |
+
"""
|
| 275 |
+
return self.ptr.has_b_frames
|
| 276 |
+
|
| 277 |
+
@reorder_depth.setter
|
| 278 |
+
def reorder_depth(self, value: cython.int):
|
| 279 |
+
self.ptr.has_b_frames = value
|
| 280 |
+
|
| 281 |
+
@property
|
| 282 |
+
def coded_width(self):
|
| 283 |
+
"""
|
| 284 |
+
:type: int
|
| 285 |
+
"""
|
| 286 |
+
return self.ptr.coded_width
|
| 287 |
+
|
| 288 |
+
@property
|
| 289 |
+
def coded_height(self):
|
| 290 |
+
"""
|
| 291 |
+
:type: int
|
| 292 |
+
"""
|
| 293 |
+
return self.ptr.coded_height
|
| 294 |
+
|
| 295 |
+
@property
|
| 296 |
+
def color_range(self):
|
| 297 |
+
"""
|
| 298 |
+
Describes the signal range of the colorspace.
|
| 299 |
+
|
| 300 |
+
Wraps :ffmpeg:`AVFrame.color_range`.
|
| 301 |
+
|
| 302 |
+
:type: int
|
| 303 |
+
"""
|
| 304 |
+
return self.ptr.color_range
|
| 305 |
+
|
| 306 |
+
@color_range.setter
|
| 307 |
+
def color_range(self, value):
|
| 308 |
+
self.ptr.color_range = value
|
| 309 |
+
|
| 310 |
+
@property
|
| 311 |
+
def color_primaries(self):
|
| 312 |
+
"""
|
| 313 |
+
Describes the RGB/XYZ matrix of the colorspace.
|
| 314 |
+
|
| 315 |
+
Wraps :ffmpeg:`AVFrame.color_primaries`.
|
| 316 |
+
|
| 317 |
+
:type: int
|
| 318 |
+
"""
|
| 319 |
+
return self.ptr.color_primaries
|
| 320 |
+
|
| 321 |
+
@color_primaries.setter
|
| 322 |
+
def color_primaries(self, value):
|
| 323 |
+
self.ptr.color_primaries = value
|
| 324 |
+
|
| 325 |
+
@property
|
| 326 |
+
def color_trc(self):
|
| 327 |
+
"""
|
| 328 |
+
Describes the linearization function (a.k.a. transformation characteristics) of the colorspace.
|
| 329 |
+
|
| 330 |
+
Wraps :ffmpeg:`AVFrame.color_trc`.
|
| 331 |
+
|
| 332 |
+
:type: int
|
| 333 |
+
"""
|
| 334 |
+
return self.ptr.color_trc
|
| 335 |
+
|
| 336 |
+
@color_trc.setter
|
| 337 |
+
def color_trc(self, value):
|
| 338 |
+
self.ptr.color_trc = value
|
| 339 |
+
|
| 340 |
+
@property
|
| 341 |
+
def colorspace(self):
|
| 342 |
+
"""
|
| 343 |
+
Describes the YUV/RGB transformation matrix of the colorspace.
|
| 344 |
+
|
| 345 |
+
Wraps :ffmpeg:`AVFrame.colorspace`.
|
| 346 |
+
|
| 347 |
+
:type: int
|
| 348 |
+
"""
|
| 349 |
+
return self.ptr.colorspace
|
| 350 |
+
|
| 351 |
+
@colorspace.setter
|
| 352 |
+
def colorspace(self, value):
|
| 353 |
+
self.ptr.colorspace = value
|
| 354 |
+
|
| 355 |
+
@property
|
| 356 |
+
def max_b_frames(self):
|
| 357 |
+
"""
|
| 358 |
+
The maximum run of consecutive B frames when encoding a video.
|
| 359 |
+
|
| 360 |
+
:type: int
|
| 361 |
+
"""
|
| 362 |
+
return self.ptr.max_b_frames
|
| 363 |
+
|
| 364 |
+
@max_b_frames.setter
|
| 365 |
+
def max_b_frames(self, value):
|
| 366 |
+
self.ptr.max_b_frames = value
|
| 367 |
+
|
| 368 |
+
@property
|
| 369 |
+
def qmin(self):
|
| 370 |
+
"""
|
| 371 |
+
The minimum quantiser value of an encoded stream.
|
| 372 |
+
|
| 373 |
+
Wraps :ffmpeg:`AVCodecContext.qmin`.
|
| 374 |
+
|
| 375 |
+
:type: int
|
| 376 |
+
"""
|
| 377 |
+
return self.ptr.qmin
|
| 378 |
+
|
| 379 |
+
@qmin.setter
|
| 380 |
+
def qmin(self, value):
|
| 381 |
+
self.ptr.qmin = value
|
| 382 |
+
|
| 383 |
+
@property
|
| 384 |
+
def qmax(self):
|
| 385 |
+
"""
|
| 386 |
+
The maximum quantiser value of an encoded stream.
|
| 387 |
+
|
| 388 |
+
Wraps :ffmpeg:`AVCodecContext.qmax`.
|
| 389 |
+
|
| 390 |
+
:type: int
|
| 391 |
+
"""
|
| 392 |
+
return self.ptr.qmax
|
| 393 |
+
|
| 394 |
+
@qmax.setter
|
| 395 |
+
def qmax(self, value):
|
| 396 |
+
self.ptr.qmax = value
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/codeccontext.pyi
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fractions import Fraction
|
| 2 |
+
from typing import Iterator, Literal
|
| 3 |
+
|
| 4 |
+
from av.codec.context import CodecContext
|
| 5 |
+
from av.packet import Packet
|
| 6 |
+
|
| 7 |
+
from .format import VideoFormat
|
| 8 |
+
from .frame import VideoFrame
|
| 9 |
+
|
| 10 |
+
class VideoCodecContext(CodecContext):
|
| 11 |
+
format: VideoFormat | None
|
| 12 |
+
width: int
|
| 13 |
+
height: int
|
| 14 |
+
bits_per_coded_sample: int
|
| 15 |
+
pix_fmt: str | None
|
| 16 |
+
framerate: Fraction
|
| 17 |
+
rate: Fraction
|
| 18 |
+
gop_size: int
|
| 19 |
+
sample_aspect_ratio: Fraction | None
|
| 20 |
+
display_aspect_ratio: Fraction | None
|
| 21 |
+
has_b_frames: bool
|
| 22 |
+
reorder_depth: int
|
| 23 |
+
max_b_frames: int
|
| 24 |
+
coded_width: int
|
| 25 |
+
coded_height: int
|
| 26 |
+
color_range: int
|
| 27 |
+
color_primaries: int
|
| 28 |
+
color_trc: int
|
| 29 |
+
colorspace: int
|
| 30 |
+
qmin: int
|
| 31 |
+
qmax: int
|
| 32 |
+
type: Literal["video"]
|
| 33 |
+
|
| 34 |
+
def encode(self, frame: VideoFrame | None = None) -> list[Packet]: ...
|
| 35 |
+
def encode_lazy(self, frame: VideoFrame | None = None) -> Iterator[Packet]: ...
|
| 36 |
+
def decode(self, packet: Packet | None = None) -> list[VideoFrame]: ...
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/format.cpython-310-darwin.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3aed2c1a5eacab306f44e66e06d8433244a62ea15cb62ac7ebf545793bbc6140
|
| 3 |
+
size 142592
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/format.pxd
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cimport libav as lib
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
cdef class VideoFormat:
|
| 5 |
+
cdef lib.AVPixelFormat pix_fmt
|
| 6 |
+
cdef const lib.AVPixFmtDescriptor *ptr
|
| 7 |
+
cdef readonly unsigned int width, height
|
| 8 |
+
cdef _init(self, lib.AVPixelFormat pix_fmt, unsigned int width, unsigned int height)
|
| 9 |
+
cpdef chroma_width(self, int luma_width=?)
|
| 10 |
+
cpdef chroma_height(self, int luma_height=?)
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
cdef class VideoFormatComponent:
|
| 14 |
+
cdef VideoFormat format
|
| 15 |
+
cdef readonly unsigned int index
|
| 16 |
+
cdef const lib.AVComponentDescriptor *ptr
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
cdef VideoFormat get_video_format(lib.AVPixelFormat c_format, unsigned int width, unsigned int height)
|
| 20 |
+
cdef lib.AVPixelFormat get_pix_fmt(const char *name) except lib.AV_PIX_FMT_NONE
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/format.py
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import cython
|
| 2 |
+
from cython import uint as cuint
|
| 3 |
+
|
| 4 |
+
_cinit_bypass_sentinel = cython.declare(object, object())
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
@cython.cfunc
|
| 8 |
+
def get_video_format(
|
| 9 |
+
c_format: lib.AVPixelFormat, width: cuint, height: cuint
|
| 10 |
+
) -> VideoFormat | None:
|
| 11 |
+
if c_format == lib.AV_PIX_FMT_NONE:
|
| 12 |
+
return None
|
| 13 |
+
|
| 14 |
+
format: VideoFormat = VideoFormat.__new__(VideoFormat, _cinit_bypass_sentinel)
|
| 15 |
+
format._init(c_format, width, height)
|
| 16 |
+
return format
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
@cython.cfunc
|
| 20 |
+
@cython.exceptval(lib.AV_PIX_FMT_NONE, check=False)
|
| 21 |
+
def get_pix_fmt(name: cython.p_const_char) -> lib.AVPixelFormat:
|
| 22 |
+
"""Wrapper for lib.av_get_pix_fmt with error checking."""
|
| 23 |
+
|
| 24 |
+
pix_fmt: lib.AVPixelFormat = lib.av_get_pix_fmt(name)
|
| 25 |
+
if pix_fmt == lib.AV_PIX_FMT_NONE:
|
| 26 |
+
raise ValueError("not a pixel format: %r" % name)
|
| 27 |
+
return pix_fmt
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
@cython.final
|
| 31 |
+
@cython.cclass
|
| 32 |
+
class VideoFormat:
|
| 33 |
+
"""
|
| 34 |
+
|
| 35 |
+
>>> format = VideoFormat('rgb24')
|
| 36 |
+
>>> format.name
|
| 37 |
+
'rgb24'
|
| 38 |
+
|
| 39 |
+
"""
|
| 40 |
+
|
| 41 |
+
def __cinit__(self, name, width=0, height=0):
|
| 42 |
+
if name is _cinit_bypass_sentinel:
|
| 43 |
+
return
|
| 44 |
+
|
| 45 |
+
if isinstance(name, VideoFormat):
|
| 46 |
+
other: VideoFormat = cython.cast(VideoFormat, name)
|
| 47 |
+
self._init(other.pix_fmt, width or other.width, height or other.height)
|
| 48 |
+
return
|
| 49 |
+
|
| 50 |
+
pix_fmt: lib.AVPixelFormat = get_pix_fmt(name)
|
| 51 |
+
self._init(pix_fmt, width, height)
|
| 52 |
+
|
| 53 |
+
@cython.cfunc
|
| 54 |
+
def _init(self, pix_fmt: lib.AVPixelFormat, width: cuint, height: cuint):
|
| 55 |
+
self.pix_fmt = pix_fmt
|
| 56 |
+
self.ptr = lib.av_pix_fmt_desc_get(pix_fmt)
|
| 57 |
+
self.width = width
|
| 58 |
+
self.height = height
|
| 59 |
+
|
| 60 |
+
def __repr__(self):
|
| 61 |
+
if self.width or self.height:
|
| 62 |
+
return f"<av.{self.__class__.__name__} {self.name}, {self.width}x{self.height}>"
|
| 63 |
+
else:
|
| 64 |
+
return f"<av.{self.__class__.__name__} {self.name}>"
|
| 65 |
+
|
| 66 |
+
def __int__(self):
|
| 67 |
+
return int(self.pix_fmt)
|
| 68 |
+
|
| 69 |
+
@property
|
| 70 |
+
def name(self):
|
| 71 |
+
"""Canonical name of the pixel format."""
|
| 72 |
+
return cython.cast(str, self.ptr.name)
|
| 73 |
+
|
| 74 |
+
@property
|
| 75 |
+
def components(self):
|
| 76 |
+
return tuple(
|
| 77 |
+
VideoFormatComponent(self, i) for i in range(self.ptr.nb_components)
|
| 78 |
+
)
|
| 79 |
+
|
| 80 |
+
@property
|
| 81 |
+
def bits_per_pixel(self):
|
| 82 |
+
return lib.av_get_bits_per_pixel(self.ptr)
|
| 83 |
+
|
| 84 |
+
@property
|
| 85 |
+
def padded_bits_per_pixel(self):
|
| 86 |
+
return lib.av_get_padded_bits_per_pixel(self.ptr)
|
| 87 |
+
|
| 88 |
+
@property
|
| 89 |
+
def is_big_endian(self):
|
| 90 |
+
"""Pixel format is big-endian."""
|
| 91 |
+
return bool(self.ptr.flags & lib.AV_PIX_FMT_FLAG_BE)
|
| 92 |
+
|
| 93 |
+
@property
|
| 94 |
+
def has_palette(self):
|
| 95 |
+
"""Pixel format has a palette in data[1], values are indexes in this palette."""
|
| 96 |
+
return bool(self.ptr.flags & lib.AV_PIX_FMT_FLAG_PAL)
|
| 97 |
+
|
| 98 |
+
@property
|
| 99 |
+
def is_bit_stream(self):
|
| 100 |
+
"""All values of a component are bit-wise packed end to end."""
|
| 101 |
+
return bool(self.ptr.flags & lib.AV_PIX_FMT_FLAG_BITSTREAM)
|
| 102 |
+
|
| 103 |
+
@property
|
| 104 |
+
def is_planar(self):
|
| 105 |
+
"""At least one pixel component is not in the first data plane."""
|
| 106 |
+
return bool(self.ptr.flags & lib.AV_PIX_FMT_FLAG_PLANAR)
|
| 107 |
+
|
| 108 |
+
@property
|
| 109 |
+
def is_rgb(self):
|
| 110 |
+
"""The pixel format contains RGB-like data (as opposed to YUV/grayscale)."""
|
| 111 |
+
return bool(self.ptr.flags & lib.AV_PIX_FMT_FLAG_RGB)
|
| 112 |
+
|
| 113 |
+
@property
|
| 114 |
+
def is_bayer(self):
|
| 115 |
+
"""The pixel format contains Bayer data."""
|
| 116 |
+
return bool(self.ptr.flags & lib.AV_PIX_FMT_FLAG_BAYER)
|
| 117 |
+
|
| 118 |
+
@cython.ccall
|
| 119 |
+
def chroma_width(self, luma_width: cython.int = 0):
|
| 120 |
+
"""chroma_width(luma_width=0)
|
| 121 |
+
|
| 122 |
+
Width of a chroma plane relative to a luma plane.
|
| 123 |
+
|
| 124 |
+
:param int luma_width: Width of the luma plane; defaults to ``self.width``.
|
| 125 |
+
|
| 126 |
+
"""
|
| 127 |
+
luma_width = luma_width or self.width
|
| 128 |
+
return -((-luma_width) >> self.ptr.log2_chroma_w) if luma_width else 0
|
| 129 |
+
|
| 130 |
+
@cython.ccall
|
| 131 |
+
def chroma_height(self, luma_height: cython.int = 0):
|
| 132 |
+
"""chroma_height(luma_height=0)
|
| 133 |
+
|
| 134 |
+
Height of a chroma plane relative to a luma plane.
|
| 135 |
+
|
| 136 |
+
:param int luma_height: Height of the luma plane; defaults to ``self.height``.
|
| 137 |
+
|
| 138 |
+
"""
|
| 139 |
+
luma_height = luma_height or self.height
|
| 140 |
+
return -((-luma_height) >> self.ptr.log2_chroma_h) if luma_height else 0
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
@cython.final
|
| 144 |
+
@cython.cclass
|
| 145 |
+
class VideoFormatComponent:
|
| 146 |
+
def __cinit__(self, format: VideoFormat, index: cython.size_t):
|
| 147 |
+
self.format = format
|
| 148 |
+
self.index = index
|
| 149 |
+
self.ptr = cython.address(format.ptr.comp[index])
|
| 150 |
+
|
| 151 |
+
@property
|
| 152 |
+
def plane(self):
|
| 153 |
+
"""The index of the plane which contains this component."""
|
| 154 |
+
return self.ptr.plane
|
| 155 |
+
|
| 156 |
+
@property
|
| 157 |
+
def bits(self):
|
| 158 |
+
"""Number of bits in the component."""
|
| 159 |
+
return self.ptr.depth
|
| 160 |
+
|
| 161 |
+
@property
|
| 162 |
+
def is_alpha(self):
|
| 163 |
+
"""Is this component an alpha channel?"""
|
| 164 |
+
return (self.index == 1 and self.format.ptr.nb_components == 2) or (
|
| 165 |
+
self.index == 3 and self.format.ptr.nb_components == 4
|
| 166 |
+
)
|
| 167 |
+
|
| 168 |
+
@property
|
| 169 |
+
def is_luma(self):
|
| 170 |
+
"""Is this component a luma channel?"""
|
| 171 |
+
return self.index == 0 and (
|
| 172 |
+
self.format.ptr.nb_components == 1
|
| 173 |
+
or self.format.ptr.nb_components == 2
|
| 174 |
+
or not self.format.is_rgb
|
| 175 |
+
)
|
| 176 |
+
|
| 177 |
+
@property
|
| 178 |
+
def is_chroma(self):
|
| 179 |
+
"""Is this component a chroma channel?"""
|
| 180 |
+
return (self.index == 1 or self.index == 2) and (
|
| 181 |
+
self.format.ptr.log2_chroma_w or self.format.ptr.log2_chroma_h
|
| 182 |
+
)
|
| 183 |
+
|
| 184 |
+
@property
|
| 185 |
+
def width(self):
|
| 186 |
+
"""The width of this component's plane.
|
| 187 |
+
|
| 188 |
+
Requires the parent :class:`VideoFormat` to have a width.
|
| 189 |
+
|
| 190 |
+
"""
|
| 191 |
+
return self.format.chroma_width() if self.is_chroma else self.format.width
|
| 192 |
+
|
| 193 |
+
@property
|
| 194 |
+
def height(self):
|
| 195 |
+
"""The height of this component's plane.
|
| 196 |
+
|
| 197 |
+
Requires the parent :class:`VideoFormat` to have a height.
|
| 198 |
+
|
| 199 |
+
"""
|
| 200 |
+
return self.format.chroma_height() if self.is_chroma else self.format.height
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
names = set()
|
| 204 |
+
desc = cython.declare(cython.pointer[cython.const[lib.AVPixFmtDescriptor]], cython.NULL)
|
| 205 |
+
while True:
|
| 206 |
+
desc = lib.av_pix_fmt_desc_next(desc)
|
| 207 |
+
if not desc:
|
| 208 |
+
break
|
| 209 |
+
names.add(desc.name)
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/format.pyi
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class VideoFormat:
|
| 2 |
+
name: str
|
| 3 |
+
bits_per_pixel: int
|
| 4 |
+
padded_bits_per_pixel: int
|
| 5 |
+
is_big_endian: bool
|
| 6 |
+
has_palette: bool
|
| 7 |
+
is_bit_stream: bool
|
| 8 |
+
is_planar: bool
|
| 9 |
+
width: int
|
| 10 |
+
height: int
|
| 11 |
+
@property
|
| 12 |
+
def components(self) -> tuple[VideoFormatComponent, ...]: ...
|
| 13 |
+
@property
|
| 14 |
+
def is_rgb(self) -> bool: ...
|
| 15 |
+
@property
|
| 16 |
+
def is_bayer(self) -> bool: ...
|
| 17 |
+
def __init__(self, name: str, width: int = 0, height: int = 0) -> None: ...
|
| 18 |
+
def chroma_width(self, luma_width: int = 0) -> int: ...
|
| 19 |
+
def chroma_height(self, luma_height: int = 0) -> int: ...
|
| 20 |
+
|
| 21 |
+
class VideoFormatComponent:
|
| 22 |
+
plane: int
|
| 23 |
+
bits: int
|
| 24 |
+
is_alpha: bool
|
| 25 |
+
is_luma: bool
|
| 26 |
+
is_chroma: bool
|
| 27 |
+
width: int
|
| 28 |
+
height: int
|
| 29 |
+
|
| 30 |
+
def __init__(self, format: VideoFormat, index: int) -> None: ...
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/frame.cpython-310-darwin.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1acbdb7f3a36ab3eba5cdca0d7d4b5d5f4e59a657aa024fa035ee2ae060c5f88
|
| 3 |
+
size 413152
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/frame.pxd
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cimport libav as lib
|
| 2 |
+
from libc.stdint cimport uint8_t
|
| 3 |
+
|
| 4 |
+
from av.frame cimport Frame
|
| 5 |
+
from av.video.format cimport VideoFormat
|
| 6 |
+
from av.video.reformatter cimport VideoReformatter
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
cdef class CudaContext:
|
| 10 |
+
cdef readonly int device_id
|
| 11 |
+
cdef readonly bint primary_ctx
|
| 12 |
+
cdef lib.AVBufferRef* _device_ref
|
| 13 |
+
cdef dict _frames_cache
|
| 14 |
+
cdef lib.AVBufferRef* _get_device_ref(self)
|
| 15 |
+
cdef public lib.AVBufferRef* get_frames_ctx(
|
| 16 |
+
self, lib.AVPixelFormat sw_fmt, int width, int height
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
cdef class VideoFrame(Frame):
|
| 20 |
+
cdef CudaContext _cuda_ctx
|
| 21 |
+
cdef VideoReformatter reformatter
|
| 22 |
+
cdef readonly VideoFormat format
|
| 23 |
+
cdef readonly int _device_id
|
| 24 |
+
cdef _init(self, lib.AVPixelFormat format, unsigned int width, unsigned int height)
|
| 25 |
+
cdef _init_user_attributes(self)
|
| 26 |
+
cpdef save(self, object filepath)
|
| 27 |
+
|
| 28 |
+
cdef VideoFrame alloc_video_frame()
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/frame.py
ADDED
|
@@ -0,0 +1,1631 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
from enum import IntEnum
|
| 3 |
+
|
| 4 |
+
import cython
|
| 5 |
+
import cython.cimports.libav as lib
|
| 6 |
+
from cython.cimports.av.dictionary import Dictionary
|
| 7 |
+
from cython.cimports.av.error import err_check
|
| 8 |
+
from cython.cimports.av.sidedata.sidedata import get_display_rotation
|
| 9 |
+
from cython.cimports.av.utils import check_ndarray
|
| 10 |
+
from cython.cimports.av.video.format import get_pix_fmt, get_video_format
|
| 11 |
+
from cython.cimports.av.video.plane import DLManagedTensor, VideoPlane, kCPU, kCuda
|
| 12 |
+
from cython.cimports.cpython.exc import PyErr_Clear
|
| 13 |
+
from cython.cimports.cpython.pycapsule import (
|
| 14 |
+
PyCapsule_GetPointer,
|
| 15 |
+
PyCapsule_IsValid,
|
| 16 |
+
PyCapsule_SetName,
|
| 17 |
+
)
|
| 18 |
+
from cython.cimports.cpython.ref import Py_DECREF, Py_INCREF
|
| 19 |
+
from cython.cimports.libc.stdint import int64_t, uint8_t
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
@cython.final
|
| 23 |
+
@cython.cclass
|
| 24 |
+
class CudaContext:
|
| 25 |
+
def __cinit__(self, device_id: cython.int = 0, primary_ctx: cython.bint = True):
|
| 26 |
+
self.device_id = device_id
|
| 27 |
+
self.primary_ctx = primary_ctx
|
| 28 |
+
self._device_ref = cython.NULL
|
| 29 |
+
self._frames_cache = {}
|
| 30 |
+
|
| 31 |
+
def __dealloc__(self):
|
| 32 |
+
ref: cython.pointer[lib.AVBufferRef]
|
| 33 |
+
|
| 34 |
+
for v in self._frames_cache.values():
|
| 35 |
+
ref = cython.cast(
|
| 36 |
+
cython.pointer[lib.AVBufferRef],
|
| 37 |
+
cython.cast(cython.size_t, v),
|
| 38 |
+
)
|
| 39 |
+
lib.av_buffer_unref(cython.address(ref))
|
| 40 |
+
self._frames_cache.clear()
|
| 41 |
+
|
| 42 |
+
ref = self._device_ref
|
| 43 |
+
if ref != cython.NULL:
|
| 44 |
+
lib.av_buffer_unref(cython.address(ref))
|
| 45 |
+
self._device_ref = cython.NULL
|
| 46 |
+
|
| 47 |
+
@cython.cfunc
|
| 48 |
+
def _get_device_ref(self) -> cython.pointer[lib.AVBufferRef]:
|
| 49 |
+
device_ref: cython.pointer[lib.AVBufferRef] = self._device_ref
|
| 50 |
+
if device_ref != cython.NULL:
|
| 51 |
+
return device_ref
|
| 52 |
+
|
| 53 |
+
device_ref = cython.NULL
|
| 54 |
+
device_bytes = f"{self.device_id}".encode()
|
| 55 |
+
c_device: cython.p_char = device_bytes
|
| 56 |
+
options: Dictionary = Dictionary(
|
| 57 |
+
{"primary_ctx": "1" if self.primary_ctx else "0"}
|
| 58 |
+
)
|
| 59 |
+
err_check(
|
| 60 |
+
lib.av_hwdevice_ctx_create(
|
| 61 |
+
cython.address(device_ref),
|
| 62 |
+
lib.AV_HWDEVICE_TYPE_CUDA,
|
| 63 |
+
c_device,
|
| 64 |
+
options.ptr,
|
| 65 |
+
0,
|
| 66 |
+
)
|
| 67 |
+
)
|
| 68 |
+
self._device_ref = device_ref
|
| 69 |
+
return device_ref
|
| 70 |
+
|
| 71 |
+
@cython.cfunc
|
| 72 |
+
def get_frames_ctx(
|
| 73 |
+
self,
|
| 74 |
+
sw_fmt: lib.AVPixelFormat,
|
| 75 |
+
width: cython.int,
|
| 76 |
+
height: cython.int,
|
| 77 |
+
) -> cython.pointer[lib.AVBufferRef]:
|
| 78 |
+
key = (int(sw_fmt), int(width), int(height))
|
| 79 |
+
cached = self._frames_cache.get(key)
|
| 80 |
+
cached_ref: cython.pointer[lib.AVBufferRef]
|
| 81 |
+
out_ref: cython.pointer[lib.AVBufferRef]
|
| 82 |
+
|
| 83 |
+
if cached is not None:
|
| 84 |
+
cached_ref = cython.cast(
|
| 85 |
+
cython.pointer[lib.AVBufferRef],
|
| 86 |
+
cython.cast(cython.size_t, cached),
|
| 87 |
+
)
|
| 88 |
+
out_ref = lib.av_buffer_ref(cached_ref)
|
| 89 |
+
if out_ref == cython.NULL:
|
| 90 |
+
raise MemoryError("av_buffer_ref() failed")
|
| 91 |
+
return out_ref
|
| 92 |
+
|
| 93 |
+
device_ref = self._get_device_ref()
|
| 94 |
+
|
| 95 |
+
frames_ref: cython.pointer[lib.AVBufferRef] = lib.av_hwframe_ctx_alloc(
|
| 96 |
+
device_ref
|
| 97 |
+
)
|
| 98 |
+
if frames_ref == cython.NULL:
|
| 99 |
+
raise MemoryError("av_hwframe_ctx_alloc() failed")
|
| 100 |
+
|
| 101 |
+
try:
|
| 102 |
+
frames_ctx: cython.pointer[lib.AVHWFramesContext] = cython.cast(
|
| 103 |
+
cython.pointer[lib.AVHWFramesContext], frames_ref.data
|
| 104 |
+
)
|
| 105 |
+
frames_ctx.format = get_pix_fmt(b"cuda")
|
| 106 |
+
frames_ctx.sw_format = sw_fmt
|
| 107 |
+
frames_ctx.width = int(width)
|
| 108 |
+
frames_ctx.height = int(height)
|
| 109 |
+
err_check(lib.av_hwframe_ctx_init(frames_ref))
|
| 110 |
+
except Exception:
|
| 111 |
+
lib.av_buffer_unref(cython.address(frames_ref))
|
| 112 |
+
raise
|
| 113 |
+
|
| 114 |
+
out_ref = lib.av_buffer_ref(frames_ref)
|
| 115 |
+
if out_ref == cython.NULL:
|
| 116 |
+
lib.av_buffer_unref(cython.address(frames_ref))
|
| 117 |
+
raise MemoryError("av_buffer_ref() failed")
|
| 118 |
+
|
| 119 |
+
self._frames_cache[key] = cython.cast(cython.size_t, frames_ref)
|
| 120 |
+
return out_ref
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
@cython.cfunc
|
| 124 |
+
def _consume_dlpack(obj: object, stream: object) -> cython.pointer[DLManagedTensor]:
|
| 125 |
+
capsule: object
|
| 126 |
+
managed: cython.pointer[DLManagedTensor]
|
| 127 |
+
|
| 128 |
+
if hasattr(obj, "__dlpack__"):
|
| 129 |
+
capsule = obj.__dlpack__() if stream is None else obj.__dlpack__(stream=stream)
|
| 130 |
+
else:
|
| 131 |
+
capsule = obj
|
| 132 |
+
|
| 133 |
+
if not PyCapsule_IsValid(capsule, b"dltensor"):
|
| 134 |
+
PyErr_Clear()
|
| 135 |
+
raise TypeError(
|
| 136 |
+
"expected a DLPack capsule or an object implementing __dlpack__"
|
| 137 |
+
)
|
| 138 |
+
|
| 139 |
+
managed = cython.cast(
|
| 140 |
+
cython.pointer[DLManagedTensor],
|
| 141 |
+
PyCapsule_GetPointer(capsule, b"dltensor"),
|
| 142 |
+
)
|
| 143 |
+
if managed == cython.NULL:
|
| 144 |
+
raise ValueError("PyCapsule_GetPointer returned NULL")
|
| 145 |
+
|
| 146 |
+
if PyCapsule_SetName(capsule, b"used_dltensor") != 0:
|
| 147 |
+
raise RuntimeError("PyCapsule_SetName failed")
|
| 148 |
+
|
| 149 |
+
return managed
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
@cython.cfunc
|
| 153 |
+
@cython.nogil
|
| 154 |
+
@cython.exceptval(check=False)
|
| 155 |
+
def _dlpack_avbuffer_free(
|
| 156 |
+
opaque: cython.p_void,
|
| 157 |
+
data: cython.pointer[uint8_t],
|
| 158 |
+
) -> cython.void:
|
| 159 |
+
managed: cython.pointer[DLManagedTensor] = cython.cast(
|
| 160 |
+
cython.pointer[DLManagedTensor], opaque
|
| 161 |
+
)
|
| 162 |
+
if managed != cython.NULL:
|
| 163 |
+
managed.deleter(managed)
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
@cython.cfunc
|
| 167 |
+
@cython.nogil
|
| 168 |
+
@cython.exceptval(check=False)
|
| 169 |
+
def _numpy_avbuffer_free(
|
| 170 |
+
opaque: cython.p_void,
|
| 171 |
+
data: cython.pointer[uint8_t],
|
| 172 |
+
) -> cython.void:
|
| 173 |
+
if opaque != cython.NULL:
|
| 174 |
+
with cython.gil:
|
| 175 |
+
Py_DECREF(cython.cast(object, opaque))
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
_cinit_bypass_sentinel = cython.declare(object, object())
|
| 179 |
+
|
| 180 |
+
# `pix_fmt`s supported by Frame.to_ndarray() and Frame.from_ndarray()
|
| 181 |
+
supported_np_pix_fmts = {
|
| 182 |
+
"abgr",
|
| 183 |
+
"argb",
|
| 184 |
+
"bayer_bggr16be",
|
| 185 |
+
"bayer_bggr16le",
|
| 186 |
+
"bayer_bggr8",
|
| 187 |
+
"bayer_gbrg16be",
|
| 188 |
+
"bayer_gbrg16le",
|
| 189 |
+
"bayer_gbrg8",
|
| 190 |
+
"bayer_grbg16be",
|
| 191 |
+
"bayer_grbg16le",
|
| 192 |
+
"bayer_grbg8",
|
| 193 |
+
"bayer_rggb16be",
|
| 194 |
+
"bayer_rggb16le",
|
| 195 |
+
"bayer_rggb8",
|
| 196 |
+
"bgr24",
|
| 197 |
+
"bgr48be",
|
| 198 |
+
"bgr48le",
|
| 199 |
+
"bgr8",
|
| 200 |
+
"bgra",
|
| 201 |
+
"bgra64be",
|
| 202 |
+
"bgra64le",
|
| 203 |
+
"gbrap",
|
| 204 |
+
"gbrap10be",
|
| 205 |
+
"gbrap10le",
|
| 206 |
+
"gbrap12be",
|
| 207 |
+
"gbrap12le",
|
| 208 |
+
"gbrap14be",
|
| 209 |
+
"gbrap14le",
|
| 210 |
+
"gbrap16be",
|
| 211 |
+
"gbrap16le",
|
| 212 |
+
"gbrapf32be",
|
| 213 |
+
"gbrapf32le",
|
| 214 |
+
"gbrp",
|
| 215 |
+
"gbrp10be",
|
| 216 |
+
"gbrp10le",
|
| 217 |
+
"gbrp12be",
|
| 218 |
+
"gbrp12le",
|
| 219 |
+
"gbrp14be",
|
| 220 |
+
"gbrp14le",
|
| 221 |
+
"gbrp16be",
|
| 222 |
+
"gbrp16le",
|
| 223 |
+
"gbrp9be",
|
| 224 |
+
"gbrp9le",
|
| 225 |
+
"gbrpf32be",
|
| 226 |
+
"gbrpf32le",
|
| 227 |
+
"gray",
|
| 228 |
+
"gray10be",
|
| 229 |
+
"gray10le",
|
| 230 |
+
"gray12be",
|
| 231 |
+
"gray12le",
|
| 232 |
+
"gray14be",
|
| 233 |
+
"gray14le",
|
| 234 |
+
"gray16be",
|
| 235 |
+
"gray16le",
|
| 236 |
+
"gray8",
|
| 237 |
+
"gray9be",
|
| 238 |
+
"gray9le",
|
| 239 |
+
"grayf32be",
|
| 240 |
+
"grayf32le",
|
| 241 |
+
"nv12",
|
| 242 |
+
"pal8",
|
| 243 |
+
"rgb24",
|
| 244 |
+
"rgb48be",
|
| 245 |
+
"rgb48le",
|
| 246 |
+
"rgb8",
|
| 247 |
+
"rgba",
|
| 248 |
+
"rgba64be",
|
| 249 |
+
"rgba64le",
|
| 250 |
+
"rgbaf16be",
|
| 251 |
+
"rgbaf16le",
|
| 252 |
+
"rgbaf32be",
|
| 253 |
+
"rgbaf32le",
|
| 254 |
+
"rgbf32be",
|
| 255 |
+
"rgbf32le",
|
| 256 |
+
"yuv420p",
|
| 257 |
+
"yuv422p10le",
|
| 258 |
+
"yuv444p",
|
| 259 |
+
"yuv444p16be",
|
| 260 |
+
"yuv444p16le",
|
| 261 |
+
"yuva444p16be",
|
| 262 |
+
"yuva444p16le",
|
| 263 |
+
"yuvj420p",
|
| 264 |
+
"yuvj444p",
|
| 265 |
+
"yuyv422",
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
# Mapping from format name to (itemsize, dtype) for formats where planes
|
| 269 |
+
# are simply concatenated into shape (height, width, channels).
|
| 270 |
+
_np_pix_fmt_dtypes = cython.declare(
|
| 271 |
+
dict[str, tuple[cython.uint, str]],
|
| 272 |
+
{
|
| 273 |
+
"abgr": (4, "uint8"),
|
| 274 |
+
"argb": (4, "uint8"),
|
| 275 |
+
"bayer_bggr8": (1, "uint8"),
|
| 276 |
+
"bayer_gbrg8": (1, "uint8"),
|
| 277 |
+
"bayer_grbg8": (1, "uint8"),
|
| 278 |
+
"bayer_rggb8": (1, "uint8"),
|
| 279 |
+
"bayer_bggr16le": (2, "uint16"),
|
| 280 |
+
"bayer_bggr16be": (2, "uint16"),
|
| 281 |
+
"bayer_gbrg16le": (2, "uint16"),
|
| 282 |
+
"bayer_gbrg16be": (2, "uint16"),
|
| 283 |
+
"bayer_grbg16le": (2, "uint16"),
|
| 284 |
+
"bayer_grbg16be": (2, "uint16"),
|
| 285 |
+
"bayer_rggb16le": (2, "uint16"),
|
| 286 |
+
"bayer_rggb16be": (2, "uint16"),
|
| 287 |
+
"bgr24": (3, "uint8"),
|
| 288 |
+
"bgr48be": (6, "uint16"),
|
| 289 |
+
"bgr48le": (6, "uint16"),
|
| 290 |
+
"bgr8": (1, "uint8"),
|
| 291 |
+
"bgra": (4, "uint8"),
|
| 292 |
+
"bgra64be": (8, "uint16"),
|
| 293 |
+
"bgra64le": (8, "uint16"),
|
| 294 |
+
"gbrap": (1, "uint8"),
|
| 295 |
+
"gbrap10be": (2, "uint16"),
|
| 296 |
+
"gbrap10le": (2, "uint16"),
|
| 297 |
+
"gbrap12be": (2, "uint16"),
|
| 298 |
+
"gbrap12le": (2, "uint16"),
|
| 299 |
+
"gbrap14be": (2, "uint16"),
|
| 300 |
+
"gbrap14le": (2, "uint16"),
|
| 301 |
+
"gbrap16be": (2, "uint16"),
|
| 302 |
+
"gbrap16le": (2, "uint16"),
|
| 303 |
+
"gbrapf32be": (4, "float32"),
|
| 304 |
+
"gbrapf32le": (4, "float32"),
|
| 305 |
+
"gbrp": (1, "uint8"),
|
| 306 |
+
"gbrp10be": (2, "uint16"),
|
| 307 |
+
"gbrp10le": (2, "uint16"),
|
| 308 |
+
"gbrp12be": (2, "uint16"),
|
| 309 |
+
"gbrp12le": (2, "uint16"),
|
| 310 |
+
"gbrp14be": (2, "uint16"),
|
| 311 |
+
"gbrp14le": (2, "uint16"),
|
| 312 |
+
"gbrp16be": (2, "uint16"),
|
| 313 |
+
"gbrp16le": (2, "uint16"),
|
| 314 |
+
"gbrp9be": (2, "uint16"),
|
| 315 |
+
"gbrp9le": (2, "uint16"),
|
| 316 |
+
"gbrpf32be": (4, "float32"),
|
| 317 |
+
"gbrpf32le": (4, "float32"),
|
| 318 |
+
"gray": (1, "uint8"),
|
| 319 |
+
"gray10be": (2, "uint16"),
|
| 320 |
+
"gray10le": (2, "uint16"),
|
| 321 |
+
"gray12be": (2, "uint16"),
|
| 322 |
+
"gray12le": (2, "uint16"),
|
| 323 |
+
"gray14be": (2, "uint16"),
|
| 324 |
+
"gray14le": (2, "uint16"),
|
| 325 |
+
"gray16be": (2, "uint16"),
|
| 326 |
+
"gray16le": (2, "uint16"),
|
| 327 |
+
"gray8": (1, "uint8"),
|
| 328 |
+
"gray9be": (2, "uint16"),
|
| 329 |
+
"gray9le": (2, "uint16"),
|
| 330 |
+
"grayf32be": (4, "float32"),
|
| 331 |
+
"grayf32le": (4, "float32"),
|
| 332 |
+
"rgb24": (3, "uint8"),
|
| 333 |
+
"rgb48be": (6, "uint16"),
|
| 334 |
+
"rgb48le": (6, "uint16"),
|
| 335 |
+
"rgb8": (1, "uint8"),
|
| 336 |
+
"rgba": (4, "uint8"),
|
| 337 |
+
"rgba64be": (8, "uint16"),
|
| 338 |
+
"rgba64le": (8, "uint16"),
|
| 339 |
+
"rgbaf16be": (8, "float16"),
|
| 340 |
+
"rgbaf16le": (8, "float16"),
|
| 341 |
+
"rgbaf32be": (16, "float32"),
|
| 342 |
+
"rgbaf32le": (16, "float32"),
|
| 343 |
+
"rgbf32be": (12, "float32"),
|
| 344 |
+
"rgbf32le": (12, "float32"),
|
| 345 |
+
"yuv444p": (1, "uint8"),
|
| 346 |
+
"yuv444p16be": (2, "uint16"),
|
| 347 |
+
"yuv444p16le": (2, "uint16"),
|
| 348 |
+
"yuva444p16be": (2, "uint16"),
|
| 349 |
+
"yuva444p16le": (2, "uint16"),
|
| 350 |
+
"yuvj444p": (1, "uint8"),
|
| 351 |
+
"yuyv422": (2, "uint8"),
|
| 352 |
+
},
|
| 353 |
+
)
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
@cython.cfunc
|
| 357 |
+
def alloc_video_frame() -> VideoFrame:
|
| 358 |
+
"""Get a mostly uninitialized VideoFrame.
|
| 359 |
+
|
| 360 |
+
You MUST call VideoFrame._init(...) or VideoFrame._init_user_attributes()
|
| 361 |
+
before exposing to the user.
|
| 362 |
+
|
| 363 |
+
"""
|
| 364 |
+
return VideoFrame(_cinit_bypass_sentinel)
|
| 365 |
+
|
| 366 |
+
|
| 367 |
+
class PictureType(IntEnum):
|
| 368 |
+
NONE = lib.AV_PICTURE_TYPE_NONE # Undefined
|
| 369 |
+
I = lib.AV_PICTURE_TYPE_I # Intra
|
| 370 |
+
P = lib.AV_PICTURE_TYPE_P # Predicted
|
| 371 |
+
B = lib.AV_PICTURE_TYPE_B # Bi-directional predicted
|
| 372 |
+
S = lib.AV_PICTURE_TYPE_S # S(GMC)-VOP MPEG-4
|
| 373 |
+
SI = lib.AV_PICTURE_TYPE_SI # Switching intra
|
| 374 |
+
SP = lib.AV_PICTURE_TYPE_SP # Switching predicted
|
| 375 |
+
BI = lib.AV_PICTURE_TYPE_BI # BI type
|
| 376 |
+
|
| 377 |
+
|
| 378 |
+
_is_big_endian = cython.declare(cython.bint, sys.byteorder == "big")
|
| 379 |
+
|
| 380 |
+
|
| 381 |
+
@cython.cfunc
|
| 382 |
+
@cython.inline
|
| 383 |
+
def byteswap_array(array, big_endian: cython.bint):
|
| 384 |
+
if _is_big_endian != big_endian:
|
| 385 |
+
return array.byteswap()
|
| 386 |
+
return array
|
| 387 |
+
|
| 388 |
+
|
| 389 |
+
@cython.cfunc
|
| 390 |
+
def copy_bytes_to_plane(
|
| 391 |
+
img_bytes,
|
| 392 |
+
plane: VideoPlane,
|
| 393 |
+
bytes_per_pixel: cython.uint,
|
| 394 |
+
flip_horizontal: cython.bint,
|
| 395 |
+
flip_vertical: cython.bint,
|
| 396 |
+
):
|
| 397 |
+
i_buf: cython.const[uint8_t][:] = img_bytes
|
| 398 |
+
i_pos: cython.size_t = 0
|
| 399 |
+
i_stride: cython.size_t = plane.width * bytes_per_pixel
|
| 400 |
+
|
| 401 |
+
o_buf: uint8_t[:] = plane
|
| 402 |
+
o_pos: cython.size_t = 0
|
| 403 |
+
o_stride: cython.size_t = abs(plane.line_size)
|
| 404 |
+
|
| 405 |
+
start_row, end_row, step = cython.declare(cython.int)
|
| 406 |
+
if flip_vertical:
|
| 407 |
+
start_row = plane.height - 1
|
| 408 |
+
end_row = -1
|
| 409 |
+
step = -1
|
| 410 |
+
else:
|
| 411 |
+
start_row = 0
|
| 412 |
+
end_row = plane.height
|
| 413 |
+
step = 1
|
| 414 |
+
|
| 415 |
+
for row in range(start_row, end_row, step):
|
| 416 |
+
i_pos = row * i_stride
|
| 417 |
+
if flip_horizontal:
|
| 418 |
+
i: cython.Py_ssize_t
|
| 419 |
+
for i in range(0, i_stride, bytes_per_pixel):
|
| 420 |
+
j: cython.Py_ssize_t
|
| 421 |
+
for j in range(bytes_per_pixel):
|
| 422 |
+
o_buf[o_pos + i + j] = i_buf[
|
| 423 |
+
i_pos + i_stride - i - bytes_per_pixel + j
|
| 424 |
+
]
|
| 425 |
+
else:
|
| 426 |
+
o_buf[o_pos : o_pos + i_stride] = i_buf[i_pos : i_pos + i_stride]
|
| 427 |
+
o_pos += o_stride
|
| 428 |
+
|
| 429 |
+
|
| 430 |
+
@cython.cfunc
|
| 431 |
+
def copy_array_to_plane(array, plane: VideoPlane, bytes_per_pixel: cython.uint):
|
| 432 |
+
imgbytes: bytes = array.tobytes()
|
| 433 |
+
copy_bytes_to_plane(imgbytes, plane, bytes_per_pixel, False, False)
|
| 434 |
+
|
| 435 |
+
|
| 436 |
+
@cython.cfunc
|
| 437 |
+
@cython.inline
|
| 438 |
+
def useful_array(
|
| 439 |
+
plane: VideoPlane, bytes_per_pixel: cython.uint = 1, dtype: str = "uint8"
|
| 440 |
+
):
|
| 441 |
+
"""
|
| 442 |
+
Return the useful part of the VideoPlane as a strided array.
|
| 443 |
+
|
| 444 |
+
We are simply creating a view that discards any padding which was added for
|
| 445 |
+
alignment.
|
| 446 |
+
"""
|
| 447 |
+
import numpy as np
|
| 448 |
+
|
| 449 |
+
dtype_obj = np.dtype(dtype)
|
| 450 |
+
line_size = plane.frame.ptr.linesize[plane.index]
|
| 451 |
+
total_line_size = abs(line_size)
|
| 452 |
+
itemsize = dtype_obj.itemsize
|
| 453 |
+
channels = bytes_per_pixel // itemsize
|
| 454 |
+
|
| 455 |
+
if channels == 1:
|
| 456 |
+
shape = (plane.height, plane.width)
|
| 457 |
+
strides = (total_line_size, itemsize)
|
| 458 |
+
else:
|
| 459 |
+
shape = (plane.height, plane.width, channels)
|
| 460 |
+
strides = (total_line_size, bytes_per_pixel, itemsize)
|
| 461 |
+
|
| 462 |
+
if line_size < 0:
|
| 463 |
+
offset = (plane.height - 1) * total_line_size
|
| 464 |
+
strides = (-total_line_size, *strides[1:])
|
| 465 |
+
return np.ndarray(
|
| 466 |
+
shape, dtype=dtype_obj, buffer=plane, offset=offset, strides=strides
|
| 467 |
+
)
|
| 468 |
+
|
| 469 |
+
return np.ndarray(shape, dtype=dtype_obj, buffer=plane, strides=strides)
|
| 470 |
+
|
| 471 |
+
|
| 472 |
+
@cython.cfunc
|
| 473 |
+
def check_ndarray_shape(array: object, ok: cython.bint):
|
| 474 |
+
if not ok:
|
| 475 |
+
raise ValueError(f"Unexpected numpy array shape `{array.shape}`")
|
| 476 |
+
|
| 477 |
+
|
| 478 |
+
@cython.final
|
| 479 |
+
@cython.cclass
|
| 480 |
+
class VideoFrame(Frame):
|
| 481 |
+
def __cinit__(self, width=0, height=0, format="yuv420p"):
|
| 482 |
+
if width is _cinit_bypass_sentinel:
|
| 483 |
+
return
|
| 484 |
+
|
| 485 |
+
c_format: lib.AVPixelFormat = get_pix_fmt(format)
|
| 486 |
+
self._init(c_format, width, height)
|
| 487 |
+
|
| 488 |
+
@cython.cfunc
|
| 489 |
+
def _init(self, format: lib.AVPixelFormat, width: cython.uint, height: cython.uint):
|
| 490 |
+
res: cython.int = 0
|
| 491 |
+
|
| 492 |
+
with cython.nogil:
|
| 493 |
+
self.ptr.width = width
|
| 494 |
+
self.ptr.height = height
|
| 495 |
+
self.ptr.format = format
|
| 496 |
+
|
| 497 |
+
# We enforce aligned buffers, otherwise `sws_scale_frame` can perform
|
| 498 |
+
# poorly or even cause out-of-bounds reads and writes.
|
| 499 |
+
if width and height:
|
| 500 |
+
res = lib.av_frame_get_buffer(self.ptr, 16)
|
| 501 |
+
|
| 502 |
+
if res:
|
| 503 |
+
err_check(res)
|
| 504 |
+
|
| 505 |
+
self._init_user_attributes()
|
| 506 |
+
|
| 507 |
+
@cython.cfunc
|
| 508 |
+
def _init_user_attributes(self):
|
| 509 |
+
self.format = get_video_format(
|
| 510 |
+
cython.cast(lib.AVPixelFormat, self.ptr.format),
|
| 511 |
+
self.ptr.width,
|
| 512 |
+
self.ptr.height,
|
| 513 |
+
)
|
| 514 |
+
|
| 515 |
+
def __dealloc__(self):
|
| 516 |
+
lib.av_frame_unref(self.ptr)
|
| 517 |
+
|
| 518 |
+
def __repr__(self):
|
| 519 |
+
return (
|
| 520 |
+
f"<av.{self.__class__.__name__}, pts={self.pts} {self.format.name} "
|
| 521 |
+
f"{self.width}x{self.height} at 0x{id(self):x}>"
|
| 522 |
+
)
|
| 523 |
+
|
| 524 |
+
@property
|
| 525 |
+
def planes(self):
|
| 526 |
+
"""
|
| 527 |
+
A tuple of :class:`.VideoPlane` objects.
|
| 528 |
+
"""
|
| 529 |
+
# We need to detect which planes actually exist, but also constrain ourselves to
|
| 530 |
+
# the maximum plane count (as determined only by VideoFrames so far), in case
|
| 531 |
+
# the library implementation does not set the last plane to NULL.
|
| 532 |
+
fmt = self.format
|
| 533 |
+
if self.ptr.hw_frames_ctx:
|
| 534 |
+
frames_ctx: cython.pointer[lib.AVHWFramesContext] = cython.cast(
|
| 535 |
+
cython.pointer[lib.AVHWFramesContext], self.ptr.hw_frames_ctx.data
|
| 536 |
+
)
|
| 537 |
+
fmt = get_video_format(
|
| 538 |
+
frames_ctx.sw_format, self.ptr.width, self.ptr.height
|
| 539 |
+
)
|
| 540 |
+
|
| 541 |
+
max_plane_count: cython.int = 0
|
| 542 |
+
for i in range(fmt.ptr.nb_components):
|
| 543 |
+
count = fmt.ptr.comp[i].plane + 1
|
| 544 |
+
if max_plane_count < count:
|
| 545 |
+
max_plane_count = count
|
| 546 |
+
if fmt.name == "pal8":
|
| 547 |
+
max_plane_count = 2
|
| 548 |
+
|
| 549 |
+
plane_count: cython.int = 0
|
| 550 |
+
while plane_count < max_plane_count and self.ptr.extended_data[plane_count]:
|
| 551 |
+
plane_count += 1
|
| 552 |
+
if plane_count == 1:
|
| 553 |
+
return (VideoPlane(self, 0),)
|
| 554 |
+
return tuple([VideoPlane(self, i) for i in range(plane_count)])
|
| 555 |
+
|
| 556 |
+
@property
|
| 557 |
+
def width(self):
|
| 558 |
+
"""Width of the image, in pixels."""
|
| 559 |
+
return self.ptr.width
|
| 560 |
+
|
| 561 |
+
@property
|
| 562 |
+
def height(self):
|
| 563 |
+
"""Height of the image, in pixels."""
|
| 564 |
+
return self.ptr.height
|
| 565 |
+
|
| 566 |
+
@property
|
| 567 |
+
def rotation(self):
|
| 568 |
+
"""The rotation component of the `DISPLAYMATRIX` transformation matrix.
|
| 569 |
+
|
| 570 |
+
Returns:
|
| 571 |
+
int: The angle (in degrees) by which the transformation rotates the frame
|
| 572 |
+
counterclockwise. The angle will be in range [-180, 180].
|
| 573 |
+
"""
|
| 574 |
+
return get_display_rotation(self)
|
| 575 |
+
|
| 576 |
+
@property
|
| 577 |
+
def interlaced_frame(self):
|
| 578 |
+
"""Is this frame an interlaced or progressive?"""
|
| 579 |
+
|
| 580 |
+
return bool(self.ptr.flags & lib.AV_FRAME_FLAG_INTERLACED)
|
| 581 |
+
|
| 582 |
+
@property
|
| 583 |
+
def pict_type(self):
|
| 584 |
+
"""Returns an integer that corresponds to the PictureType enum.
|
| 585 |
+
|
| 586 |
+
Wraps :ffmpeg:`AVFrame.pict_type`
|
| 587 |
+
|
| 588 |
+
:type: int
|
| 589 |
+
"""
|
| 590 |
+
return self.ptr.pict_type
|
| 591 |
+
|
| 592 |
+
@pict_type.setter
|
| 593 |
+
def pict_type(self, value):
|
| 594 |
+
self.ptr.pict_type = value
|
| 595 |
+
|
| 596 |
+
@property
|
| 597 |
+
def colorspace(self):
|
| 598 |
+
"""Colorspace of frame.
|
| 599 |
+
|
| 600 |
+
Wraps :ffmpeg:`AVFrame.colorspace`.
|
| 601 |
+
|
| 602 |
+
"""
|
| 603 |
+
return self.ptr.colorspace
|
| 604 |
+
|
| 605 |
+
@colorspace.setter
|
| 606 |
+
def colorspace(self, value):
|
| 607 |
+
self.ptr.colorspace = value
|
| 608 |
+
|
| 609 |
+
@property
|
| 610 |
+
def color_range(self):
|
| 611 |
+
"""Color range of frame.
|
| 612 |
+
|
| 613 |
+
Wraps :ffmpeg:`AVFrame.color_range`.
|
| 614 |
+
|
| 615 |
+
"""
|
| 616 |
+
return self.ptr.color_range
|
| 617 |
+
|
| 618 |
+
@color_range.setter
|
| 619 |
+
def color_range(self, value):
|
| 620 |
+
self.ptr.color_range = value
|
| 621 |
+
|
| 622 |
+
@property
|
| 623 |
+
def color_trc(self):
|
| 624 |
+
"""Transfer characteristic of frame.
|
| 625 |
+
|
| 626 |
+
Wraps :ffmpeg:`AVFrame.color_trc`.
|
| 627 |
+
|
| 628 |
+
"""
|
| 629 |
+
return self.ptr.color_trc
|
| 630 |
+
|
| 631 |
+
@color_trc.setter
|
| 632 |
+
def color_trc(self, value):
|
| 633 |
+
self.ptr.color_trc = value
|
| 634 |
+
|
| 635 |
+
@property
|
| 636 |
+
def color_primaries(self):
|
| 637 |
+
"""Color primaries of frame.
|
| 638 |
+
|
| 639 |
+
Wraps :ffmpeg:`AVFrame.color_primaries`.
|
| 640 |
+
|
| 641 |
+
"""
|
| 642 |
+
return self.ptr.color_primaries
|
| 643 |
+
|
| 644 |
+
@color_primaries.setter
|
| 645 |
+
def color_primaries(self, value):
|
| 646 |
+
self.ptr.color_primaries = value
|
| 647 |
+
|
| 648 |
+
def reformat(self, *args, **kwargs):
|
| 649 |
+
"""reformat(width=None, height=None, format=None, src_colorspace=None, dst_colorspace=None, interpolation=None, threads=None)
|
| 650 |
+
|
| 651 |
+
Create a new :class:`VideoFrame` with the given width/height/format/colorspace.
|
| 652 |
+
|
| 653 |
+
.. seealso:: :meth:`.VideoReformatter.reformat` for arguments.
|
| 654 |
+
|
| 655 |
+
"""
|
| 656 |
+
if not self.reformatter:
|
| 657 |
+
self.reformatter = VideoReformatter()
|
| 658 |
+
return self.reformatter.reformat(self, *args, **kwargs)
|
| 659 |
+
|
| 660 |
+
def to_rgb(self, **kwargs):
|
| 661 |
+
"""Get an RGB version of this frame.
|
| 662 |
+
|
| 663 |
+
Any ``**kwargs`` are passed to :meth:`.VideoReformatter.reformat`.
|
| 664 |
+
|
| 665 |
+
>>> frame = VideoFrame(1920, 1080)
|
| 666 |
+
>>> frame.format.name
|
| 667 |
+
'yuv420p'
|
| 668 |
+
>>> frame.to_rgb().format.name
|
| 669 |
+
'rgb24'
|
| 670 |
+
|
| 671 |
+
"""
|
| 672 |
+
return self.reformat(format="rgb24", **kwargs)
|
| 673 |
+
|
| 674 |
+
@cython.ccall
|
| 675 |
+
def save(self, filepath: object):
|
| 676 |
+
"""Save a VideoFrame as a JPG or PNG.
|
| 677 |
+
|
| 678 |
+
:param filepath: str | Path
|
| 679 |
+
"""
|
| 680 |
+
is_jpg: cython.bint
|
| 681 |
+
|
| 682 |
+
if filepath.endswith(".png"):
|
| 683 |
+
is_jpg = False
|
| 684 |
+
elif filepath.endswith(".jpg") or filepath.endswith(".jpeg"):
|
| 685 |
+
is_jpg = True
|
| 686 |
+
else:
|
| 687 |
+
raise ValueError("filepath must end with png or jpg.")
|
| 688 |
+
|
| 689 |
+
encoder: str = "mjpeg" if is_jpg else "png"
|
| 690 |
+
pix_fmt: str = "yuvj420p" if is_jpg else "rgb24"
|
| 691 |
+
|
| 692 |
+
from av.container.core import open
|
| 693 |
+
|
| 694 |
+
with open(filepath, "w", options={"update": "1"}) as output:
|
| 695 |
+
output_stream = output.add_stream(encoder, pix_fmt=pix_fmt)
|
| 696 |
+
output_stream.width = self.width
|
| 697 |
+
output_stream.height = self.height
|
| 698 |
+
|
| 699 |
+
output.mux(output_stream.encode(self.reformat(format=pix_fmt)))
|
| 700 |
+
output.mux(output_stream.encode(None))
|
| 701 |
+
|
| 702 |
+
def to_image(self, **kwargs):
|
| 703 |
+
"""Get an RGB ``PIL.Image`` of this frame.
|
| 704 |
+
|
| 705 |
+
Any ``**kwargs`` are passed to :meth:`.VideoReformatter.reformat`.
|
| 706 |
+
|
| 707 |
+
.. note:: PIL or Pillow must be installed.
|
| 708 |
+
|
| 709 |
+
"""
|
| 710 |
+
from PIL import Image
|
| 711 |
+
|
| 712 |
+
plane: VideoPlane = self.reformat(format="rgb24", **kwargs).planes[0]
|
| 713 |
+
|
| 714 |
+
i_buf: cython.const[uint8_t][:] = plane
|
| 715 |
+
line_size: cython.int = plane.line_size
|
| 716 |
+
i_stride: cython.size_t = abs(line_size)
|
| 717 |
+
|
| 718 |
+
o_pos: cython.size_t = 0
|
| 719 |
+
o_stride: cython.size_t = plane.width * 3
|
| 720 |
+
o_size: cython.size_t = plane.height * o_stride
|
| 721 |
+
o_buf: bytearray = bytearray(o_size)
|
| 722 |
+
|
| 723 |
+
# For bottom-up frames (negative line_size) the buffer protocol exposes
|
| 724 |
+
# rows from the lowest address, so the top display row is at the far end.
|
| 725 |
+
i_pos: cython.size_t = (plane.height - 1) * i_stride if line_size < 0 else 0
|
| 726 |
+
|
| 727 |
+
while o_pos < o_size:
|
| 728 |
+
o_buf[o_pos : o_pos + o_stride] = i_buf[i_pos : i_pos + o_stride]
|
| 729 |
+
if line_size < 0:
|
| 730 |
+
i_pos -= i_stride
|
| 731 |
+
else:
|
| 732 |
+
i_pos += i_stride
|
| 733 |
+
o_pos += o_stride
|
| 734 |
+
|
| 735 |
+
return Image.frombytes(
|
| 736 |
+
"RGB", (plane.width, plane.height), bytes(o_buf), "raw", "RGB", 0, 1
|
| 737 |
+
)
|
| 738 |
+
|
| 739 |
+
def to_ndarray(self, channel_last=False, **kwargs):
|
| 740 |
+
"""Get a numpy array of this frame.
|
| 741 |
+
|
| 742 |
+
Any ``**kwargs`` are passed to :meth:`.VideoReformatter.reformat`.
|
| 743 |
+
|
| 744 |
+
The array returned is generally of dimension (height, width, channels).
|
| 745 |
+
|
| 746 |
+
:param bool channel_last: If True, the shape of array will be
|
| 747 |
+
(height, width, channels) rather than (channels, height, width) for
|
| 748 |
+
the "yuv444p" and "yuvj444p" formats.
|
| 749 |
+
|
| 750 |
+
.. note:: Numpy must be installed.
|
| 751 |
+
|
| 752 |
+
.. note:: For formats which return an array of ``uint16``, ``float16`` or ``float32``,
|
| 753 |
+
the samples will be in the system's native byte order.
|
| 754 |
+
|
| 755 |
+
.. note:: For ``pal8``, an ``(image, palette)`` tuple will be returned,
|
| 756 |
+
with the palette being in ARGB (PyAV will swap bytes if needed).
|
| 757 |
+
|
| 758 |
+
.. note:: For ``gbrp`` formats, channels are flipped to RGB order.
|
| 759 |
+
|
| 760 |
+
"""
|
| 761 |
+
if self.ptr.hw_frames_ctx and "format" not in kwargs:
|
| 762 |
+
frames_ctx: cython.pointer[lib.AVHWFramesContext] = cython.cast(
|
| 763 |
+
cython.pointer[lib.AVHWFramesContext], self.ptr.hw_frames_ctx.data
|
| 764 |
+
)
|
| 765 |
+
kwargs = dict(kwargs)
|
| 766 |
+
kwargs["format"] = get_video_format(
|
| 767 |
+
frames_ctx.sw_format, self.ptr.width, self.ptr.height
|
| 768 |
+
).name
|
| 769 |
+
|
| 770 |
+
frame: VideoFrame = self.reformat(**kwargs) if len(kwargs) > 0 else self
|
| 771 |
+
if frame.ptr.hw_frames_ctx:
|
| 772 |
+
raise ValueError("Cannot convert a hardware frame to numpy directly.")
|
| 773 |
+
|
| 774 |
+
import numpy as np
|
| 775 |
+
|
| 776 |
+
# check size
|
| 777 |
+
format_name = frame.format.name
|
| 778 |
+
planes: tuple[VideoPlane, ...] = frame.planes
|
| 779 |
+
# cases planes are simply concatenated in shape (height, width, channels)
|
| 780 |
+
if format_name in _np_pix_fmt_dtypes:
|
| 781 |
+
if format_name == "yuyv422":
|
| 782 |
+
assert frame.ptr.width % 2 == 0, "width has to be even for yuyv422"
|
| 783 |
+
assert frame.ptr.height % 2 == 0, "height has to be even for yuyv422"
|
| 784 |
+
itemsize: cython.uint
|
| 785 |
+
itemsize, dtype = _np_pix_fmt_dtypes[format_name]
|
| 786 |
+
num_planes: cython.size_t = len(planes)
|
| 787 |
+
if num_planes == 1: # shortcut, avoid memory copy
|
| 788 |
+
array = useful_array(planes[0], itemsize, dtype)
|
| 789 |
+
else: # general case
|
| 790 |
+
array = np.empty(
|
| 791 |
+
(frame.ptr.height, frame.ptr.width, num_planes), dtype=dtype
|
| 792 |
+
)
|
| 793 |
+
if format_name.startswith("gbr"):
|
| 794 |
+
plane_indices = (2, 0, 1, *range(3, num_planes))
|
| 795 |
+
else:
|
| 796 |
+
plane_indices = range(num_planes)
|
| 797 |
+
for i, p_idx in enumerate(plane_indices):
|
| 798 |
+
array[:, :, i] = useful_array(planes[p_idx], itemsize, dtype)
|
| 799 |
+
array = byteswap_array(array, format_name.endswith("be"))
|
| 800 |
+
if not channel_last and format_name in {"yuv444p", "yuvj444p"}:
|
| 801 |
+
array = np.moveaxis(array, 2, 0)
|
| 802 |
+
return array
|
| 803 |
+
|
| 804 |
+
# special cases
|
| 805 |
+
if format_name in {"yuv420p", "yuvj420p", "yuv422p"}:
|
| 806 |
+
assert frame.ptr.width % 2 == 0, "width has to be even for this format"
|
| 807 |
+
assert frame.ptr.height % 2 == 0, "height has to be even for this format"
|
| 808 |
+
return np.hstack(
|
| 809 |
+
[
|
| 810 |
+
useful_array(planes[0]).reshape(-1),
|
| 811 |
+
useful_array(planes[1]).reshape(-1),
|
| 812 |
+
useful_array(planes[2]).reshape(-1),
|
| 813 |
+
]
|
| 814 |
+
).reshape(-1, frame.ptr.width)
|
| 815 |
+
if format_name == "yuv422p10le":
|
| 816 |
+
assert frame.ptr.width % 2 == 0, "width has to be even for this format"
|
| 817 |
+
assert frame.ptr.height % 2 == 0, "height has to be even for this format"
|
| 818 |
+
# Read planes as uint16 at their original width
|
| 819 |
+
y = useful_array(planes[0], 2, "uint16")
|
| 820 |
+
u = useful_array(planes[1], 2, "uint16")
|
| 821 |
+
v = useful_array(planes[2], 2, "uint16")
|
| 822 |
+
|
| 823 |
+
# Double the width of U and V by repeating each value
|
| 824 |
+
u_full = np.repeat(u, 2, axis=1)
|
| 825 |
+
v_full = np.repeat(v, 2, axis=1)
|
| 826 |
+
if channel_last:
|
| 827 |
+
return np.stack([y, u_full, v_full], axis=2)
|
| 828 |
+
return np.stack([y, u_full, v_full], axis=0)
|
| 829 |
+
if format_name == "pal8":
|
| 830 |
+
image = useful_array(planes[0])
|
| 831 |
+
palette = (
|
| 832 |
+
np.frombuffer(planes[1], "i4")
|
| 833 |
+
.astype(">i4")
|
| 834 |
+
.reshape(-1, 1)
|
| 835 |
+
.view(np.uint8)
|
| 836 |
+
)
|
| 837 |
+
return image, palette
|
| 838 |
+
if format_name == "nv12":
|
| 839 |
+
return np.hstack(
|
| 840 |
+
[
|
| 841 |
+
useful_array(planes[0]).reshape(-1),
|
| 842 |
+
useful_array(planes[1], 2).reshape(-1),
|
| 843 |
+
]
|
| 844 |
+
).reshape(-1, frame.ptr.width)
|
| 845 |
+
|
| 846 |
+
raise ValueError(
|
| 847 |
+
f"Conversion to numpy array with format `{format_name}` is not yet supported"
|
| 848 |
+
)
|
| 849 |
+
|
| 850 |
+
def set_image(self, img):
|
| 851 |
+
"""
|
| 852 |
+
Update content from a ``PIL.Image``.
|
| 853 |
+
"""
|
| 854 |
+
if img.mode != "RGB":
|
| 855 |
+
img = img.convert("RGB")
|
| 856 |
+
|
| 857 |
+
copy_array_to_plane(img, self.planes[0], 3)
|
| 858 |
+
|
| 859 |
+
@staticmethod
|
| 860 |
+
def from_image(img):
|
| 861 |
+
"""
|
| 862 |
+
Construct a frame from a ``PIL.Image``.
|
| 863 |
+
"""
|
| 864 |
+
frame: VideoFrame = VideoFrame(img.size[0], img.size[1], "rgb24")
|
| 865 |
+
frame.set_image(img)
|
| 866 |
+
|
| 867 |
+
return frame
|
| 868 |
+
|
| 869 |
+
@staticmethod
|
| 870 |
+
def from_numpy_buffer(array, format="rgb24", width=0):
|
| 871 |
+
"""
|
| 872 |
+
Construct a frame from a numpy buffer.
|
| 873 |
+
|
| 874 |
+
:param int width: optional width of actual image, if different from the array width.
|
| 875 |
+
|
| 876 |
+
.. note:: For formats which expect an array of ``uint16``, ``float16`` or ``float32``,
|
| 877 |
+
the samples must be in the system's native byte order.
|
| 878 |
+
|
| 879 |
+
.. note:: for ``gbrp`` formats, channels are assumed to be given in RGB order.
|
| 880 |
+
|
| 881 |
+
.. note:: For formats where width of the array is not the same as the width of the image,
|
| 882 |
+
for example with yuv420p images the UV rows at the bottom have padding bytes in the middle of the
|
| 883 |
+
row as well as at the end. To cope with these, callers need to be able to pass the actual width.
|
| 884 |
+
"""
|
| 885 |
+
import numpy as np
|
| 886 |
+
|
| 887 |
+
height = array.shape[0]
|
| 888 |
+
if not width:
|
| 889 |
+
width = array.shape[1]
|
| 890 |
+
|
| 891 |
+
if format in {"rgb24", "bgr24"}:
|
| 892 |
+
check_ndarray(array, "uint8", 3)
|
| 893 |
+
check_ndarray_shape(array, array.shape[2] == 3)
|
| 894 |
+
if array.strides[1:] != (3, 1):
|
| 895 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 896 |
+
linesizes = (array.strides[0],)
|
| 897 |
+
elif format in {"rgb48le", "rgb48be", "bgr48le", "bgr48be"}:
|
| 898 |
+
check_ndarray(array, "uint16", 3)
|
| 899 |
+
check_ndarray_shape(array, array.shape[2] == 3)
|
| 900 |
+
if array.strides[1:] != (6, 2):
|
| 901 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 902 |
+
linesizes = (array.strides[0],)
|
| 903 |
+
elif format in {"rgbf32le", "rgbf32be"}:
|
| 904 |
+
check_ndarray(array, "float32", 3)
|
| 905 |
+
check_ndarray_shape(array, array.shape[2] == 3)
|
| 906 |
+
if array.strides[1:] != (12, 4):
|
| 907 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 908 |
+
linesizes = (array.strides[0],)
|
| 909 |
+
elif format in {"rgba", "bgra", "argb", "abgr"}:
|
| 910 |
+
check_ndarray(array, "uint8", 3)
|
| 911 |
+
check_ndarray_shape(array, array.shape[2] == 4)
|
| 912 |
+
if array.strides[1:] != (4, 1):
|
| 913 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 914 |
+
linesizes = (array.strides[0],)
|
| 915 |
+
elif format in {"rgba64le", "rgba64be", "bgra64le", "bgra64be"}:
|
| 916 |
+
check_ndarray(array, "uint16", 3)
|
| 917 |
+
check_ndarray_shape(array, array.shape[2] == 4)
|
| 918 |
+
if array.strides[1:] != (8, 2):
|
| 919 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 920 |
+
linesizes = (array.strides[0],)
|
| 921 |
+
elif format in {"rgbaf16le", "rgbaf16be"}:
|
| 922 |
+
check_ndarray(array, "float16", 3)
|
| 923 |
+
check_ndarray_shape(array, array.shape[2] == 4)
|
| 924 |
+
if array.strides[1:] != (8, 2):
|
| 925 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 926 |
+
linesizes = (array.strides[0],)
|
| 927 |
+
elif format in {"rgbaf32le", "rgbaf32be"}:
|
| 928 |
+
check_ndarray(array, "float32", 3)
|
| 929 |
+
check_ndarray_shape(array, array.shape[2] == 4)
|
| 930 |
+
if array.strides[1:] != (16, 4):
|
| 931 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 932 |
+
linesizes = (array.strides[0],)
|
| 933 |
+
elif format in {
|
| 934 |
+
"gray",
|
| 935 |
+
"gray8",
|
| 936 |
+
"rgb8",
|
| 937 |
+
"bgr8",
|
| 938 |
+
"bayer_bggr8",
|
| 939 |
+
"bayer_gbrg8",
|
| 940 |
+
"bayer_grbg8",
|
| 941 |
+
"bayer_rggb8",
|
| 942 |
+
}:
|
| 943 |
+
check_ndarray(array, "uint8", 2)
|
| 944 |
+
if array.strides[1] != 1:
|
| 945 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 946 |
+
linesizes = (array.strides[0],)
|
| 947 |
+
elif format in {
|
| 948 |
+
"gray9be",
|
| 949 |
+
"gray9le",
|
| 950 |
+
"gray10be",
|
| 951 |
+
"gray10le",
|
| 952 |
+
"gray12be",
|
| 953 |
+
"gray12le",
|
| 954 |
+
"gray14be",
|
| 955 |
+
"gray14le",
|
| 956 |
+
"gray16be",
|
| 957 |
+
"gray16le",
|
| 958 |
+
"bayer_bggr16be",
|
| 959 |
+
"bayer_bggr16le",
|
| 960 |
+
"bayer_gbrg16be",
|
| 961 |
+
"bayer_gbrg16le",
|
| 962 |
+
"bayer_grbg16be",
|
| 963 |
+
"bayer_grbg16le",
|
| 964 |
+
"bayer_rggb16be",
|
| 965 |
+
"bayer_rggb16le",
|
| 966 |
+
}:
|
| 967 |
+
check_ndarray(array, "uint16", 2)
|
| 968 |
+
if array.strides[1] != 2:
|
| 969 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 970 |
+
linesizes = (array.strides[0],)
|
| 971 |
+
elif format in {"grayf32le", "grayf32be"}:
|
| 972 |
+
check_ndarray(array, "float32", 2)
|
| 973 |
+
if array.strides[1] != 4:
|
| 974 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 975 |
+
linesizes = (array.strides[0],)
|
| 976 |
+
elif format in {"gbrp"}:
|
| 977 |
+
check_ndarray(array, "uint8", 3)
|
| 978 |
+
check_ndarray_shape(array, array.shape[2] == 3)
|
| 979 |
+
if array.strides[1:] != (3, 1):
|
| 980 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 981 |
+
linesizes = (
|
| 982 |
+
array.strides[0] // 3,
|
| 983 |
+
array.strides[0] // 3,
|
| 984 |
+
array.strides[0] // 3,
|
| 985 |
+
)
|
| 986 |
+
elif format in {
|
| 987 |
+
"gbrp9be",
|
| 988 |
+
"gbrp9le",
|
| 989 |
+
"gbrp10be",
|
| 990 |
+
"gbrp10le",
|
| 991 |
+
"gbrp12be",
|
| 992 |
+
"gbrp12le",
|
| 993 |
+
"gbrp14be",
|
| 994 |
+
"gbrp14le",
|
| 995 |
+
"gbrp16be",
|
| 996 |
+
"gbrp16le",
|
| 997 |
+
}:
|
| 998 |
+
check_ndarray(array, "uint16", 3)
|
| 999 |
+
check_ndarray_shape(array, array.shape[2] == 3)
|
| 1000 |
+
if array.strides[1:] != (6, 2):
|
| 1001 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 1002 |
+
linesizes = (
|
| 1003 |
+
array.strides[0] // 3,
|
| 1004 |
+
array.strides[0] // 3,
|
| 1005 |
+
array.strides[0] // 3,
|
| 1006 |
+
)
|
| 1007 |
+
elif format in {"gbrpf32be", "gbrpf32le"}:
|
| 1008 |
+
check_ndarray(array, "float32", 3)
|
| 1009 |
+
check_ndarray_shape(array, array.shape[2] == 3)
|
| 1010 |
+
if array.strides[1:] != (12, 4):
|
| 1011 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 1012 |
+
linesizes = (
|
| 1013 |
+
array.strides[0] // 3,
|
| 1014 |
+
array.strides[0] // 3,
|
| 1015 |
+
array.strides[0] // 3,
|
| 1016 |
+
)
|
| 1017 |
+
elif format in {"gbrap"}:
|
| 1018 |
+
check_ndarray(array, "uint8", 3)
|
| 1019 |
+
check_ndarray_shape(array, array.shape[2] == 4)
|
| 1020 |
+
if array.strides[1:] != (4, 1):
|
| 1021 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 1022 |
+
linesizes = (
|
| 1023 |
+
array.strides[0] // 4,
|
| 1024 |
+
array.strides[0] // 4,
|
| 1025 |
+
array.strides[0] // 4,
|
| 1026 |
+
array.strides[0] // 4,
|
| 1027 |
+
)
|
| 1028 |
+
elif format in {
|
| 1029 |
+
"gbrap10be",
|
| 1030 |
+
"gbrap10le",
|
| 1031 |
+
"gbrap12be",
|
| 1032 |
+
"gbrap12le",
|
| 1033 |
+
"gbrap14be",
|
| 1034 |
+
"gbrap14le",
|
| 1035 |
+
"gbrap16be",
|
| 1036 |
+
"gbrap16le",
|
| 1037 |
+
}:
|
| 1038 |
+
check_ndarray(array, "uint16", 3)
|
| 1039 |
+
check_ndarray_shape(array, array.shape[2] == 4)
|
| 1040 |
+
if array.strides[1:] != (8, 2):
|
| 1041 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 1042 |
+
linesizes = (
|
| 1043 |
+
array.strides[0] // 4,
|
| 1044 |
+
array.strides[0] // 4,
|
| 1045 |
+
array.strides[0] // 4,
|
| 1046 |
+
array.strides[0] // 4,
|
| 1047 |
+
)
|
| 1048 |
+
elif format in {"gbrapf32be", "gbrapf32le"}:
|
| 1049 |
+
check_ndarray(array, "float32", 3)
|
| 1050 |
+
check_ndarray_shape(array, array.shape[2] == 4)
|
| 1051 |
+
if array.strides[1:] != (16, 4):
|
| 1052 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 1053 |
+
linesizes = (
|
| 1054 |
+
array.strides[0] // 4,
|
| 1055 |
+
array.strides[0] // 4,
|
| 1056 |
+
array.strides[0] // 4,
|
| 1057 |
+
array.strides[0] // 4,
|
| 1058 |
+
)
|
| 1059 |
+
elif format in {"yuv420p", "yuvj420p", "nv12"}:
|
| 1060 |
+
check_ndarray(array, "uint8", 2)
|
| 1061 |
+
check_ndarray_shape(array, array.shape[0] % 3 == 0)
|
| 1062 |
+
check_ndarray_shape(array, array.shape[1] % 2 == 0)
|
| 1063 |
+
height = height // 6 * 4
|
| 1064 |
+
if array.strides[1] != 1:
|
| 1065 |
+
raise ValueError("provided array does not have C_CONTIGUOUS rows")
|
| 1066 |
+
if format in {"yuv420p", "yuvj420p"}:
|
| 1067 |
+
# For YUV420 planar formats, the UV plane stride is always half the Y stride.
|
| 1068 |
+
linesizes = (
|
| 1069 |
+
array.strides[0],
|
| 1070 |
+
array.strides[0] // 2,
|
| 1071 |
+
array.strides[0] // 2,
|
| 1072 |
+
)
|
| 1073 |
+
else:
|
| 1074 |
+
# Planes where U and V are interleaved have the same stride as Y.
|
| 1075 |
+
linesizes = (array.strides[0], array.strides[0])
|
| 1076 |
+
else:
|
| 1077 |
+
raise ValueError(
|
| 1078 |
+
f"Conversion from numpy array with format `{format}` is not yet supported"
|
| 1079 |
+
)
|
| 1080 |
+
|
| 1081 |
+
if format.startswith("gbrap"): # rgba -> gbra
|
| 1082 |
+
array = np.ascontiguousarray(np.moveaxis(array[..., [1, 2, 0, 3]], -1, 0))
|
| 1083 |
+
elif format.startswith("gbrp"): # rgb -> gbr
|
| 1084 |
+
array = np.ascontiguousarray(np.moveaxis(array[..., [1, 2, 0]], -1, 0))
|
| 1085 |
+
|
| 1086 |
+
frame = VideoFrame(_cinit_bypass_sentinel)
|
| 1087 |
+
frame._image_fill_pointers_numpy(array, width, height, linesizes, format)
|
| 1088 |
+
return frame
|
| 1089 |
+
|
| 1090 |
+
def _image_fill_pointers_numpy(self, buffer, width, height, linesizes, format):
|
| 1091 |
+
# If you want to use the numpy notation, then you need to include the following lines at the top of the file:
|
| 1092 |
+
# cimport numpy as cnp
|
| 1093 |
+
# cnp.import_array()
|
| 1094 |
+
|
| 1095 |
+
# And add the numpy include directories to the setup.py files
|
| 1096 |
+
# hint np.get_include()
|
| 1097 |
+
# cdef cnp.ndarray[
|
| 1098 |
+
# dtype=cnp.uint8_t, ndim=1,
|
| 1099 |
+
# negative_indices=False, mode='c'] c_buffer
|
| 1100 |
+
# c_buffer = buffer.reshape(-1)
|
| 1101 |
+
# c_ptr = &c_buffer[0]
|
| 1102 |
+
# c_ptr = <uint8_t*> (<void*>(buffer.ctypes.data))
|
| 1103 |
+
|
| 1104 |
+
# Using buffer.ctypes.data helps avoid any kind of usage of the c-api from
|
| 1105 |
+
# numpy, which avoid the need to add numpy as a compile time dependency.
|
| 1106 |
+
|
| 1107 |
+
c_data: cython.Py_ssize_t = buffer.ctypes.data
|
| 1108 |
+
c_ptr: cython.pointer[uint8_t] = cython.cast(cython.pointer[uint8_t], c_data)
|
| 1109 |
+
c_format: lib.AVPixelFormat = get_pix_fmt(format)
|
| 1110 |
+
lib.av_frame_unref(self.ptr)
|
| 1111 |
+
|
| 1112 |
+
# Hold on to a reference for the numpy buffer so that it doesn't get accidentally garbage collected
|
| 1113 |
+
self.ptr.format = c_format
|
| 1114 |
+
self.ptr.width = width
|
| 1115 |
+
self.ptr.height = height
|
| 1116 |
+
for i, linesize in enumerate(linesizes):
|
| 1117 |
+
self.ptr.linesize[i] = linesize
|
| 1118 |
+
|
| 1119 |
+
required = err_check(
|
| 1120 |
+
lib.av_image_fill_pointers(
|
| 1121 |
+
self.ptr.data,
|
| 1122 |
+
cython.cast(lib.AVPixelFormat, self.ptr.format),
|
| 1123 |
+
self.ptr.height,
|
| 1124 |
+
c_ptr,
|
| 1125 |
+
self.ptr.linesize,
|
| 1126 |
+
)
|
| 1127 |
+
)
|
| 1128 |
+
|
| 1129 |
+
py_buf = cython.cast(object, buffer)
|
| 1130 |
+
Py_INCREF(py_buf)
|
| 1131 |
+
|
| 1132 |
+
self.ptr.buf[0] = lib.av_buffer_create(
|
| 1133 |
+
c_ptr,
|
| 1134 |
+
required,
|
| 1135 |
+
_numpy_avbuffer_free,
|
| 1136 |
+
cython.cast(cython.p_void, py_buf),
|
| 1137 |
+
0,
|
| 1138 |
+
)
|
| 1139 |
+
if self.ptr.buf[0] == cython.NULL:
|
| 1140 |
+
Py_DECREF(py_buf)
|
| 1141 |
+
raise MemoryError("av_buffer_create failed")
|
| 1142 |
+
|
| 1143 |
+
self._init_user_attributes()
|
| 1144 |
+
|
| 1145 |
+
@staticmethod
|
| 1146 |
+
def from_ndarray(array, format="rgb24", channel_last=False):
|
| 1147 |
+
"""
|
| 1148 |
+
Construct a frame from a numpy array.
|
| 1149 |
+
|
| 1150 |
+
:param bool channel_last: If False (default), the shape for the yuv444p and yuvj444p
|
| 1151 |
+
is given by (channels, height, width) rather than (height, width, channels).
|
| 1152 |
+
|
| 1153 |
+
.. note:: For formats which expect an array of ``uint16``, ``float16`` or ``float32``,
|
| 1154 |
+
the samples must be in the system's native byte order.
|
| 1155 |
+
|
| 1156 |
+
.. note:: for ``pal8``, an ``(image, palette)`` pair must be passed. `palette` must
|
| 1157 |
+
have shape (256, 4) and is given in ARGB format (PyAV will swap bytes if needed).
|
| 1158 |
+
|
| 1159 |
+
.. note:: for ``gbrp`` formats, channels are assumed to be given in RGB order.
|
| 1160 |
+
|
| 1161 |
+
"""
|
| 1162 |
+
import numpy as np
|
| 1163 |
+
|
| 1164 |
+
# case layers are concatenated
|
| 1165 |
+
channels, itemsize, dtype = {
|
| 1166 |
+
"bayer_bggr16be": (1, 2, "uint16"),
|
| 1167 |
+
"bayer_bggr16le": (1, 2, "uint16"),
|
| 1168 |
+
"bayer_bggr8": (1, 1, "uint8"),
|
| 1169 |
+
"bayer_gbrg16be": (1, 2, "uint16"),
|
| 1170 |
+
"bayer_gbrg16le": (1, 2, "uint16"),
|
| 1171 |
+
"bayer_gbrg8": (1, 1, "uint8"),
|
| 1172 |
+
"bayer_grbg16be": (1, 2, "uint16"),
|
| 1173 |
+
"bayer_grbg16le": (1, 2, "uint16"),
|
| 1174 |
+
"bayer_grbg8": (1, 1, "uint8"),
|
| 1175 |
+
"bayer_rggb16be": (1, 2, "uint16"),
|
| 1176 |
+
"bayer_rggb16le": (1, 2, "uint16"),
|
| 1177 |
+
"bayer_rggb8": (1, 1, "uint8"),
|
| 1178 |
+
"bgr8": (1, 1, "uint8"),
|
| 1179 |
+
"gbrap": (4, 1, "uint8"),
|
| 1180 |
+
"gbrap10be": (4, 2, "uint16"),
|
| 1181 |
+
"gbrap10le": (4, 2, "uint16"),
|
| 1182 |
+
"gbrap12be": (4, 2, "uint16"),
|
| 1183 |
+
"gbrap12le": (4, 2, "uint16"),
|
| 1184 |
+
"gbrap14be": (4, 2, "uint16"),
|
| 1185 |
+
"gbrap14le": (4, 2, "uint16"),
|
| 1186 |
+
"gbrap16be": (4, 2, "uint16"),
|
| 1187 |
+
"gbrap16le": (4, 2, "uint16"),
|
| 1188 |
+
"gbrapf32be": (4, 4, "float32"),
|
| 1189 |
+
"gbrapf32le": (4, 4, "float32"),
|
| 1190 |
+
"gbrp": (3, 1, "uint8"),
|
| 1191 |
+
"gbrp10be": (3, 2, "uint16"),
|
| 1192 |
+
"gbrp10le": (3, 2, "uint16"),
|
| 1193 |
+
"gbrp12be": (3, 2, "uint16"),
|
| 1194 |
+
"gbrp12le": (3, 2, "uint16"),
|
| 1195 |
+
"gbrp14be": (3, 2, "uint16"),
|
| 1196 |
+
"gbrp14le": (3, 2, "uint16"),
|
| 1197 |
+
"gbrp16be": (3, 2, "uint16"),
|
| 1198 |
+
"gbrp16le": (3, 2, "uint16"),
|
| 1199 |
+
"gbrp9be": (3, 2, "uint16"),
|
| 1200 |
+
"gbrp9le": (3, 2, "uint16"),
|
| 1201 |
+
"gbrpf32be": (3, 4, "float32"),
|
| 1202 |
+
"gbrpf32le": (3, 4, "float32"),
|
| 1203 |
+
"gray": (1, 1, "uint8"),
|
| 1204 |
+
"gray10be": (1, 2, "uint16"),
|
| 1205 |
+
"gray10le": (1, 2, "uint16"),
|
| 1206 |
+
"gray12be": (1, 2, "uint16"),
|
| 1207 |
+
"gray12le": (1, 2, "uint16"),
|
| 1208 |
+
"gray14be": (1, 2, "uint16"),
|
| 1209 |
+
"gray14le": (1, 2, "uint16"),
|
| 1210 |
+
"gray16be": (1, 2, "uint16"),
|
| 1211 |
+
"gray16le": (1, 2, "uint16"),
|
| 1212 |
+
"gray8": (1, 1, "uint8"),
|
| 1213 |
+
"gray9be": (1, 2, "uint16"),
|
| 1214 |
+
"gray9le": (1, 2, "uint16"),
|
| 1215 |
+
"grayf32be": (1, 4, "float32"),
|
| 1216 |
+
"grayf32le": (1, 4, "float32"),
|
| 1217 |
+
"rgb8": (1, 1, "uint8"),
|
| 1218 |
+
"yuv444p": (3, 1, "uint8"),
|
| 1219 |
+
"yuv444p16be": (3, 2, "uint16"),
|
| 1220 |
+
"yuv444p16le": (3, 2, "uint16"),
|
| 1221 |
+
"yuva444p16be": (4, 2, "uint16"),
|
| 1222 |
+
"yuva444p16le": (4, 2, "uint16"),
|
| 1223 |
+
"yuvj444p": (3, 1, "uint8"),
|
| 1224 |
+
}.get(format, (None, None, None))
|
| 1225 |
+
if channels is not None:
|
| 1226 |
+
if array.ndim == 2: # (height, width) -> (height, width, 1)
|
| 1227 |
+
array = array[:, :, None]
|
| 1228 |
+
check_ndarray(array, dtype, 3)
|
| 1229 |
+
if not channel_last and format in {"yuv444p", "yuvj444p"}:
|
| 1230 |
+
array = np.moveaxis(array, 0, 2) # (channels, h, w) -> (h, w, channels)
|
| 1231 |
+
check_ndarray_shape(array, array.shape[2] == channels)
|
| 1232 |
+
array = byteswap_array(array, format.endswith("be"))
|
| 1233 |
+
frame = VideoFrame(array.shape[1], array.shape[0], format)
|
| 1234 |
+
if frame.format.name.startswith("gbr"): # rgb -> gbr
|
| 1235 |
+
array = np.concatenate(
|
| 1236 |
+
[ # not inplace to avoid bad surprises
|
| 1237 |
+
array[:, :, 1:3],
|
| 1238 |
+
array[:, :, 0:1],
|
| 1239 |
+
array[:, :, 3:],
|
| 1240 |
+
],
|
| 1241 |
+
axis=2,
|
| 1242 |
+
)
|
| 1243 |
+
for i in range(channels):
|
| 1244 |
+
copy_array_to_plane(array[:, :, i], frame.planes[i], itemsize)
|
| 1245 |
+
return frame
|
| 1246 |
+
|
| 1247 |
+
# other cases
|
| 1248 |
+
if format == "pal8":
|
| 1249 |
+
array, palette = array
|
| 1250 |
+
check_ndarray(array, "uint8", 2)
|
| 1251 |
+
check_ndarray(palette, "uint8", 2)
|
| 1252 |
+
check_ndarray_shape(palette, palette.shape == (256, 4))
|
| 1253 |
+
|
| 1254 |
+
frame = VideoFrame(array.shape[1], array.shape[0], format)
|
| 1255 |
+
copy_array_to_plane(array, frame.planes[0], 1)
|
| 1256 |
+
frame.planes[1].update(palette.view(">i4").astype("i4").tobytes())
|
| 1257 |
+
return frame
|
| 1258 |
+
elif format in {"yuv420p", "yuvj420p"}:
|
| 1259 |
+
check_ndarray(array, "uint8", 2)
|
| 1260 |
+
check_ndarray_shape(array, array.shape[0] % 3 == 0)
|
| 1261 |
+
check_ndarray_shape(array, array.shape[1] % 2 == 0)
|
| 1262 |
+
|
| 1263 |
+
frame = VideoFrame(array.shape[1], (array.shape[0] * 2) // 3, format)
|
| 1264 |
+
u_start = frame.width * frame.height
|
| 1265 |
+
v_start = 5 * u_start // 4
|
| 1266 |
+
flat = array.reshape(-1)
|
| 1267 |
+
copy_array_to_plane(flat[0:u_start], frame.planes[0], 1)
|
| 1268 |
+
copy_array_to_plane(flat[u_start:v_start], frame.planes[1], 1)
|
| 1269 |
+
copy_array_to_plane(flat[v_start:], frame.planes[2], 1)
|
| 1270 |
+
return frame
|
| 1271 |
+
elif format == "yuv422p":
|
| 1272 |
+
check_ndarray(array, "uint8", 2)
|
| 1273 |
+
check_ndarray_shape(array, array.shape[0] % 4 == 0)
|
| 1274 |
+
check_ndarray_shape(array, array.shape[1] % 2 == 0)
|
| 1275 |
+
|
| 1276 |
+
frame = VideoFrame(array.shape[1], array.shape[0] // 2, format)
|
| 1277 |
+
u_start = frame.width * frame.height
|
| 1278 |
+
v_start = u_start + u_start // 2
|
| 1279 |
+
flat = array.reshape(-1)
|
| 1280 |
+
copy_array_to_plane(flat[0:u_start], frame.planes[0], 1)
|
| 1281 |
+
copy_array_to_plane(flat[u_start:v_start], frame.planes[1], 1)
|
| 1282 |
+
copy_array_to_plane(flat[v_start:], frame.planes[2], 1)
|
| 1283 |
+
return frame
|
| 1284 |
+
elif format == "yuv422p10le":
|
| 1285 |
+
if not isinstance(array, np.ndarray) or array.dtype != np.uint16:
|
| 1286 |
+
raise ValueError("Array must be uint16 type")
|
| 1287 |
+
|
| 1288 |
+
# Convert to channel-first if needed
|
| 1289 |
+
if channel_last and array.shape[2] == 3:
|
| 1290 |
+
array = np.moveaxis(array, 2, 0)
|
| 1291 |
+
elif not (array.shape[0] == 3):
|
| 1292 |
+
raise ValueError(
|
| 1293 |
+
"Array must have shape (3, height, width) or (height, width, 3)"
|
| 1294 |
+
)
|
| 1295 |
+
|
| 1296 |
+
height, width = array.shape[1:]
|
| 1297 |
+
if width % 2 != 0 or height % 2 != 0:
|
| 1298 |
+
raise ValueError("Width and height must be even")
|
| 1299 |
+
|
| 1300 |
+
frame = VideoFrame(width, height, format)
|
| 1301 |
+
copy_array_to_plane(array[0], frame.planes[0], 2)
|
| 1302 |
+
# Subsample U and V by taking every other column
|
| 1303 |
+
u = array[1, :, ::2].copy() # Need copy to ensure C-contiguous
|
| 1304 |
+
v = array[2, :, ::2].copy() # Need copy to ensure C-contiguous
|
| 1305 |
+
copy_array_to_plane(u, frame.planes[1], 2)
|
| 1306 |
+
copy_array_to_plane(v, frame.planes[2], 2)
|
| 1307 |
+
return frame
|
| 1308 |
+
elif format == "yuyv422":
|
| 1309 |
+
check_ndarray(array, "uint8", 3)
|
| 1310 |
+
check_ndarray_shape(array, array.shape[0] % 2 == 0)
|
| 1311 |
+
check_ndarray_shape(array, array.shape[1] % 2 == 0)
|
| 1312 |
+
check_ndarray_shape(array, array.shape[2] == 2)
|
| 1313 |
+
elif format in {"rgb24", "bgr24"}:
|
| 1314 |
+
check_ndarray(array, "uint8", 3)
|
| 1315 |
+
check_ndarray_shape(array, array.shape[2] == 3)
|
| 1316 |
+
elif format in {"argb", "rgba", "abgr", "bgra"}:
|
| 1317 |
+
check_ndarray(array, "uint8", 3)
|
| 1318 |
+
check_ndarray_shape(array, array.shape[2] == 4)
|
| 1319 |
+
elif format in {"rgb48be", "rgb48le", "bgr48be", "bgr48le"}:
|
| 1320 |
+
check_ndarray(array, "uint16", 3)
|
| 1321 |
+
check_ndarray_shape(array, array.shape[2] == 3)
|
| 1322 |
+
frame = VideoFrame(array.shape[1], array.shape[0], format)
|
| 1323 |
+
copy_array_to_plane(
|
| 1324 |
+
byteswap_array(array, format.endswith("be")), frame.planes[0], 6
|
| 1325 |
+
)
|
| 1326 |
+
return frame
|
| 1327 |
+
elif format in {"rgbf32be", "rgbf32le"}:
|
| 1328 |
+
check_ndarray(array, "float32", 3)
|
| 1329 |
+
check_ndarray_shape(array, array.shape[2] == 3)
|
| 1330 |
+
frame = VideoFrame(array.shape[1], array.shape[0], format)
|
| 1331 |
+
copy_array_to_plane(
|
| 1332 |
+
byteswap_array(array, format.endswith("be")), frame.planes[0], 12
|
| 1333 |
+
)
|
| 1334 |
+
return frame
|
| 1335 |
+
elif format in {"rgba64be", "rgba64le", "bgra64be", "bgra64le"}:
|
| 1336 |
+
check_ndarray(array, "uint16", 3)
|
| 1337 |
+
check_ndarray_shape(array, array.shape[2] == 4)
|
| 1338 |
+
frame = VideoFrame(array.shape[1], array.shape[0], format)
|
| 1339 |
+
copy_array_to_plane(
|
| 1340 |
+
byteswap_array(array, format.endswith("be")), frame.planes[0], 8
|
| 1341 |
+
)
|
| 1342 |
+
return frame
|
| 1343 |
+
elif format in {"rgbaf16be", "rgbaf16le"}:
|
| 1344 |
+
check_ndarray(array, "float16", 3)
|
| 1345 |
+
check_ndarray_shape(array, array.shape[2] == 4)
|
| 1346 |
+
frame = VideoFrame(array.shape[1], array.shape[0], format)
|
| 1347 |
+
copy_array_to_plane(
|
| 1348 |
+
byteswap_array(array, format.endswith("be")), frame.planes[0], 8
|
| 1349 |
+
)
|
| 1350 |
+
return frame
|
| 1351 |
+
elif format in {"rgbaf32be", "rgbaf32le"}:
|
| 1352 |
+
check_ndarray(array, "float32", 3)
|
| 1353 |
+
check_ndarray_shape(array, array.shape[2] == 4)
|
| 1354 |
+
frame = VideoFrame(array.shape[1], array.shape[0], format)
|
| 1355 |
+
copy_array_to_plane(
|
| 1356 |
+
byteswap_array(array, format.endswith("be")), frame.planes[0], 16
|
| 1357 |
+
)
|
| 1358 |
+
return frame
|
| 1359 |
+
elif format == "nv12":
|
| 1360 |
+
check_ndarray(array, "uint8", 2)
|
| 1361 |
+
check_ndarray_shape(array, array.shape[0] % 3 == 0)
|
| 1362 |
+
check_ndarray_shape(array, array.shape[1] % 2 == 0)
|
| 1363 |
+
|
| 1364 |
+
frame = VideoFrame(array.shape[1], (array.shape[0] * 2) // 3, format)
|
| 1365 |
+
uv_start = frame.width * frame.height
|
| 1366 |
+
flat = array.reshape(-1)
|
| 1367 |
+
copy_array_to_plane(flat[:uv_start], frame.planes[0], 1)
|
| 1368 |
+
copy_array_to_plane(flat[uv_start:], frame.planes[1], 2)
|
| 1369 |
+
return frame
|
| 1370 |
+
else:
|
| 1371 |
+
raise ValueError(
|
| 1372 |
+
f"Conversion from numpy array with format `{format}` is not yet supported"
|
| 1373 |
+
)
|
| 1374 |
+
|
| 1375 |
+
frame = VideoFrame(array.shape[1], array.shape[0], format)
|
| 1376 |
+
copy_array_to_plane(
|
| 1377 |
+
array, frame.planes[0], 1 if array.ndim == 2 else array.shape[2]
|
| 1378 |
+
)
|
| 1379 |
+
|
| 1380 |
+
return frame
|
| 1381 |
+
|
| 1382 |
+
@staticmethod
|
| 1383 |
+
def from_bytes(
|
| 1384 |
+
img_bytes: bytes,
|
| 1385 |
+
width: int,
|
| 1386 |
+
height: int,
|
| 1387 |
+
format="rgba",
|
| 1388 |
+
flip_horizontal=False,
|
| 1389 |
+
flip_vertical=False,
|
| 1390 |
+
):
|
| 1391 |
+
frame = VideoFrame(width, height, format)
|
| 1392 |
+
if format == "rgba":
|
| 1393 |
+
copy_bytes_to_plane(
|
| 1394 |
+
img_bytes, frame.planes[0], 4, flip_horizontal, flip_vertical
|
| 1395 |
+
)
|
| 1396 |
+
elif format in {
|
| 1397 |
+
"bayer_bggr8",
|
| 1398 |
+
"bayer_rggb8",
|
| 1399 |
+
"bayer_gbrg8",
|
| 1400 |
+
"bayer_grbg8",
|
| 1401 |
+
"bayer_bggr16le",
|
| 1402 |
+
"bayer_rggb16le",
|
| 1403 |
+
"bayer_gbrg16le",
|
| 1404 |
+
"bayer_grbg16le",
|
| 1405 |
+
"bayer_bggr16be",
|
| 1406 |
+
"bayer_rggb16be",
|
| 1407 |
+
"bayer_gbrg16be",
|
| 1408 |
+
"bayer_grbg16be",
|
| 1409 |
+
}:
|
| 1410 |
+
copy_bytes_to_plane(
|
| 1411 |
+
img_bytes,
|
| 1412 |
+
frame.planes[0],
|
| 1413 |
+
1 if format.endswith("8") else 2,
|
| 1414 |
+
flip_horizontal,
|
| 1415 |
+
flip_vertical,
|
| 1416 |
+
)
|
| 1417 |
+
else:
|
| 1418 |
+
raise NotImplementedError(f"Format '{format}' is not supported.")
|
| 1419 |
+
return frame
|
| 1420 |
+
|
| 1421 |
+
@staticmethod
|
| 1422 |
+
def from_dlpack(
|
| 1423 |
+
planes,
|
| 1424 |
+
format: str = "nv12",
|
| 1425 |
+
width: int = 0,
|
| 1426 |
+
height: int = 0,
|
| 1427 |
+
stream=None,
|
| 1428 |
+
device_id: int | None = None,
|
| 1429 |
+
primary_ctx: bool = True,
|
| 1430 |
+
cuda_context=None,
|
| 1431 |
+
):
|
| 1432 |
+
if not isinstance(planes, (tuple, list)):
|
| 1433 |
+
planes = (planes,)
|
| 1434 |
+
|
| 1435 |
+
if len(planes) != 2:
|
| 1436 |
+
raise ValueError(
|
| 1437 |
+
"from_dlpack currently supports 2-plane formats only (nv12/p010le/p016le)"
|
| 1438 |
+
)
|
| 1439 |
+
|
| 1440 |
+
sw_fmt: lib.AVPixelFormat = get_pix_fmt(format)
|
| 1441 |
+
nv12 = get_pix_fmt(b"nv12")
|
| 1442 |
+
p010le = get_pix_fmt(b"p010le")
|
| 1443 |
+
p016le = get_pix_fmt(b"p016le")
|
| 1444 |
+
|
| 1445 |
+
if sw_fmt not in (nv12, p010le, p016le):
|
| 1446 |
+
raise NotImplementedError("from_dlpack supports nv12, p010le, p016le only")
|
| 1447 |
+
|
| 1448 |
+
expected_bits = 8 if sw_fmt == nv12 else 16
|
| 1449 |
+
itemsize = 1 if expected_bits == 8 else 2
|
| 1450 |
+
|
| 1451 |
+
m0: cython.pointer[DLManagedTensor] = cython.NULL
|
| 1452 |
+
m1: cython.pointer[DLManagedTensor] = cython.NULL
|
| 1453 |
+
frame: VideoFrame = None
|
| 1454 |
+
|
| 1455 |
+
try:
|
| 1456 |
+
m0 = _consume_dlpack(planes[0], stream)
|
| 1457 |
+
m1 = _consume_dlpack(planes[1], stream)
|
| 1458 |
+
|
| 1459 |
+
dev_type0 = m0.dl_tensor.device_type
|
| 1460 |
+
dev_type1 = m1.dl_tensor.device_type
|
| 1461 |
+
if dev_type0 != dev_type1:
|
| 1462 |
+
raise ValueError("plane tensors must have the same device_type")
|
| 1463 |
+
if dev_type0 not in (kCuda, kCPU):
|
| 1464 |
+
raise NotImplementedError(
|
| 1465 |
+
"only CPU and CUDA DLPack tensors are supported"
|
| 1466 |
+
)
|
| 1467 |
+
|
| 1468 |
+
dev0 = m0.dl_tensor.device_id
|
| 1469 |
+
dev1 = m1.dl_tensor.device_id
|
| 1470 |
+
if dev0 != dev1:
|
| 1471 |
+
raise ValueError("plane tensors must be on the same CUDA device")
|
| 1472 |
+
if dev_type0 == kCuda:
|
| 1473 |
+
if device_id is None:
|
| 1474 |
+
device_id = dev0
|
| 1475 |
+
elif device_id != dev0:
|
| 1476 |
+
raise ValueError(
|
| 1477 |
+
"device_id does not match the DLPack tensor device_id"
|
| 1478 |
+
)
|
| 1479 |
+
else:
|
| 1480 |
+
if device_id not in (None, 0):
|
| 1481 |
+
raise ValueError("device_id must be 0 for CPU tensors")
|
| 1482 |
+
device_id = 0
|
| 1483 |
+
if dev_type0 == kCPU and (dev0 != 0 or dev1 != 0):
|
| 1484 |
+
raise ValueError("CPU DLPack tensors must have device_id == 0")
|
| 1485 |
+
|
| 1486 |
+
if (
|
| 1487 |
+
m0.dl_tensor.dtype.code != 1
|
| 1488 |
+
or m0.dl_tensor.dtype.bits != expected_bits
|
| 1489 |
+
or m0.dl_tensor.dtype.lanes != 1
|
| 1490 |
+
):
|
| 1491 |
+
raise TypeError("unexpected dtype for plane 0")
|
| 1492 |
+
if (
|
| 1493 |
+
m1.dl_tensor.dtype.code != 1
|
| 1494 |
+
or m1.dl_tensor.dtype.bits != expected_bits
|
| 1495 |
+
or m1.dl_tensor.dtype.lanes != 1
|
| 1496 |
+
):
|
| 1497 |
+
raise TypeError("unexpected dtype for plane 1")
|
| 1498 |
+
|
| 1499 |
+
if m0.dl_tensor.ndim != 2:
|
| 1500 |
+
raise ValueError("plane 0 must be 2D (H, W)")
|
| 1501 |
+
|
| 1502 |
+
y_h = cython.cast(int64_t, m0.dl_tensor.shape[0])
|
| 1503 |
+
y_w = cython.cast(int64_t, m0.dl_tensor.shape[1])
|
| 1504 |
+
|
| 1505 |
+
if width == 0 and height == 0:
|
| 1506 |
+
width = cython.cast(int, y_w)
|
| 1507 |
+
height = cython.cast(int, y_h)
|
| 1508 |
+
elif width == 0 or height == 0:
|
| 1509 |
+
raise ValueError("either specify both width/height or neither")
|
| 1510 |
+
else:
|
| 1511 |
+
if y_w != width or y_h != height:
|
| 1512 |
+
raise ValueError("plane 0 shape does not match width/height")
|
| 1513 |
+
|
| 1514 |
+
if width % 2 or height % 2:
|
| 1515 |
+
raise ValueError("width/height must be even for nv12/p010le/p016le")
|
| 1516 |
+
|
| 1517 |
+
if m0.dl_tensor.strides != cython.NULL:
|
| 1518 |
+
if m0.dl_tensor.strides[1] != 1:
|
| 1519 |
+
raise ValueError("plane 0 must be contiguous in the last dimension")
|
| 1520 |
+
y_pitch_elems = cython.cast(int64_t, m0.dl_tensor.strides[0])
|
| 1521 |
+
else:
|
| 1522 |
+
y_pitch_elems = cython.cast(int64_t, width)
|
| 1523 |
+
|
| 1524 |
+
y_linesize = cython.cast(int, y_pitch_elems * itemsize)
|
| 1525 |
+
y_size = cython.cast(int, y_linesize * height)
|
| 1526 |
+
|
| 1527 |
+
uv_ndim = m1.dl_tensor.ndim
|
| 1528 |
+
uv_h_expected = height // 2
|
| 1529 |
+
|
| 1530 |
+
if uv_ndim == 2:
|
| 1531 |
+
uv_h = cython.cast(int, m1.dl_tensor.shape[0])
|
| 1532 |
+
uv_w = cython.cast(int, m1.dl_tensor.shape[1])
|
| 1533 |
+
if uv_h != uv_h_expected or uv_w != width:
|
| 1534 |
+
raise ValueError("plane 1 must have shape (H/2, W) for 2D UV")
|
| 1535 |
+
if m1.dl_tensor.strides != cython.NULL:
|
| 1536 |
+
if m1.dl_tensor.strides[1] != 1:
|
| 1537 |
+
raise ValueError(
|
| 1538 |
+
"plane 1 must be contiguous in the last dimension"
|
| 1539 |
+
)
|
| 1540 |
+
uv_pitch_elems = cython.cast(int64_t, m1.dl_tensor.strides[0])
|
| 1541 |
+
else:
|
| 1542 |
+
uv_pitch_elems = cython.cast(int64_t, uv_w)
|
| 1543 |
+
elif uv_ndim == 3:
|
| 1544 |
+
uv_h = cython.cast(int, m1.dl_tensor.shape[0])
|
| 1545 |
+
uv_w2 = cython.cast(int, m1.dl_tensor.shape[1])
|
| 1546 |
+
uv_c = cython.cast(int, m1.dl_tensor.shape[2])
|
| 1547 |
+
if uv_h != uv_h_expected or uv_w2 != (width // 2) or uv_c != 2:
|
| 1548 |
+
raise ValueError("plane 1 must have shape (H/2, W/2, 2) for 3D UV")
|
| 1549 |
+
if m1.dl_tensor.strides != cython.NULL:
|
| 1550 |
+
if m1.dl_tensor.strides[2] != 1 or m1.dl_tensor.strides[1] != 2:
|
| 1551 |
+
raise ValueError(
|
| 1552 |
+
"unexpected UV plane strides for (H/2, W/2, 2)"
|
| 1553 |
+
)
|
| 1554 |
+
uv_pitch_elems = cython.cast(int64_t, m1.dl_tensor.strides[0])
|
| 1555 |
+
else:
|
| 1556 |
+
uv_pitch_elems = cython.cast(int64_t, width)
|
| 1557 |
+
else:
|
| 1558 |
+
raise ValueError("plane 1 must be 2D or 3D")
|
| 1559 |
+
|
| 1560 |
+
uv_linesize = cython.cast(int, uv_pitch_elems * itemsize)
|
| 1561 |
+
uv_size = cython.cast(int, uv_linesize * (height // 2))
|
| 1562 |
+
|
| 1563 |
+
frame = alloc_video_frame()
|
| 1564 |
+
frame.ptr.width = width
|
| 1565 |
+
frame.ptr.height = height
|
| 1566 |
+
if dev_type0 == kCuda:
|
| 1567 |
+
ctx: CudaContext
|
| 1568 |
+
frames_ref: cython.pointer[lib.AVBufferRef]
|
| 1569 |
+
if cuda_context is None:
|
| 1570 |
+
ctx = CudaContext(device_id=device_id, primary_ctx=primary_ctx)
|
| 1571 |
+
else:
|
| 1572 |
+
if not isinstance(cuda_context, CudaContext):
|
| 1573 |
+
raise TypeError("cuda_context must be a CudaContext")
|
| 1574 |
+
if int(cuda_context.device_id) != int(device_id):
|
| 1575 |
+
raise ValueError(
|
| 1576 |
+
"cuda_context.device_id does not match the DLPack tensor device_id"
|
| 1577 |
+
)
|
| 1578 |
+
if bool(cuda_context.primary_ctx) != bool(primary_ctx):
|
| 1579 |
+
raise ValueError(
|
| 1580 |
+
"cuda_context.primary_ctx does not match primary_ctx"
|
| 1581 |
+
)
|
| 1582 |
+
ctx = cython.cast(CudaContext, cuda_context)
|
| 1583 |
+
|
| 1584 |
+
frames_ref = ctx.get_frames_ctx(sw_fmt, width, height)
|
| 1585 |
+
frame.ptr.format = get_pix_fmt(b"cuda")
|
| 1586 |
+
frame.ptr.hw_frames_ctx = frames_ref
|
| 1587 |
+
frame._device_id = device_id
|
| 1588 |
+
frame._cuda_ctx = ctx
|
| 1589 |
+
else:
|
| 1590 |
+
frame.ptr.format = sw_fmt
|
| 1591 |
+
|
| 1592 |
+
y_ptr = cython.cast(
|
| 1593 |
+
cython.pointer[uint8_t], m0.dl_tensor.data
|
| 1594 |
+
) + cython.cast(cython.size_t, m0.dl_tensor.byte_offset)
|
| 1595 |
+
uv_ptr = cython.cast(
|
| 1596 |
+
cython.pointer[uint8_t], m1.dl_tensor.data
|
| 1597 |
+
) + cython.cast(cython.size_t, m1.dl_tensor.byte_offset)
|
| 1598 |
+
|
| 1599 |
+
frame.ptr.buf[0] = lib.av_buffer_create(
|
| 1600 |
+
y_ptr, y_size, _dlpack_avbuffer_free, cython.cast(cython.p_void, m0), 0
|
| 1601 |
+
)
|
| 1602 |
+
if frame.ptr.buf[0] == cython.NULL:
|
| 1603 |
+
raise MemoryError("av_buffer_create failed for plane 0")
|
| 1604 |
+
frame.ptr.data[0] = y_ptr
|
| 1605 |
+
frame.ptr.linesize[0] = y_linesize
|
| 1606 |
+
m0 = cython.NULL
|
| 1607 |
+
|
| 1608 |
+
frame.ptr.buf[1] = lib.av_buffer_create(
|
| 1609 |
+
uv_ptr,
|
| 1610 |
+
uv_size,
|
| 1611 |
+
_dlpack_avbuffer_free,
|
| 1612 |
+
cython.cast(cython.p_void, m1),
|
| 1613 |
+
0,
|
| 1614 |
+
)
|
| 1615 |
+
if frame.ptr.buf[1] == cython.NULL:
|
| 1616 |
+
raise MemoryError("av_buffer_create failed for plane 1")
|
| 1617 |
+
frame.ptr.data[1] = uv_ptr
|
| 1618 |
+
frame.ptr.linesize[1] = uv_linesize
|
| 1619 |
+
m1 = cython.NULL
|
| 1620 |
+
|
| 1621 |
+
frame._init_user_attributes()
|
| 1622 |
+
return frame
|
| 1623 |
+
|
| 1624 |
+
except Exception:
|
| 1625 |
+
if frame is not None:
|
| 1626 |
+
lib.av_frame_unref(frame.ptr)
|
| 1627 |
+
if m0 != cython.NULL:
|
| 1628 |
+
m0.deleter(m0)
|
| 1629 |
+
if m1 != cython.NULL:
|
| 1630 |
+
m1.deleter(m1)
|
| 1631 |
+
raise
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/frame.pyi
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from enum import IntEnum
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
from typing import Any, Union
|
| 4 |
+
|
| 5 |
+
import numpy as np
|
| 6 |
+
|
| 7 |
+
from av.frame import Frame
|
| 8 |
+
|
| 9 |
+
from .format import VideoFormat
|
| 10 |
+
from .plane import VideoPlane
|
| 11 |
+
from .reformatter import ColorPrimaries, ColorTrc
|
| 12 |
+
|
| 13 |
+
_SupportedNDarray = Union[
|
| 14 |
+
np.ndarray[Any, np.dtype[np.uint8]],
|
| 15 |
+
np.ndarray[Any, np.dtype[np.uint16]],
|
| 16 |
+
np.ndarray[Any, np.dtype[np.float16]],
|
| 17 |
+
np.ndarray[Any, np.dtype[np.float32]],
|
| 18 |
+
]
|
| 19 |
+
|
| 20 |
+
supported_np_pix_fmts: set[str]
|
| 21 |
+
|
| 22 |
+
class PictureType(IntEnum):
|
| 23 |
+
NONE = 0
|
| 24 |
+
I = 1
|
| 25 |
+
P = 2
|
| 26 |
+
B = 3
|
| 27 |
+
S = 4
|
| 28 |
+
SI = 5
|
| 29 |
+
SP = 6
|
| 30 |
+
BI = 7
|
| 31 |
+
|
| 32 |
+
class CudaContext:
|
| 33 |
+
@property
|
| 34 |
+
def device_id(self) -> int: ...
|
| 35 |
+
@property
|
| 36 |
+
def primary_ctx(self) -> bool: ...
|
| 37 |
+
def __init__(self, device_id: int = 0, primary_ctx: bool = True) -> None: ...
|
| 38 |
+
|
| 39 |
+
class VideoFrame(Frame):
|
| 40 |
+
format: VideoFormat
|
| 41 |
+
planes: tuple[VideoPlane, ...]
|
| 42 |
+
pict_type: int
|
| 43 |
+
colorspace: int
|
| 44 |
+
color_range: int
|
| 45 |
+
color_trc: int
|
| 46 |
+
color_primaries: int
|
| 47 |
+
|
| 48 |
+
@property
|
| 49 |
+
def time(self) -> float: ...
|
| 50 |
+
@property
|
| 51 |
+
def width(self) -> int: ...
|
| 52 |
+
@property
|
| 53 |
+
def height(self) -> int: ...
|
| 54 |
+
@property
|
| 55 |
+
def interlaced_frame(self) -> bool: ...
|
| 56 |
+
@property
|
| 57 |
+
def rotation(self) -> int: ...
|
| 58 |
+
def __init__(
|
| 59 |
+
self, width: int = 0, height: int = 0, format: str = "yuv420p"
|
| 60 |
+
) -> None: ...
|
| 61 |
+
def reformat(
|
| 62 |
+
self,
|
| 63 |
+
width: int | None = None,
|
| 64 |
+
height: int | None = None,
|
| 65 |
+
format: str | None = None,
|
| 66 |
+
src_colorspace: str | int | None = None,
|
| 67 |
+
dst_colorspace: str | int | None = None,
|
| 68 |
+
interpolation: int | str | None = None,
|
| 69 |
+
src_color_range: int | str | None = None,
|
| 70 |
+
dst_color_range: int | str | None = None,
|
| 71 |
+
dst_color_trc: int | ColorTrc | None = None,
|
| 72 |
+
dst_color_primaries: int | ColorPrimaries | None = None,
|
| 73 |
+
threads: int | None = None,
|
| 74 |
+
) -> VideoFrame: ...
|
| 75 |
+
def to_rgb(self, **kwargs: Any) -> VideoFrame: ...
|
| 76 |
+
def save(self, filepath: str | Path) -> None: ...
|
| 77 |
+
def to_image(self, **kwargs): ...
|
| 78 |
+
def to_ndarray(
|
| 79 |
+
self, channel_last: bool = False, **kwargs: Any
|
| 80 |
+
) -> _SupportedNDarray: ...
|
| 81 |
+
@staticmethod
|
| 82 |
+
def from_image(img): ...
|
| 83 |
+
@staticmethod
|
| 84 |
+
def from_numpy_buffer(
|
| 85 |
+
array: _SupportedNDarray, format: str = "rgb24", width: int = 0
|
| 86 |
+
) -> VideoFrame: ...
|
| 87 |
+
@staticmethod
|
| 88 |
+
def from_ndarray(
|
| 89 |
+
array: _SupportedNDarray, format: str = "rgb24", channel_last: bool = False
|
| 90 |
+
) -> VideoFrame: ...
|
| 91 |
+
@staticmethod
|
| 92 |
+
def from_bytes(
|
| 93 |
+
data: bytes,
|
| 94 |
+
width: int,
|
| 95 |
+
height: int,
|
| 96 |
+
format: str = "rgba",
|
| 97 |
+
flip_horizontal: bool = False,
|
| 98 |
+
flip_vertical: bool = False,
|
| 99 |
+
) -> VideoFrame: ...
|
| 100 |
+
@staticmethod
|
| 101 |
+
def from_dlpack(
|
| 102 |
+
planes: object | tuple[object, ...],
|
| 103 |
+
format: str = "nv12",
|
| 104 |
+
width: int = 0,
|
| 105 |
+
height: int = 0,
|
| 106 |
+
stream: int | None = None,
|
| 107 |
+
device_id: int | None = None,
|
| 108 |
+
primary_ctx: bool = True,
|
| 109 |
+
cuda_context: CudaContext | None = None,
|
| 110 |
+
) -> VideoFrame: ...
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/plane.cpython-310-darwin.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a0a050b7e962550479fe28418c37731601d3ccd3489c574fef23b1da6cbbef62
|
| 3 |
+
size 117184
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/plane.pxd
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from libc.stdint cimport int64_t, uint8_t, uint16_t, uint64_t
|
| 2 |
+
|
| 3 |
+
from av.plane cimport Plane
|
| 4 |
+
from av.video.format cimport VideoFormatComponent
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
cdef class VideoPlane(Plane):
|
| 8 |
+
cdef readonly size_t buffer_size
|
| 9 |
+
cdef readonly unsigned int width, height
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
cdef enum DeviceType:
|
| 13 |
+
kCPU = 1
|
| 14 |
+
kCuda = 2
|
| 15 |
+
|
| 16 |
+
cdef struct DLDataType:
|
| 17 |
+
uint8_t code
|
| 18 |
+
uint8_t bits
|
| 19 |
+
uint16_t lanes
|
| 20 |
+
|
| 21 |
+
cdef struct DLTensor:
|
| 22 |
+
void* data
|
| 23 |
+
int device_type
|
| 24 |
+
int device_id
|
| 25 |
+
int ndim
|
| 26 |
+
DLDataType dtype
|
| 27 |
+
int64_t* shape
|
| 28 |
+
int64_t* strides
|
| 29 |
+
uint64_t byte_offset
|
| 30 |
+
|
| 31 |
+
cdef struct DLManagedTensor
|
| 32 |
+
|
| 33 |
+
ctypedef void (*DLManagedTensorDeleter)(DLManagedTensor*) noexcept nogil
|
| 34 |
+
|
| 35 |
+
cdef struct DLManagedTensor:
|
| 36 |
+
DLTensor dl_tensor
|
| 37 |
+
void* manager_ctx
|
| 38 |
+
DLManagedTensorDeleter deleter
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/plane.py
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import cython
|
| 2 |
+
import cython.cimports.libav as lib
|
| 3 |
+
from cython.cimports.av.error import err_check
|
| 4 |
+
from cython.cimports.av.video.format import (
|
| 5 |
+
VideoFormatComponent,
|
| 6 |
+
get_pix_fmt,
|
| 7 |
+
get_video_format,
|
| 8 |
+
)
|
| 9 |
+
from cython.cimports.av.video.frame import VideoFrame
|
| 10 |
+
from cython.cimports.cpython import PyBUF_WRITABLE, PyBuffer_FillInfo
|
| 11 |
+
from cython.cimports.cpython.buffer import Py_buffer
|
| 12 |
+
from cython.cimports.cpython.pycapsule import (
|
| 13 |
+
PyCapsule_GetPointer,
|
| 14 |
+
PyCapsule_IsValid,
|
| 15 |
+
PyCapsule_New,
|
| 16 |
+
)
|
| 17 |
+
from cython.cimports.libc.stdlib import free, malloc
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
@cython.final
|
| 21 |
+
@cython.cclass
|
| 22 |
+
class VideoPlane(Plane):
|
| 23 |
+
def __cinit__(self, frame: VideoFrame, index: cython.int):
|
| 24 |
+
# The palette plane has no associated component or linesize; set fields manually
|
| 25 |
+
fmt = frame.format
|
| 26 |
+
if frame.ptr.hw_frames_ctx:
|
| 27 |
+
frames_ctx: cython.pointer[lib.AVHWFramesContext] = cython.cast(
|
| 28 |
+
cython.pointer[lib.AVHWFramesContext], frame.ptr.hw_frames_ctx.data
|
| 29 |
+
)
|
| 30 |
+
fmt = get_video_format(
|
| 31 |
+
frames_ctx.sw_format, frame.ptr.width, frame.ptr.height
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
if index == 1 and fmt.name == "pal8":
|
| 35 |
+
self.width = 256
|
| 36 |
+
self.height = 1
|
| 37 |
+
self.buffer_size = 256 * 4
|
| 38 |
+
return
|
| 39 |
+
|
| 40 |
+
for i in range(fmt.ptr.nb_components):
|
| 41 |
+
if fmt.ptr.comp[i].plane == index:
|
| 42 |
+
component = VideoFormatComponent(fmt, i)
|
| 43 |
+
self.width = component.width
|
| 44 |
+
self.height = component.height
|
| 45 |
+
break
|
| 46 |
+
else:
|
| 47 |
+
raise RuntimeError(f"could not find plane {index} of {fmt!r}")
|
| 48 |
+
|
| 49 |
+
# Sometimes, linesize is negative (and that is meaningful). We are only
|
| 50 |
+
# insisting that the buffer size be based on the extent of linesize, and
|
| 51 |
+
# ignore it's direction.
|
| 52 |
+
self.buffer_size = abs(self.frame.ptr.linesize[self.index]) * self.height
|
| 53 |
+
|
| 54 |
+
@cython.cfunc
|
| 55 |
+
def _buffer_size(self) -> cython.size_t:
|
| 56 |
+
return self.buffer_size
|
| 57 |
+
|
| 58 |
+
@property
|
| 59 |
+
def line_size(self):
|
| 60 |
+
"""
|
| 61 |
+
Bytes per horizontal line in this plane.
|
| 62 |
+
|
| 63 |
+
:type: int
|
| 64 |
+
"""
|
| 65 |
+
return self.frame.ptr.linesize[self.index]
|
| 66 |
+
|
| 67 |
+
@cython.cfunc
|
| 68 |
+
def _buffer_writable(self) -> cython.bint:
|
| 69 |
+
if self.frame.ptr.hw_frames_ctx:
|
| 70 |
+
return False
|
| 71 |
+
return True
|
| 72 |
+
|
| 73 |
+
def __getbuffer__(self, view: cython.pointer[Py_buffer], flags: cython.int):
|
| 74 |
+
if self.frame.ptr.hw_frames_ctx:
|
| 75 |
+
raise TypeError(
|
| 76 |
+
"Hardware frame planes do not support the Python buffer protocol. "
|
| 77 |
+
"Use DLPack (__dlpack__) or download to a software frame."
|
| 78 |
+
)
|
| 79 |
+
if flags & PyBUF_WRITABLE and not self._buffer_writable():
|
| 80 |
+
raise ValueError("buffer is not writable")
|
| 81 |
+
|
| 82 |
+
ptr: cython.p_void = self._buffer_ptr()
|
| 83 |
+
line_size: cython.int = self.frame.ptr.linesize[self.index]
|
| 84 |
+
if line_size < 0:
|
| 85 |
+
height: cython.int = self.height
|
| 86 |
+
ptr = cython.cast(cython.p_char, ptr) + (height - 1) * line_size
|
| 87 |
+
|
| 88 |
+
PyBuffer_FillInfo(view, self, ptr, self._buffer_size(), 0, flags)
|
| 89 |
+
|
| 90 |
+
def __dlpack_device__(self):
|
| 91 |
+
if self.frame.ptr.hw_frames_ctx:
|
| 92 |
+
if cython.cast(lib.AVPixelFormat, self.frame.ptr.format) != get_pix_fmt(
|
| 93 |
+
b"cuda"
|
| 94 |
+
):
|
| 95 |
+
raise NotImplementedError(
|
| 96 |
+
"DLPack export is only implemented for CUDA hw frames"
|
| 97 |
+
)
|
| 98 |
+
return (kCuda, self.frame._device_id)
|
| 99 |
+
return (kCPU, 0)
|
| 100 |
+
|
| 101 |
+
def __dlpack__(self, *, stream: int | None = None):
|
| 102 |
+
if self.frame.ptr.buf[0] == cython.NULL:
|
| 103 |
+
raise TypeError(
|
| 104 |
+
"DLPack export requires a refcounted AVFrame (frame.buf[0] is NULL)"
|
| 105 |
+
)
|
| 106 |
+
|
| 107 |
+
sw_fmt: lib.AVPixelFormat
|
| 108 |
+
device_type: cython.int
|
| 109 |
+
device_id: cython.int
|
| 110 |
+
|
| 111 |
+
if self.frame.ptr.hw_frames_ctx:
|
| 112 |
+
if cython.cast(lib.AVPixelFormat, self.frame.ptr.format) != get_pix_fmt(
|
| 113 |
+
b"cuda"
|
| 114 |
+
):
|
| 115 |
+
raise NotImplementedError(
|
| 116 |
+
"DLPack export is only implemented for CUDA hw frames"
|
| 117 |
+
)
|
| 118 |
+
if stream is not None:
|
| 119 |
+
raise NotImplementedError(
|
| 120 |
+
"CUDA stream synchronization is not supported. "
|
| 121 |
+
"Pass stream=None and synchronize before calling __dlpack__."
|
| 122 |
+
)
|
| 123 |
+
|
| 124 |
+
frames_ctx: cython.pointer[lib.AVHWFramesContext] = cython.cast(
|
| 125 |
+
cython.pointer[lib.AVHWFramesContext], self.frame.ptr.hw_frames_ctx.data
|
| 126 |
+
)
|
| 127 |
+
sw_fmt = frames_ctx.sw_format
|
| 128 |
+
device_type = kCuda
|
| 129 |
+
device_id = self.frame._device_id
|
| 130 |
+
else:
|
| 131 |
+
sw_fmt = cython.cast(lib.AVPixelFormat, self.frame.ptr.format)
|
| 132 |
+
device_type = kCPU
|
| 133 |
+
device_id = 0
|
| 134 |
+
|
| 135 |
+
line_size = self.line_size
|
| 136 |
+
if line_size < 0:
|
| 137 |
+
raise NotImplementedError(
|
| 138 |
+
"negative linesize is not supported for DLPack export"
|
| 139 |
+
)
|
| 140 |
+
|
| 141 |
+
nv12 = get_pix_fmt(b"nv12")
|
| 142 |
+
p010le = get_pix_fmt(b"p010le")
|
| 143 |
+
p016le = get_pix_fmt(b"p016le")
|
| 144 |
+
|
| 145 |
+
ndim, bits, itemsize = cython.declare(cython.int)
|
| 146 |
+
s0, s1, s2 = cython.declare(int64_t)
|
| 147 |
+
st0, st1, st2 = cython.declare(int64_t)
|
| 148 |
+
|
| 149 |
+
if sw_fmt == nv12:
|
| 150 |
+
itemsize = 1
|
| 151 |
+
bits = 8
|
| 152 |
+
if self.index == 0:
|
| 153 |
+
ndim = 2
|
| 154 |
+
s0 = self.frame.ptr.height
|
| 155 |
+
s1 = self.frame.ptr.width
|
| 156 |
+
st0 = line_size
|
| 157 |
+
st1 = 1
|
| 158 |
+
elif self.index == 1:
|
| 159 |
+
ndim = 3
|
| 160 |
+
s0 = self.frame.ptr.height // 2
|
| 161 |
+
s1 = self.frame.ptr.width // 2
|
| 162 |
+
s2 = 2
|
| 163 |
+
st0 = line_size
|
| 164 |
+
st1 = 2
|
| 165 |
+
st2 = 1
|
| 166 |
+
else:
|
| 167 |
+
raise ValueError("invalid plane index for NV12")
|
| 168 |
+
elif sw_fmt == p010le or sw_fmt == p016le:
|
| 169 |
+
itemsize = 2
|
| 170 |
+
bits = 16
|
| 171 |
+
if line_size % itemsize:
|
| 172 |
+
raise ValueError("linesize is not aligned to dtype")
|
| 173 |
+
if self.index == 0:
|
| 174 |
+
ndim = 2
|
| 175 |
+
s0 = self.frame.ptr.height
|
| 176 |
+
s1 = self.frame.ptr.width
|
| 177 |
+
st0 = line_size // itemsize
|
| 178 |
+
st1 = 1
|
| 179 |
+
elif self.index == 1:
|
| 180 |
+
ndim = 3
|
| 181 |
+
s0 = self.frame.ptr.height // 2
|
| 182 |
+
s1 = self.frame.ptr.width // 2
|
| 183 |
+
s2 = 2
|
| 184 |
+
st0 = line_size // itemsize
|
| 185 |
+
st1 = 2
|
| 186 |
+
st2 = 1
|
| 187 |
+
else:
|
| 188 |
+
raise ValueError("invalid plane index for P010/P016")
|
| 189 |
+
else:
|
| 190 |
+
raise NotImplementedError("unsupported sw_format for DLPack export")
|
| 191 |
+
|
| 192 |
+
frame_ref: cython.pointer[lib.AVFrame] = lib.av_frame_alloc()
|
| 193 |
+
if frame_ref == cython.NULL:
|
| 194 |
+
raise MemoryError("av_frame_alloc() failed")
|
| 195 |
+
err_check(lib.av_frame_ref(frame_ref, self.frame.ptr))
|
| 196 |
+
|
| 197 |
+
shape = cython.cast(
|
| 198 |
+
cython.pointer[int64_t], malloc(ndim * cython.sizeof(int64_t))
|
| 199 |
+
)
|
| 200 |
+
strides = cython.cast(
|
| 201 |
+
cython.pointer[int64_t], malloc(ndim * cython.sizeof(int64_t))
|
| 202 |
+
)
|
| 203 |
+
if shape == cython.NULL or strides == cython.NULL:
|
| 204 |
+
if shape != cython.NULL:
|
| 205 |
+
free(shape)
|
| 206 |
+
if strides != cython.NULL:
|
| 207 |
+
free(strides)
|
| 208 |
+
lib.av_frame_free(cython.address(frame_ref))
|
| 209 |
+
raise MemoryError("malloc() failed")
|
| 210 |
+
|
| 211 |
+
if ndim == 2:
|
| 212 |
+
shape[0] = s0
|
| 213 |
+
shape[1] = s1
|
| 214 |
+
strides[0] = st0
|
| 215 |
+
strides[1] = st1
|
| 216 |
+
else:
|
| 217 |
+
shape[0] = s0
|
| 218 |
+
shape[1] = s1
|
| 219 |
+
shape[2] = s2
|
| 220 |
+
strides[0] = st0
|
| 221 |
+
strides[1] = st1
|
| 222 |
+
strides[2] = st2
|
| 223 |
+
|
| 224 |
+
ctx = cython.cast(
|
| 225 |
+
cython.pointer[cython.p_void], malloc(3 * cython.sizeof(cython.p_void))
|
| 226 |
+
)
|
| 227 |
+
if ctx == cython.NULL:
|
| 228 |
+
free(shape)
|
| 229 |
+
free(strides)
|
| 230 |
+
lib.av_frame_free(cython.address(frame_ref))
|
| 231 |
+
raise MemoryError("malloc() failed")
|
| 232 |
+
|
| 233 |
+
ctx[0] = cython.cast(cython.p_void, frame_ref)
|
| 234 |
+
ctx[1] = cython.cast(cython.p_void, shape)
|
| 235 |
+
ctx[2] = cython.cast(cython.p_void, strides)
|
| 236 |
+
|
| 237 |
+
managed = cython.cast(
|
| 238 |
+
cython.pointer[DLManagedTensor], malloc(cython.sizeof(DLManagedTensor))
|
| 239 |
+
)
|
| 240 |
+
if managed == cython.NULL:
|
| 241 |
+
free(ctx)
|
| 242 |
+
free(shape)
|
| 243 |
+
free(strides)
|
| 244 |
+
lib.av_frame_free(cython.address(frame_ref))
|
| 245 |
+
raise MemoryError("malloc() failed")
|
| 246 |
+
|
| 247 |
+
managed.dl_tensor.data = cython.cast(cython.p_void, frame_ref.data[self.index])
|
| 248 |
+
managed.dl_tensor.device_type = device_type
|
| 249 |
+
managed.dl_tensor.device_id = device_id
|
| 250 |
+
managed.dl_tensor.ndim = ndim
|
| 251 |
+
managed.dl_tensor.dtype = DLDataType(code=1, bits=bits, lanes=1)
|
| 252 |
+
managed.dl_tensor.shape = shape
|
| 253 |
+
managed.dl_tensor.strides = strides
|
| 254 |
+
managed.dl_tensor.byte_offset = 0
|
| 255 |
+
managed.manager_ctx = cython.cast(cython.p_void, ctx)
|
| 256 |
+
managed.deleter = _dlpack_managed_tensor_deleter
|
| 257 |
+
|
| 258 |
+
try:
|
| 259 |
+
capsule = PyCapsule_New(
|
| 260 |
+
cython.cast(cython.p_void, managed),
|
| 261 |
+
b"dltensor",
|
| 262 |
+
_dlpack_capsule_destructor,
|
| 263 |
+
)
|
| 264 |
+
except Exception:
|
| 265 |
+
_dlpack_managed_tensor_deleter(managed)
|
| 266 |
+
raise
|
| 267 |
+
|
| 268 |
+
return capsule
|
| 269 |
+
|
| 270 |
+
|
| 271 |
+
@cython.cfunc
|
| 272 |
+
@cython.nogil
|
| 273 |
+
@cython.exceptval(check=False)
|
| 274 |
+
def _dlpack_managed_tensor_deleter(
|
| 275 |
+
managed: cython.pointer[DLManagedTensor],
|
| 276 |
+
) -> cython.void:
|
| 277 |
+
if managed == cython.NULL:
|
| 278 |
+
return
|
| 279 |
+
ctx = cython.cast(cython.pointer[cython.p_void], managed.manager_ctx)
|
| 280 |
+
if ctx != cython.NULL:
|
| 281 |
+
frame_ref = cython.cast(cython.pointer[lib.AVFrame], ctx[0])
|
| 282 |
+
shape = cython.cast(cython.pointer[int64_t], ctx[1])
|
| 283 |
+
strides = cython.cast(cython.pointer[int64_t], ctx[2])
|
| 284 |
+
|
| 285 |
+
if frame_ref != cython.NULL:
|
| 286 |
+
lib.av_frame_free(cython.address(frame_ref))
|
| 287 |
+
if shape != cython.NULL:
|
| 288 |
+
free(shape)
|
| 289 |
+
if strides != cython.NULL:
|
| 290 |
+
free(strides)
|
| 291 |
+
free(ctx)
|
| 292 |
+
|
| 293 |
+
free(managed)
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
@cython.cfunc
|
| 297 |
+
@cython.exceptval(check=False)
|
| 298 |
+
def _dlpack_capsule_destructor(capsule: object) -> cython.void:
|
| 299 |
+
if PyCapsule_IsValid(capsule, b"dltensor"):
|
| 300 |
+
managed = cython.cast(
|
| 301 |
+
cython.pointer[DLManagedTensor],
|
| 302 |
+
PyCapsule_GetPointer(capsule, b"dltensor"),
|
| 303 |
+
)
|
| 304 |
+
if managed != cython.NULL:
|
| 305 |
+
managed.deleter(managed)
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/plane.pyi
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from types import CapsuleType
|
| 2 |
+
|
| 3 |
+
from av.plane import Plane
|
| 4 |
+
|
| 5 |
+
from .frame import VideoFrame
|
| 6 |
+
|
| 7 |
+
class VideoPlane(Plane):
|
| 8 |
+
line_size: int
|
| 9 |
+
width: int
|
| 10 |
+
height: int
|
| 11 |
+
buffer_size: int
|
| 12 |
+
|
| 13 |
+
def __init__(self, frame: VideoFrame, index: int) -> None: ...
|
| 14 |
+
def __dlpack_device__(self) -> tuple[int, int]: ...
|
| 15 |
+
def __dlpack__(self, *, stream: int | None = None) -> CapsuleType: ...
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/reformatter.cpython-310-darwin.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8fbe4c18b85a6598b6c3ed80751e08d39e9bc1f8dba54b63d1ab28636ce8224b
|
| 3 |
+
size 131616
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/reformatter.pxd
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cimport libav as lib
|
| 2 |
+
|
| 3 |
+
from av.video.frame cimport VideoFrame
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
cdef extern from "libswscale/swscale.h" nogil:
|
| 7 |
+
cdef struct SwsContext:
|
| 8 |
+
unsigned flags
|
| 9 |
+
int threads
|
| 10 |
+
|
| 11 |
+
cdef int SWS_FAST_BILINEAR
|
| 12 |
+
cdef int SWS_BILINEAR
|
| 13 |
+
cdef int SWS_BICUBIC
|
| 14 |
+
cdef int SWS_X
|
| 15 |
+
cdef int SWS_POINT
|
| 16 |
+
cdef int SWS_AREA
|
| 17 |
+
cdef int SWS_BICUBLIN
|
| 18 |
+
cdef int SWS_GAUSS
|
| 19 |
+
cdef int SWS_SINC
|
| 20 |
+
cdef int SWS_LANCZOS
|
| 21 |
+
cdef int SWS_SPLINE
|
| 22 |
+
cdef int SWS_CS_ITU709
|
| 23 |
+
cdef int SWS_CS_FCC
|
| 24 |
+
cdef int SWS_CS_ITU601
|
| 25 |
+
cdef int SWS_CS_ITU624
|
| 26 |
+
cdef int SWS_CS_SMPTE170M
|
| 27 |
+
cdef int SWS_CS_SMPTE240M
|
| 28 |
+
cdef int SWS_CS_DEFAULT
|
| 29 |
+
|
| 30 |
+
cdef SwsContext *sws_alloc_context()
|
| 31 |
+
cdef void sws_free_context(SwsContext **ctx)
|
| 32 |
+
cdef int sws_scale_frame(SwsContext *c, lib.AVFrame *dst, const lib.AVFrame *src)
|
| 33 |
+
|
| 34 |
+
cdef class VideoReformatter:
|
| 35 |
+
cdef SwsContext *ptr
|
| 36 |
+
cdef _reformat(self, VideoFrame frame, int width, int height,
|
| 37 |
+
lib.AVPixelFormat format, int src_colorspace,
|
| 38 |
+
int dst_colorspace, int interpolation,
|
| 39 |
+
int src_color_range, int dst_color_range,
|
| 40 |
+
int dst_color_trc, int dst_color_primaries,
|
| 41 |
+
bint set_dst_color_trc, bint set_dst_color_primaries,
|
| 42 |
+
int threads)
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/reformatter.py
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from enum import IntEnum
|
| 2 |
+
|
| 3 |
+
import cython
|
| 4 |
+
import cython.cimports.libav as lib
|
| 5 |
+
from cython.cimports.av.error import err_check
|
| 6 |
+
from cython.cimports.av.video.format import VideoFormat, get_pix_fmt
|
| 7 |
+
from cython.cimports.av.video.frame import alloc_video_frame
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class Interpolation(IntEnum):
|
| 11 |
+
FAST_BILINEAR: "Fast bilinear" = SWS_FAST_BILINEAR
|
| 12 |
+
BILINEAR: "Bilinear" = SWS_BILINEAR
|
| 13 |
+
BICUBIC: "2-tap cubic B-spline" = SWS_BICUBIC
|
| 14 |
+
X: "Experimental" = SWS_X
|
| 15 |
+
POINT: "Nearest neighbor / point" = SWS_POINT
|
| 16 |
+
AREA: "Area averaging" = SWS_AREA
|
| 17 |
+
BICUBLIN: "Bicubic luma / Bilinear chroma" = SWS_BICUBLIN
|
| 18 |
+
GAUSS: "Gaussian approximation" = SWS_GAUSS
|
| 19 |
+
SINC: "Unwindowed Sinc" = SWS_SINC
|
| 20 |
+
LANCZOS: "3-tap sinc/sinc" = SWS_LANCZOS
|
| 21 |
+
SPLINE: "Unwindowed natural cubic spline" = SWS_SPLINE
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class Colorspace(IntEnum):
|
| 25 |
+
ITU709 = SWS_CS_ITU709
|
| 26 |
+
FCC = SWS_CS_FCC
|
| 27 |
+
ITU601 = SWS_CS_ITU601
|
| 28 |
+
ITU624 = SWS_CS_ITU624
|
| 29 |
+
SMPTE170M = SWS_CS_SMPTE170M
|
| 30 |
+
SMPTE240M = SWS_CS_SMPTE240M
|
| 31 |
+
DEFAULT = SWS_CS_DEFAULT
|
| 32 |
+
# Lowercase for b/c.
|
| 33 |
+
itu709 = SWS_CS_ITU709
|
| 34 |
+
fcc = SWS_CS_FCC
|
| 35 |
+
itu601 = SWS_CS_ITU601
|
| 36 |
+
itu624 = SWS_CS_ITU624
|
| 37 |
+
smpte170m = SWS_CS_SMPTE170M
|
| 38 |
+
smpte240m = SWS_CS_SMPTE240M
|
| 39 |
+
default = SWS_CS_DEFAULT
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class ColorRange(IntEnum):
|
| 43 |
+
UNSPECIFIED: "Unspecified" = lib.AVCOL_RANGE_UNSPECIFIED
|
| 44 |
+
MPEG: "MPEG (limited) YUV range, 219*2^(n-8)" = lib.AVCOL_RANGE_MPEG
|
| 45 |
+
JPEG: "JPEG (full) YUV range, 2^n-1" = lib.AVCOL_RANGE_JPEG
|
| 46 |
+
NB: "Not part of ABI" = lib.AVCOL_RANGE_NB
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
class ColorTrc(IntEnum):
|
| 50 |
+
"""Transfer characteristic (gamma curve) of a video frame.
|
| 51 |
+
|
| 52 |
+
Maps to FFmpeg's ``AVColorTransferCharacteristic``.
|
| 53 |
+
"""
|
| 54 |
+
|
| 55 |
+
BT709: "BT.709" = lib.AVCOL_TRC_BT709
|
| 56 |
+
UNSPECIFIED: "Unspecified" = lib.AVCOL_TRC_UNSPECIFIED
|
| 57 |
+
GAMMA22: "Gamma 2.2 (BT.470M)" = lib.AVCOL_TRC_GAMMA22
|
| 58 |
+
GAMMA28: "Gamma 2.8 (BT.470BG)" = lib.AVCOL_TRC_GAMMA28
|
| 59 |
+
SMPTE170M: "SMPTE 170M" = lib.AVCOL_TRC_SMPTE170M
|
| 60 |
+
SMPTE240M: "SMPTE 240M" = lib.AVCOL_TRC_SMPTE240M
|
| 61 |
+
LINEAR: "Linear" = lib.AVCOL_TRC_LINEAR
|
| 62 |
+
LOG: "Logarithmic (100:1 range)" = lib.AVCOL_TRC_LOG
|
| 63 |
+
LOG_SQRT: "Logarithmic (100*sqrt(10):1 range)" = lib.AVCOL_TRC_LOG_SQRT
|
| 64 |
+
IEC61966_2_4: "IEC 61966-2-4 (sRGB)" = lib.AVCOL_TRC_IEC61966_2_4
|
| 65 |
+
BT1361_ECG: "BT.1361 extended colour gamut" = lib.AVCOL_TRC_BT1361_ECG
|
| 66 |
+
IEC61966_2_1: "IEC 61966-2-1 (sYCC)" = lib.AVCOL_TRC_IEC61966_2_1
|
| 67 |
+
BT2020_10: "BT.2020 10-bit" = lib.AVCOL_TRC_BT2020_10
|
| 68 |
+
BT2020_12: "BT.2020 12-bit" = lib.AVCOL_TRC_BT2020_12
|
| 69 |
+
SMPTE2084: "SMPTE 2084 (PQ, HDR10)" = lib.AVCOL_TRC_SMPTE2084
|
| 70 |
+
SMPTE428: "SMPTE 428-1" = lib.AVCOL_TRC_SMPTE428
|
| 71 |
+
ARIB_STD_B67: "ARIB STD-B67 (HLG)" = lib.AVCOL_TRC_ARIB_STD_B67
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
class ColorPrimaries(IntEnum):
|
| 75 |
+
"""Color primaries of a video frame.
|
| 76 |
+
|
| 77 |
+
Maps to FFmpeg's ``AVColorPrimaries``.
|
| 78 |
+
"""
|
| 79 |
+
|
| 80 |
+
BT709: "BT.709 / sRGB / sYCC" = lib.AVCOL_PRI_BT709
|
| 81 |
+
UNSPECIFIED: "Unspecified" = lib.AVCOL_PRI_UNSPECIFIED
|
| 82 |
+
BT470M: "BT.470M" = lib.AVCOL_PRI_BT470M
|
| 83 |
+
BT470BG: "BT.470BG / BT.601-6 625" = lib.AVCOL_PRI_BT470BG
|
| 84 |
+
SMPTE170M: "SMPTE 170M / BT.601-6 525" = lib.AVCOL_PRI_SMPTE170M
|
| 85 |
+
SMPTE240M: "SMPTE 240M" = lib.AVCOL_PRI_SMPTE240M
|
| 86 |
+
FILM: "Generic film (Illuminant C)" = lib.AVCOL_PRI_FILM
|
| 87 |
+
BT2020: "BT.2020 / BT.2100" = lib.AVCOL_PRI_BT2020
|
| 88 |
+
SMPTE428: "SMPTE 428-1 / XYZ" = lib.AVCOL_PRI_SMPTE428
|
| 89 |
+
SMPTE431: "SMPTE 431-2 (DCI-P3)" = lib.AVCOL_PRI_SMPTE431
|
| 90 |
+
SMPTE432: "SMPTE 432-1 (Display P3)" = lib.AVCOL_PRI_SMPTE432
|
| 91 |
+
EBU3213: "EBU 3213-E / JEDEC P22" = lib.AVCOL_PRI_EBU3213
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
@cython.cfunc
|
| 95 |
+
@cython.inline
|
| 96 |
+
def _resolve_enum_value(
|
| 97 |
+
value: object, enum_class: object, default: cython.int
|
| 98 |
+
) -> cython.int:
|
| 99 |
+
# Helper function to resolve enum values from different input types.
|
| 100 |
+
if value is None:
|
| 101 |
+
return default
|
| 102 |
+
if isinstance(value, enum_class):
|
| 103 |
+
return value.value
|
| 104 |
+
if isinstance(value, int):
|
| 105 |
+
return value
|
| 106 |
+
if isinstance(value, str):
|
| 107 |
+
return enum_class[value].value
|
| 108 |
+
raise ValueError(f"Cannot convert {value} to {enum_class.__name__}")
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
@cython.cfunc
|
| 112 |
+
@cython.inline
|
| 113 |
+
def _resolve_format(format: object, default: lib.AVPixelFormat) -> lib.AVPixelFormat:
|
| 114 |
+
if format is None:
|
| 115 |
+
return default
|
| 116 |
+
if isinstance(format, VideoFormat):
|
| 117 |
+
return cython.cast(VideoFormat, format).pix_fmt
|
| 118 |
+
return get_pix_fmt(format)
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
@cython.cfunc
|
| 122 |
+
def _set_frame_colorspace(
|
| 123 |
+
frame: cython.pointer(lib.AVFrame),
|
| 124 |
+
colorspace: cython.int,
|
| 125 |
+
color_range: cython.int,
|
| 126 |
+
):
|
| 127 |
+
"""Set AVFrame colorspace/range from SWS_CS_* and AVColorRange values."""
|
| 128 |
+
if color_range != lib.AVCOL_RANGE_UNSPECIFIED:
|
| 129 |
+
frame.color_range = cython.cast(lib.AVColorRange, color_range)
|
| 130 |
+
# Mapping from SWS_CS_* (swscale colorspace) to AVColorSpace (frame metadata).
|
| 131 |
+
# Note: SWS_CS_ITU601, SWS_CS_ITU624, SWS_CS_SMPTE170M, and SWS_CS_DEFAULT all have
|
| 132 |
+
# the same value (5), so we map 5 -> AVCOL_SPC_SMPTE170M as the most common case.
|
| 133 |
+
# SWS_CS_DEFAULT is handled specially by not setting frame metadata.
|
| 134 |
+
if colorspace == SWS_CS_ITU709:
|
| 135 |
+
frame.colorspace = lib.AVCOL_SPC_BT709
|
| 136 |
+
elif colorspace == SWS_CS_FCC:
|
| 137 |
+
frame.colorspace = lib.AVCOL_SPC_FCC
|
| 138 |
+
elif colorspace == SWS_CS_ITU601:
|
| 139 |
+
frame.colorspace = lib.AVCOL_SPC_SMPTE170M
|
| 140 |
+
elif colorspace == SWS_CS_SMPTE240M:
|
| 141 |
+
frame.colorspace = lib.AVCOL_SPC_SMPTE240M
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
@cython.final
|
| 145 |
+
@cython.cclass
|
| 146 |
+
class VideoReformatter:
|
| 147 |
+
"""An object for reformatting size and pixel format of :class:`.VideoFrame`.
|
| 148 |
+
|
| 149 |
+
It is most efficient to have a reformatter object for each set of parameters
|
| 150 |
+
you will use as calling :meth:`reformat` will reconfigure the internal object.
|
| 151 |
+
|
| 152 |
+
"""
|
| 153 |
+
|
| 154 |
+
def __dealloc__(self):
|
| 155 |
+
with cython.nogil:
|
| 156 |
+
sws_free_context(cython.address(self.ptr))
|
| 157 |
+
|
| 158 |
+
def reformat(
|
| 159 |
+
self,
|
| 160 |
+
frame: VideoFrame,
|
| 161 |
+
width=None,
|
| 162 |
+
height=None,
|
| 163 |
+
format=None,
|
| 164 |
+
src_colorspace=None,
|
| 165 |
+
dst_colorspace=None,
|
| 166 |
+
interpolation=None,
|
| 167 |
+
src_color_range=None,
|
| 168 |
+
dst_color_range=None,
|
| 169 |
+
dst_color_trc=None,
|
| 170 |
+
dst_color_primaries=None,
|
| 171 |
+
threads=None,
|
| 172 |
+
):
|
| 173 |
+
"""Create a new :class:`VideoFrame` with the given width/height/format/colorspace.
|
| 174 |
+
|
| 175 |
+
Returns the same frame untouched if nothing needs to be done to it.
|
| 176 |
+
|
| 177 |
+
:param int width: New width, or ``None`` for the same width.
|
| 178 |
+
:param int height: New height, or ``None`` for the same height.
|
| 179 |
+
:param format: New format, or ``None`` for the same format.
|
| 180 |
+
:type format: :class:`.VideoFormat` or ``str``
|
| 181 |
+
:param src_colorspace: Current colorspace, or ``None`` for the frame colorspace.
|
| 182 |
+
:type src_colorspace: :class:`Colorspace` or ``str``
|
| 183 |
+
:param dst_colorspace: Desired colorspace, or ``None`` for the frame colorspace.
|
| 184 |
+
:type dst_colorspace: :class:`Colorspace` or ``str``
|
| 185 |
+
:param interpolation: The interpolation method to use, or ``None`` for ``BILINEAR``.
|
| 186 |
+
:type interpolation: :class:`Interpolation` or ``str``
|
| 187 |
+
:param src_color_range: Current color range, or ``None`` for the ``UNSPECIFIED``.
|
| 188 |
+
:type src_color_range: :class:`ColorRange` or ``str``
|
| 189 |
+
:param dst_color_range: Desired color range, or ``None`` for the ``UNSPECIFIED``.
|
| 190 |
+
:type dst_color_range: :class:`ColorRange` or ``str``
|
| 191 |
+
:param dst_color_trc: Desired transfer characteristic to tag on the output frame,
|
| 192 |
+
or ``None`` to preserve the source frame's value. This sets frame metadata only;
|
| 193 |
+
it does not perform a pixel-level transfer function conversion.
|
| 194 |
+
:type dst_color_trc: :class:`ColorTrc` or ``int``
|
| 195 |
+
:param dst_color_primaries: Desired color primaries to tag on the output frame,
|
| 196 |
+
or ``None`` to preserve the source frame's value.
|
| 197 |
+
:type dst_color_primaries: :class:`ColorPrimaries` or ``int``
|
| 198 |
+
:param int threads: How many threads to use for scaling, or ``0`` for automatic
|
| 199 |
+
selection based on the number of available CPUs. Defaults to ``0`` (auto).
|
| 200 |
+
|
| 201 |
+
"""
|
| 202 |
+
c_dst_format = _resolve_format(format, frame.format.pix_fmt)
|
| 203 |
+
c_src_colorspace = _resolve_enum_value(
|
| 204 |
+
src_colorspace, Colorspace, frame.ptr.colorspace
|
| 205 |
+
)
|
| 206 |
+
c_dst_colorspace = _resolve_enum_value(
|
| 207 |
+
dst_colorspace, Colorspace, frame.ptr.colorspace
|
| 208 |
+
)
|
| 209 |
+
c_interpolation = _resolve_enum_value(
|
| 210 |
+
interpolation, Interpolation, SWS_BILINEAR
|
| 211 |
+
)
|
| 212 |
+
c_src_color_range = _resolve_enum_value(src_color_range, ColorRange, 0)
|
| 213 |
+
c_dst_color_range = _resolve_enum_value(dst_color_range, ColorRange, 0)
|
| 214 |
+
c_dst_color_trc = _resolve_enum_value(dst_color_trc, ColorTrc, 0)
|
| 215 |
+
c_dst_color_primaries = _resolve_enum_value(
|
| 216 |
+
dst_color_primaries, ColorPrimaries, 0
|
| 217 |
+
)
|
| 218 |
+
c_threads: cython.int = threads if threads is not None else 0
|
| 219 |
+
c_width: cython.int = width if width is not None else frame.ptr.width
|
| 220 |
+
c_height: cython.int = height if height is not None else frame.ptr.height
|
| 221 |
+
|
| 222 |
+
# Track whether user explicitly specified destination metadata
|
| 223 |
+
set_dst_color_trc: cython.bint = dst_color_trc is not None
|
| 224 |
+
set_dst_color_primaries: cython.bint = dst_color_primaries is not None
|
| 225 |
+
|
| 226 |
+
return self._reformat(
|
| 227 |
+
frame,
|
| 228 |
+
c_width,
|
| 229 |
+
c_height,
|
| 230 |
+
c_dst_format,
|
| 231 |
+
c_src_colorspace,
|
| 232 |
+
c_dst_colorspace,
|
| 233 |
+
c_interpolation,
|
| 234 |
+
c_src_color_range,
|
| 235 |
+
c_dst_color_range,
|
| 236 |
+
c_dst_color_trc,
|
| 237 |
+
c_dst_color_primaries,
|
| 238 |
+
set_dst_color_trc,
|
| 239 |
+
set_dst_color_primaries,
|
| 240 |
+
c_threads,
|
| 241 |
+
)
|
| 242 |
+
|
| 243 |
+
@cython.cfunc
|
| 244 |
+
def _reformat(
|
| 245 |
+
self,
|
| 246 |
+
frame: VideoFrame,
|
| 247 |
+
width: cython.int,
|
| 248 |
+
height: cython.int,
|
| 249 |
+
dst_format: lib.AVPixelFormat,
|
| 250 |
+
src_colorspace: cython.int,
|
| 251 |
+
dst_colorspace: cython.int,
|
| 252 |
+
interpolation: cython.int,
|
| 253 |
+
src_color_range: cython.int,
|
| 254 |
+
dst_color_range: cython.int,
|
| 255 |
+
dst_color_trc: cython.int,
|
| 256 |
+
dst_color_primaries: cython.int,
|
| 257 |
+
set_dst_color_trc: cython.bint,
|
| 258 |
+
set_dst_color_primaries: cython.bint,
|
| 259 |
+
threads: cython.int,
|
| 260 |
+
):
|
| 261 |
+
if frame.ptr.format < 0:
|
| 262 |
+
raise ValueError("Frame does not have format set.")
|
| 263 |
+
|
| 264 |
+
src_format = cython.cast(lib.AVPixelFormat, frame.ptr.format)
|
| 265 |
+
|
| 266 |
+
# Shortcut!
|
| 267 |
+
if (
|
| 268 |
+
dst_format == src_format
|
| 269 |
+
and width == frame.ptr.width
|
| 270 |
+
and height == frame.ptr.height
|
| 271 |
+
and dst_colorspace == src_colorspace
|
| 272 |
+
and src_color_range == dst_color_range
|
| 273 |
+
and not set_dst_color_trc
|
| 274 |
+
and not set_dst_color_primaries
|
| 275 |
+
):
|
| 276 |
+
return frame
|
| 277 |
+
|
| 278 |
+
if frame.ptr.hw_frames_ctx:
|
| 279 |
+
frame_sw = alloc_video_frame()
|
| 280 |
+
err_check(lib.av_hwframe_transfer_data(frame_sw.ptr, frame.ptr, 0))
|
| 281 |
+
frame_sw.pts = frame.pts
|
| 282 |
+
frame_sw._init_user_attributes()
|
| 283 |
+
frame = frame_sw
|
| 284 |
+
src_format = cython.cast(lib.AVPixelFormat, frame.ptr.format)
|
| 285 |
+
|
| 286 |
+
if self.ptr == cython.NULL:
|
| 287 |
+
self.ptr = sws_alloc_context()
|
| 288 |
+
if self.ptr == cython.NULL:
|
| 289 |
+
raise MemoryError("Could not allocate SwsContext")
|
| 290 |
+
self.ptr.threads = threads
|
| 291 |
+
self.ptr.flags = cython.cast(cython.uint, interpolation)
|
| 292 |
+
|
| 293 |
+
new_frame: VideoFrame = alloc_video_frame()
|
| 294 |
+
new_frame._copy_internal_attributes(frame)
|
| 295 |
+
new_frame._init(dst_format, width, height)
|
| 296 |
+
|
| 297 |
+
# Set source frame colorspace/range so sws_scale_frame can read it
|
| 298 |
+
frame_src_colorspace: lib.AVColorSpace = frame.ptr.colorspace
|
| 299 |
+
frame_src_color_range: lib.AVColorRange = frame.ptr.color_range
|
| 300 |
+
_set_frame_colorspace(frame.ptr, src_colorspace, src_color_range)
|
| 301 |
+
_set_frame_colorspace(new_frame.ptr, dst_colorspace, dst_color_range)
|
| 302 |
+
|
| 303 |
+
with cython.nogil:
|
| 304 |
+
ret = sws_scale_frame(self.ptr, new_frame.ptr, frame.ptr)
|
| 305 |
+
|
| 306 |
+
# Restore source frame colorspace/range to avoid side effects
|
| 307 |
+
frame.ptr.colorspace = frame_src_colorspace
|
| 308 |
+
frame.ptr.color_range = frame_src_color_range
|
| 309 |
+
|
| 310 |
+
err_check(ret)
|
| 311 |
+
|
| 312 |
+
# Set metadata-only properties on the output frame if explicitly specified
|
| 313 |
+
if set_dst_color_trc:
|
| 314 |
+
new_frame.ptr.color_trc = cython.cast(
|
| 315 |
+
lib.AVColorTransferCharacteristic, dst_color_trc
|
| 316 |
+
)
|
| 317 |
+
if set_dst_color_primaries:
|
| 318 |
+
new_frame.ptr.color_primaries = cython.cast(
|
| 319 |
+
lib.AVColorPrimaries, dst_color_primaries
|
| 320 |
+
)
|
| 321 |
+
|
| 322 |
+
return new_frame
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/reformatter.pyi
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from enum import IntEnum
|
| 2 |
+
from typing import cast
|
| 3 |
+
|
| 4 |
+
from .frame import VideoFrame
|
| 5 |
+
|
| 6 |
+
class Interpolation(IntEnum):
|
| 7 |
+
FAST_BILINEAER = cast(int, ...)
|
| 8 |
+
BILINEAR = cast(int, ...)
|
| 9 |
+
BICUBIC = cast(int, ...)
|
| 10 |
+
X = cast(int, ...)
|
| 11 |
+
POINT = cast(int, ...)
|
| 12 |
+
AREA = cast(int, ...)
|
| 13 |
+
BICUBLIN = cast(int, ...)
|
| 14 |
+
GAUSS = cast(int, ...)
|
| 15 |
+
SINC = cast(int, ...)
|
| 16 |
+
LANCZOS = cast(int, ...)
|
| 17 |
+
SPLINE = cast(int, ...)
|
| 18 |
+
|
| 19 |
+
class Colorspace(IntEnum):
|
| 20 |
+
ITU709 = cast(int, ...)
|
| 21 |
+
FCC = cast(int, ...)
|
| 22 |
+
ITU601 = cast(int, ...)
|
| 23 |
+
ITU624 = cast(int, ...)
|
| 24 |
+
SMPTE170M = cast(int, ...)
|
| 25 |
+
SMPTE240M = cast(int, ...)
|
| 26 |
+
DEFAULT = cast(int, ...)
|
| 27 |
+
itu709 = cast(int, ...)
|
| 28 |
+
fcc = cast(int, ...)
|
| 29 |
+
itu601 = cast(int, ...)
|
| 30 |
+
itu624 = cast(int, ...)
|
| 31 |
+
smpte170m = cast(int, ...)
|
| 32 |
+
smpte240m = cast(int, ...)
|
| 33 |
+
default = cast(int, ...)
|
| 34 |
+
|
| 35 |
+
class ColorRange(IntEnum):
|
| 36 |
+
UNSPECIFIED = 0
|
| 37 |
+
MPEG = 1
|
| 38 |
+
JPEG = 2
|
| 39 |
+
NB = 3
|
| 40 |
+
|
| 41 |
+
class ColorTrc(IntEnum):
|
| 42 |
+
BT709 = cast(int, ...)
|
| 43 |
+
UNSPECIFIED = cast(int, ...)
|
| 44 |
+
GAMMA22 = cast(int, ...)
|
| 45 |
+
GAMMA28 = cast(int, ...)
|
| 46 |
+
SMPTE170M = cast(int, ...)
|
| 47 |
+
SMPTE240M = cast(int, ...)
|
| 48 |
+
LINEAR = cast(int, ...)
|
| 49 |
+
LOG = cast(int, ...)
|
| 50 |
+
LOG_SQRT = cast(int, ...)
|
| 51 |
+
IEC61966_2_4 = cast(int, ...)
|
| 52 |
+
BT1361_ECG = cast(int, ...)
|
| 53 |
+
IEC61966_2_1 = cast(int, ...)
|
| 54 |
+
BT2020_10 = cast(int, ...)
|
| 55 |
+
BT2020_12 = cast(int, ...)
|
| 56 |
+
SMPTE2084 = cast(int, ...)
|
| 57 |
+
SMPTE428 = cast(int, ...)
|
| 58 |
+
ARIB_STD_B67 = cast(int, ...)
|
| 59 |
+
|
| 60 |
+
class ColorPrimaries(IntEnum):
|
| 61 |
+
BT709 = cast(int, ...)
|
| 62 |
+
UNSPECIFIED = cast(int, ...)
|
| 63 |
+
BT470M = cast(int, ...)
|
| 64 |
+
BT470BG = cast(int, ...)
|
| 65 |
+
SMPTE170M = cast(int, ...)
|
| 66 |
+
SMPTE240M = cast(int, ...)
|
| 67 |
+
FILM = cast(int, ...)
|
| 68 |
+
BT2020 = cast(int, ...)
|
| 69 |
+
SMPTE428 = cast(int, ...)
|
| 70 |
+
SMPTE431 = cast(int, ...)
|
| 71 |
+
SMPTE432 = cast(int, ...)
|
| 72 |
+
EBU3213 = cast(int, ...)
|
| 73 |
+
|
| 74 |
+
class VideoReformatter:
|
| 75 |
+
def reformat(
|
| 76 |
+
self,
|
| 77 |
+
frame: VideoFrame,
|
| 78 |
+
width: int | None = None,
|
| 79 |
+
height: int | None = None,
|
| 80 |
+
format: str | None = None,
|
| 81 |
+
src_colorspace: int | None = None,
|
| 82 |
+
dst_colorspace: int | None = None,
|
| 83 |
+
interpolation: int | str | None = None,
|
| 84 |
+
src_color_range: int | str | None = None,
|
| 85 |
+
dst_color_range: int | str | None = None,
|
| 86 |
+
dst_color_trc: int | ColorTrc | None = None,
|
| 87 |
+
dst_color_primaries: int | ColorPrimaries | None = None,
|
| 88 |
+
threads: int | None = None,
|
| 89 |
+
) -> VideoFrame: ...
|
.venvs/kimodo/lib/python3.10/site-packages/av/video/stream.cpython-310-darwin.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:197fa08880a7f5861476cf1e1699ce461cbf87abc80796be695158e1ad00eb8a
|
| 3 |
+
size 135440
|