My favorites | Sign in
Project Home Downloads Wiki Source
Checkout   Browse   Changes    
 
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# This code is designed soley for the purposes of demonstrating the tools
# for timeshifting.
#
# Copyright 2010 British Broadcasting Corporation and Kamaelia Contributors(1)
#
# (1) Kamaelia Contributors are listed in the AUTHORS file and at
# http://www.kamaelia.org/AUTHORS - please extend this file,
# not this notice.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

from Kamaelia.Device.DVB.Core import DVB_Demuxer,DVB_Multiplex
from Kamaelia.Chassis.Graphline import Graphline
from Kamaelia.File.Writing import SimpleFileWriter
from Kamaelia.File.UnixProcess import UnixProcess
import Axon
import struct
import dvb3

from Axon.Ipc import shutdownMicroprocess, producerFinished
from Kamaelia.Device.DVB.EIT import PSIPacketReconstructor, EITPacketParser, NowNextServiceFilter, NowNextChanges, TimeAndDatePacketParser
from Kamaelia.Chassis.Carousel import Carousel
from Kamaelia.Chassis.Pipeline import Pipeline
import time, os

class EITDemux(Axon.Component.component):
Outboxes = {"outbox":"",
"signal":"",
"_eit_" :"",
}
def main(self):
while 1:
yield 1
while self.dataReady("inbox"):
packet = self.recv("inbox")
pid = struct.unpack(">H", packet[1: 3])[0] & 0x1fff
if pid != 18:
self.send( packet, "outbox")
else:
self.send( packet, "_eit_")
else:
self.pause()

class ProgrammeTranscoder(Axon.Component.component):
Inboxes = { "inbox" : "TS packets containing audio and video",
"control" : "the usual",
"_transcodingcomplete" : "signal from the transcoder",
}
Outboxes = { "outbox" : "",
"_stop" : "stop the transcoder",
"signal" : "the usual",
}
def __init__(self, eitdata, mencoder_options, dir_prefix):
super(ProgrammeTranscoder,self).__init__()
self.eitdata = eitdata
self.mencoder_options =mencoder_options
self.dir_prefix = dir_prefix

def main(self):
# first, generate unique filename
uid = str(time.time())

encodingfile = "/data/encoding"+self.dir_prefix+"/"+uid+".avi"
waitingEIT = "/data/encoding"+self.dir_prefix+"/"+uid+".eit"

finishedfile = "/data/finished"+self.dir_prefix+"/"+uid+".avi"
finishedEIT = "/data/finished"+self.dir_prefix+"/"+uid+".eit"

print uid,"Starting transcoding into: "+encodingfile
transcoder = UnixProcess("mencoder -o "+encodingfile+" "+self.mencoder_options)
print uid,"Transcoder pipethough =",transcoder.name

data_linkage = self.link( (self,"inbox"), (transcoder,"inbox"), passthrough=1 )
ctrl_linkage = self.link( (self,"_stop"), (transcoder,"control"))
done_linkage = self.link( (transcoder,"signal"), (self,"_transcodingcomplete") )

# transcoder_logger = SimpleFileWriter(uid+".log").activate()
# log_linkage = self.link( (transcoder,"outbox"), (transcoder_logger,"inbox"))

transcoder.activate()

# write the eit data to a file
eitF = open(waitingEIT,"wb")
eitF.write( str(self.eitdata) )
eitF.close()
eitF = None

while not self.dataReady("control"): # wait until shutdown
self.pause()
yield 1

print uid,"shutdown received"
while self.dataReady("control"):
self.recv("control") # flush out shutdown messages

# tell transcoder to stop
print uid,"Transcoding must now stop..."
self.send(producerFinished(), "_stop")

print uid,"waiting for transcoder to finish"
while not self.dataReady("_transcodingcomplete"):
self.pause()
yield 1
print uid,"transcoder has finished"
while self.dataReady("_transcodingcomplete"):
self.recv("_transcodingcomplete")

# move the transcoded file and eit data to final destination
print uid,"Moving finished files"
os.rename(encodingfile, finishedfile)
os.rename(waitingEIT, finishedEIT)

print uid,"Unlinking transcoder"
self.unlink(data_linkage)
self.unlink(ctrl_linkage)
self.unlink(done_linkage)
# self.unlink(log_linkage)

print uid,"Sending done signal"
self.send(producerFinished(), "signal")

# # HACK HACK HACK
# # force this program to terminate
# # and clean up any extraneous EIT data
# cruft = [file for file in os.listdir("/data/encoding"+self.dir_prefix+"/") if file[-4:]==".eit"]
# for file in cruft:
# os.remove("/data/encoding"+self.dir_prefix+"/"+file)
# raise "STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP!!!!"


def EITParsing(*service_ids):
return Pipeline(
PSIPacketReconstructor(),
EITPacketParser(),
NowNextServiceFilter(*service_ids),
NowNextChanges(),
)


def ChannelTranscoder(service_id, mencoder_options, dir_prefix): # BBC ONE
def transcoder_factory(eit):
print "transcoder factory called with eit:\n"+str(eit)+"\n"
return ProgrammeTranscoder(eit, mencoder_options, dir_prefix)

return Graphline(
PROG_CODER = Carousel( transcoder_factory ),
EIT_PARSE = EITParsing(service_id),
DEMUX = EITDemux(),
linkages = {
("self","inbox") : ("DEMUX","inbox"),
("DEMUX","outbox") : ("PROG_CODER","inbox"), # forward video and audio packets to coder
("DEMUX","_eit_") : ("EIT_PARSE", "inbox"), # forward eit packets to eit parsing
("EIT_PARSE", "outbox") : ("PROG_CODER", "next"), # eit programme junction events cause new transcoding to start
}
)

location = "manchester"

if location == "london": # Crystal Palace
freq = 505.833330 # 529.833330 # 505.833330
feparams = {
"inversion" : dvb3.frontend.INVERSION_AUTO,
"constellation" : dvb3.frontend.QAM_16,
"code_rate_HP" : dvb3.frontend.FEC_3_4,
"code_rate_LP" : dvb3.frontend.FEC_3_4,
}
elif location == "manchester": # WinterHill
freq = 754.166670
feparams = {
"inversion" : dvb3.frontend.INVERSION_AUTO,
"constellation" : dvb3.frontend.QAM_16,
"code_rate_HP" : dvb3.frontend.FEC_3_4,
"code_rate_LP" : dvb3.frontend.FEC_3_4,
}

from Kamaelia.File.ReadFileAdaptor import ReadFileAdaptor
from Kamaelia.File.Reading import RateControlledFileReader
from Kamaelia.Util.Console import ConsoleEchoer

params={}
params["LO"] = {
"mencoder_options" : " -ovc lavc -oac mp3lame -ffourcc DX50 -lavcopts acodec=mp3:vbitrate=200:abitrate=128 -vf scale=320:-2 -",
"dir_prefix" : "200",
}
params["HI"] = {
"mencoder_options" : " -ovc lavc -oac mp3lame -ffourcc DX50 -lavcopts acodec=mp3:vbitrate=512:abitrate=128 -vf scale=640:-2 -",
"dir_prefix" : "512"
}

pids = { "BBC ONE" : [600,601],
"BBC TWO" : [610,611],
"CBEEBIES": [201,401],
"CBBC" : [620,621],
"EIT" : [18],
}

service_ids = { "BBC ONE": 4164,
"BBC TWO": 4228,
"CBEEBIES":16960,
"CBBC":4671,
}

print "-----STARTING MACRO----- time =",time.time()

def repeatingFile():
def rfa_factory(_):
return RateControlledFileReader("junction.ts",readmode="bytes",rate=18000000/8,chunksize=2048)
return Graphline(CAROUSEL=Carousel(rfa_factory, make1stRequest=True),
linkages = { ("CAROUSEL","requestNext") : ("CAROUSEL","next"),
("CAROUSEL","outbox") : ("self", "outbox"),
("CAROUSEL","signal") : ("self", "signal"),
},
)

Graphline(
SOURCE=DVB_Multiplex(freq, pids["BBC TWO"]+pids["EIT"], feparams), # BBC Channels + EIT data
DEMUX=DVB_Demuxer({
610: ["BBCTWO"],
611: ["BBCTWO"],
18: ["BBCTWO"], # BBCONE","BBCONE_2","BBCTWO","BBCTWO_2", "CBEEBIES"
}),
BBCTWO_HI = ChannelTranscoder(service_ids["BBC TWO"], **params["HI"]),
linkages={
("SOURCE", "outbox"):("DEMUX","inbox"),
("DEMUX", "BBCTWO"): ("BBCTWO_HI", "inbox"),
}
).run()

# RELEASE: MH, MPS

Change log

r6563 by sparks.m on Jul 24, 2010   Diff
Change license to Apache 2
Go to: 
Sign in to write a code review

Older revisions

r4022 by ms_ on May 21, 2008   Diff
Merge of branch:
private_MH_20080518_DvbFixes

Michael
r2257 by ms_ on Aug 23, 2006   Diff
All examples changed to use
ReadFileAdaptor from the correct
location
Specifically:
   Kamaelia.File.ReadFileAdaptor
...
r2253 by ms_ on Aug 22, 2006   Diff
Updated examples to use Pipeline
rather than pipeline


Michael
All revisions of this file

File info

Size: 9073 bytes, 243 lines

File properties

svn:eol-style
native
svn:executable
*
svn:keywords
Author Date Id Revision
Powered by Google Project Hosting