yta-video-opengl 0.0.5__py3-none-any.whl → 0.0.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yta_video_opengl/classes.py +1275 -0
- yta_video_opengl/{reader.py → reader/__init__.py} +118 -16
- yta_video_opengl/reader/cache.py +155 -0
- yta_video_opengl/tests.py +694 -55
- yta_video_opengl/utils.py +100 -0
- yta_video_opengl/writer.py +40 -2
- {yta_video_opengl-0.0.5.dist-info → yta_video_opengl-0.0.7.dist-info}/METADATA +1 -1
- yta_video_opengl-0.0.7.dist-info/RECORD +11 -0
- yta_video_opengl-0.0.5.dist-info/RECORD +0 -8
- {yta_video_opengl-0.0.5.dist-info → yta_video_opengl-0.0.7.dist-info}/LICENSE +0 -0
- {yta_video_opengl-0.0.5.dist-info → yta_video_opengl-0.0.7.dist-info}/WHEEL +0 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
from yta_validation import PythonValidator
|
2
|
+
from typing import Union
|
3
|
+
|
4
|
+
import av
|
5
|
+
import numpy as np
|
6
|
+
import moderngl
|
7
|
+
|
8
|
+
|
9
|
+
def frame_to_texture(
|
10
|
+
frame: Union['VideoFrame', 'np.ndarray'],
|
11
|
+
context: moderngl.Context,
|
12
|
+
numpy_format: str = 'rgb24'
|
13
|
+
):
|
14
|
+
"""
|
15
|
+
Transform the given 'frame' to an opengl
|
16
|
+
texture. The frame can be a VideoFrame
|
17
|
+
instance (from pyav library) or a numpy
|
18
|
+
array.
|
19
|
+
"""
|
20
|
+
# To numpy RGB inverted for opengl
|
21
|
+
frame: np.ndarray = (
|
22
|
+
np.flipud(frame.to_ndarray(format = numpy_format))
|
23
|
+
if PythonValidator.is_instance_of(frame, 'VideoFrame') else
|
24
|
+
np.flipud(frame)
|
25
|
+
)
|
26
|
+
|
27
|
+
return context.texture(
|
28
|
+
size = (frame.shape[1], frame.shape[0]),
|
29
|
+
components = frame.shape[2],
|
30
|
+
data = frame.tobytes()
|
31
|
+
)
|
32
|
+
|
33
|
+
# TODO: I should make different methods to
|
34
|
+
# obtain a VideoFrame or a numpy array frame
|
35
|
+
def texture_to_frame(
|
36
|
+
texture: moderngl.Texture
|
37
|
+
) -> 'VideoFrame':
|
38
|
+
"""
|
39
|
+
Transform an opengl texture into a pyav
|
40
|
+
VideoFrame instance.
|
41
|
+
"""
|
42
|
+
# RGBA8
|
43
|
+
data = texture.read(alignment = 1)
|
44
|
+
frame = np.frombuffer(data, dtype = np.uint8).reshape((texture.size[1], texture.size[0], 4))
|
45
|
+
# Opengl gives it with the y inverted
|
46
|
+
frame = np.flipud(frame)
|
47
|
+
# TODO: This can be returned as a numpy frame
|
48
|
+
|
49
|
+
# This is if we need an 'av' VideoFrame (to
|
50
|
+
# export through the demuxer, for example)
|
51
|
+
frame = av.VideoFrame.from_ndarray(frame, format = 'rgba')
|
52
|
+
# TODO: Make this customizable
|
53
|
+
frame = frame.reformat(format = 'yuv420p')
|
54
|
+
|
55
|
+
return frame
|
56
|
+
|
57
|
+
def get_fullscreen_quad_vao(
|
58
|
+
context: moderngl.Context,
|
59
|
+
program: moderngl.Program
|
60
|
+
) -> moderngl.VertexArray:
|
61
|
+
"""
|
62
|
+
Get the vertex array object of a quad, by
|
63
|
+
using the vertices, the indexes, the vbo,
|
64
|
+
the ibo and the vao content.
|
65
|
+
"""
|
66
|
+
# Quad vertices in NDC (-1..1) with texture
|
67
|
+
# coords (0..1)
|
68
|
+
"""
|
69
|
+
The UV coordinates to build the quad we
|
70
|
+
will use to represent the frame by
|
71
|
+
applying it as a texture.
|
72
|
+
"""
|
73
|
+
vertices = np.array([
|
74
|
+
# pos.x, pos.y, tex.u, tex.v
|
75
|
+
-1.0, -1.0, 0.0, 0.0, # vertex 0 - bottom left
|
76
|
+
1.0, -1.0, 1.0, 0.0, # vertex 1 - bottom right
|
77
|
+
-1.0, 1.0, 0.0, 1.0, # vertex 2 - top left
|
78
|
+
1.0, 1.0, 1.0, 1.0, # vertex 3 - top right
|
79
|
+
], dtype = 'f4')
|
80
|
+
|
81
|
+
"""
|
82
|
+
The indexes of the vertices (see 'vertices'
|
83
|
+
property) to build the 2 opengl triangles
|
84
|
+
that will represent the quad we need for
|
85
|
+
the frame.
|
86
|
+
"""
|
87
|
+
indices = np.array([
|
88
|
+
0, 1, 2,
|
89
|
+
2, 1, 3
|
90
|
+
], dtype = 'i4')
|
91
|
+
|
92
|
+
vbo = context.buffer(vertices.tobytes())
|
93
|
+
ibo = context.buffer(indices.tobytes())
|
94
|
+
|
95
|
+
vao_content = [
|
96
|
+
# 2 floats position, 2 floats texcoords
|
97
|
+
(vbo, '2f 2f', 'in_vert', 'in_texcoord'),
|
98
|
+
]
|
99
|
+
|
100
|
+
return context.vertex_array(program, vao_content, ibo)
|
yta_video_opengl/writer.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
from yta_validation import PythonValidator
|
2
1
|
from yta_validation.parameter import ParameterValidator
|
3
2
|
from av.stream import Stream
|
4
3
|
from av.packet import Packet
|
@@ -70,7 +69,22 @@ class VideoWriter:
|
|
70
69
|
|
71
70
|
return self
|
72
71
|
|
73
|
-
|
72
|
+
def set_video_stream_from_template(
|
73
|
+
self,
|
74
|
+
template: Stream
|
75
|
+
) -> 'VideoWriter':
|
76
|
+
"""
|
77
|
+
Set the video stream, that will overwrite any other
|
78
|
+
previous video stream set.
|
79
|
+
|
80
|
+
You can pass the video stream as it was
|
81
|
+
obtained from the reader.
|
82
|
+
"""
|
83
|
+
self.video_stream: VideoStream = self.output.add_stream_from_template(
|
84
|
+
template
|
85
|
+
)
|
86
|
+
|
87
|
+
return self
|
74
88
|
|
75
89
|
def set_audio_stream(
|
76
90
|
self,
|
@@ -156,6 +170,30 @@ class VideoWriter:
|
|
156
170
|
ParameterValidator.validate_mandatory_instance_of('packet', packet, Packet)
|
157
171
|
|
158
172
|
if packet.size > 0:
|
173
|
+
try:
|
174
|
+
self.output.mux(packet)
|
175
|
+
except Exception as e:
|
176
|
+
# TODO: What strategy should we adopt with
|
177
|
+
# the packets that cannot be handled
|
178
|
+
# properly (?)
|
179
|
+
print(packet)
|
180
|
+
pass
|
181
|
+
|
182
|
+
return self
|
183
|
+
|
184
|
+
# TODO: This below is to test fails
|
185
|
+
if (
|
186
|
+
packet.size > 0 and
|
187
|
+
# This is a new special case
|
188
|
+
packet.dts % 1024 == 0 and
|
189
|
+
packet.dts > 0
|
190
|
+
):
|
191
|
+
# av.Packet of #0, dts=-2, pts=0; 1225 bytes at 0x1ef2d8e0680>
|
192
|
+
# av.Packet of #0, dts=0, pts=2; 110 bytes at 0x1e1feb8c6d0>
|
193
|
+
# av.Packet of #0, dts=1, pts=1; 182 bytes at 0x153f6b3b400>
|
194
|
+
# are failing
|
195
|
+
print(packet)
|
196
|
+
print(packet.stream.type)
|
159
197
|
self.output.mux(packet)
|
160
198
|
|
161
199
|
return self
|
@@ -0,0 +1,11 @@
|
|
1
|
+
yta_video_opengl/__init__.py,sha256=ycAx_XYMVDfkuObSvtW6irQ0Wo-fgxEz3fjIRMe8PpY,205
|
2
|
+
yta_video_opengl/classes.py,sha256=VUw73kfz8kxYLE0x0LxNHqFekF3CklcyofCNN-z57Lg,37706
|
3
|
+
yta_video_opengl/reader/__init__.py,sha256=npLoSfHPCbwAkmrVjOZn-7a9OHXZ6mPKxZj7BiDaFX4,12638
|
4
|
+
yta_video_opengl/reader/cache.py,sha256=Y3lQrirQJz7zFeiJQeJnkzyghYeMahkpKzsouzB90VI,4421
|
5
|
+
yta_video_opengl/tests.py,sha256=D8Rw0e2J0AbIA1IhinTope-z5tZdW5FQFFasBHBQvm8,25765
|
6
|
+
yta_video_opengl/utils.py,sha256=YEsvtZLingxU49-PSPZeESLMz7oMvlQxMBIe_vnyGJc,2939
|
7
|
+
yta_video_opengl/writer.py,sha256=fFkAz3r26wud2lJqKiP0EW24Ep6cZ1uTrQkc0tt8RsE,7562
|
8
|
+
yta_video_opengl-0.0.7.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
|
9
|
+
yta_video_opengl-0.0.7.dist-info/METADATA,sha256=Ga9Avta2a0bHcUwUZ_OvfYTN8rO11O2CtbmFt4btYBk,670
|
10
|
+
yta_video_opengl-0.0.7.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
11
|
+
yta_video_opengl-0.0.7.dist-info/RECORD,,
|
@@ -1,8 +0,0 @@
|
|
1
|
-
yta_video_opengl/__init__.py,sha256=ycAx_XYMVDfkuObSvtW6irQ0Wo-fgxEz3fjIRMe8PpY,205
|
2
|
-
yta_video_opengl/reader.py,sha256=ROjx5jSi_M2KWcp1Fksi4y-apb1IvItPhpLF32u5DpU,9869
|
3
|
-
yta_video_opengl/tests.py,sha256=7a_n-xW2xBVYR1sj-IuGm8c8F6It2LHZ8GqCH_SeY-U,6081
|
4
|
-
yta_video_opengl/writer.py,sha256=9i1SSaOxWF-uBTWvpToP8juIqSWhbIh_Nfyi69adWIw,6356
|
5
|
-
yta_video_opengl-0.0.5.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
|
6
|
-
yta_video_opengl-0.0.5.dist-info/METADATA,sha256=hH7uBbRBkNQ44kIEi1oKB_s3fGLtwcnd0rdZB_M3bVw,670
|
7
|
-
yta_video_opengl-0.0.5.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
8
|
-
yta_video_opengl-0.0.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|