forked from PyAV-Org/PyAV
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmulti_capture.py
More file actions
134 lines (99 loc) · 3.34 KB
/
Copy pathmulti_capture.py
File metadata and controls
134 lines (99 loc) · 3.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import argparse
import ctypes
import os
import sys
import pprint
import time
import logging
logging.basicConfig()
import av
from av import VideoFrame
from qtproxy import Q
from glproxy import gl
WIDTH = 960
HEIGHT = 540
class PlayerGLWidget(Q.GLWidget):
def initializeGL(self):
print 'initialize GL'
gl.clearColor(0, 0, 0, 0)
gl.enable(gl.TEXTURE_2D)
self.textures = [gl.genTextures(1) for _ in range(2)]
for tid in self.textures:
gl.bindTexture(gl.TEXTURE_2D, tid)
gl.texParameter(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.texParameter(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
def setFrame(self, index, frame):
width = 960
height = 540
frame = frame.reformat(width, height, 'rgb24')
ptr = ctypes.c_void_p(frame.planes[0].ptr)
gl.bindTexture(gl.TEXTURE_2D, self.textures[index])
gl.texImage2D(gl.TEXTURE_2D, 0, 3, width, height, 0, gl.RGB, gl.UNSIGNED_BYTE, ptr)
def resizeGL(self, w, h):
print 'resize to', w, h
gl.viewport(0, 0, w, h)
# gl.matrixMode(gl.PROJECTION)
# gl.loadIdentity()
# gl.ortho(0, w, 0, h, -10, 10)
# gl.matrixMode(gl.MODELVIEW)
def paintGL(self):
# print 'paint!'
gl.clear(gl.COLOR_BUFFER_BIT)
gl.bindTexture(gl.TEXTURE_2D, self.textures[0])
with gl.begin('polygon'):
gl.texCoord(0, 0); gl.vertex(-1, 1)
gl.texCoord(1, 0); gl.vertex( 0, 1)
gl.texCoord(1, 1); gl.vertex( 0, -1)
gl.texCoord(0, 1); gl.vertex(-1, -1)
gl.bindTexture(gl.TEXTURE_2D, self.textures[1])
with gl.begin('polygon'):
gl.texCoord(0, 0); gl.vertex( 0, 1)
gl.texCoord(1, 0); gl.vertex( 1, 1)
gl.texCoord(1, 1); gl.vertex( 1, -1)
gl.texCoord(0, 1); gl.vertex( 0, -1)
app = Q.Application([])
glwidget = PlayerGLWidget()
glwidget.setFixedWidth(WIDTH)
glwidget.setFixedHeight(HEIGHT / 2)
glwidget.show()
glwidget.raise_()
gl.readBuffer(gl.FRONT) # Read from front.
out_frame = VideoFrame(WIDTH, HEIGHT, 'rgb24')
out_buffer = ctypes.c_void_p(out_frame.planes[0].ptr)
out_file = av.open('output.mkv', 'w')
out_stream = out_file.add_stream('mpeg4', 24)
out_stream.time_base = '1/1000'
out_frame.time_base = out_stream.time_base
options = {
'pixel_format': '0rgb',
#'framerate': '30', # Does nothing, really.
#'video_size': '960x540',
'capture_cursor': '1',
'capture_mouse_clicks': '1',
}
containers = [
av.open('0', format='avfoundation', options=options.copy()),
av.open('1', format='avfoundation', options=options.copy()),
]
frame_times = []
start_time = time.time()
while True:
for ci, c in enumerate(containers):
for frame in c.decode():
if isinstance(frame, VideoFrame):
glwidget.setFrame(ci, frame)
break
glwidget.updateGL()
# Reads into our frame object.
gl.readPixels(0, 0, WIDTH, HEIGHT, gl.RGB, gl.UNSIGNED_BYTE, out_buffer)
now = time.time()
out_frame.pts = 1000 * (now - start_time)
out_packet = out_stream.encode(out_frame)
if out_packet:
out_file.mux(out_packet)
then = None
while len(frame_times) > 5:
then = frame_times.pop(0)
frame_times.append(now)
if then:
print 5 / (now - then)