-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathContentGenerator.py
124 lines (94 loc) · 3.89 KB
/
ContentGenerator.py
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
"""
PyPPSPP, a Python3 implementation of Peer-to-Peer Streaming Peer Protocol
Copyright (C) 2016,2017 J. Poderys, Technical University of Denmark
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
"""
Generate content based on frame lengths given in CSV files.
"""
import asyncio
import csv
class ContentGenerator(object):
"""Create VP80 packets (talking head)"""
def __init__(self):
"""Initialize the generator"""
self._loop = asyncio.get_event_loop()
self._video_samples = []
self._audio_samples = []
self._init_samples()
self._gen_handle = None
self._fps = 10
self._next_key = 0
self._gen_callbacks = []
def add_on_generated_callback(self, callback):
"""Add callback that will be called when
content is geenrated by the generator"""
self._gen_callbacks.append(callback)
def remove_on_generated_callback(self, callback):
"""Remove given callback from a list of
callback that will be called after content
is generated"""
self._gen_callbacks.remove(callback)
def _call_on_generated(self, data):
"""Call all callbacks with generated data"""
for cb in self._gen_callbacks:
cb(data)
def start_generating(self):
"""Start the generator"""
# Raise if already running
if self._gen_handle != None:
raise Exception
# Send next and start scheduling
self._gen_next()
def stop_generating(self):
"""Stop and reset the generator"""
self._gen_handle.cancel()
self._gen_handle = None
def _gen_next(self):
"""Generate and schedule next output"""
# Wrap
if self._next_key == min([len(self._audio_samples), len(self._video_samples)]):
self._next_key = 0
# Generate data
avdata = self._get_next_avdata(self._next_key)
# Send av_data
self._call_on_generated(avdata)
# Schedule next generation
self._next_key += 1
self._gen_handle = self._loop.call_later(1 / self._fps, self._gen_next)
def _get_next_avdata(self, sameple_id):
"""Get next AV data piece"""
# Get Sample
video_sample = self._video_samples[sameple_id]
audio_sample = self._audio_samples[sameple_id]
# Save as object
av_data = {}
av_data['id'] = sameple_id # seq num
int_k = int(video_sample['key']) # Size of key frame
int_n = int(video_sample['non-key']) # Size of non-key frame
if int_n == 0:
# Key frame has size -> key-frame
av_data['vk'] = 1 # key-frame -> 1
av_data['vd'] = int_k * bytes([192]) # video data
else:
av_data['vk'] = 0 # key-frame -> 1
av_data['vd'] = int_n * bytes([192]) # video data
av_data['ad'] = int(audio_sample['size']) * bytes([192]) # audio data
av_data['in'] = 'Quick Brow Fox!'
return av_data
def _init_samples(self):
with open('CSV_Audio_Frames.csv', 'r') as audio_csv:
ar = csv.DictReader(audio_csv)
self._audio_samples = list(ar)
with open('CSV_Video_Frames.csv', 'r') as video_csv:
vr = csv.DictReader(video_csv)
self._video_samples = list(vr)