~ubuntu-branches/ubuntu/karmic/tovid/karmic

« back to all changes in this revision

Viewing changes to libtovid/playtime.py

  • Committer: Bazaar Package Importer
  • Author(s): Matvey Kozhev
  • Date: 2008-01-24 22:04:40 UTC
  • Revision ID: james.westby@ubuntu.com-20080124220440-x7cheljduf1rdgnq
Tags: upstream-0.31
ImportĀ upstreamĀ versionĀ 0.31

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# (no interpreter)
 
2
# -*- coding: utf8 -*-
 
3
 
4
# Copyright 2007 Joe Friedrichsen <pengi.films@gmail.com>
 
5
 
6
# This file is part of tovid.
 
7
 
 
8
"""Relate a video's bitrate, size, and play time
 
9
 
 
10
A video file (a/v stream) has three related characteristics:
 
11
  1. Play length
 
12
  2. Final output size
 
13
  3. Encoded (average) bitrate
 
14
These are related by their units: bitrate = size / length. This module
 
15
provides ways to calculate these values. 
 
16
 
 
17
You can predict/calculate any one of these characteristics given the
 
18
other two. By default, a new AVstream object assumes you want to find
 
19
the average bitrate from a known play length and final size:
 
20
 
 
21
    >>> avs = playtime.AVstream()
 
22
    >>> avs.play_length
 
23
    120.0
 
24
    >>> avs.final_size
 
25
    4400.0
 
26
    >>> avs.bitrate.kbps
 
27
    5126.3715555555555
 
28
    >>> avs.bitrate.MiBpm
 
29
    36.666666666666664
 
30
    >>> avs.bitrate.GiBph
 
31
    2.1484375
 
32
 
 
33
Usually when putting video on a disc, the final output size is well
 
34
defined and non-changing. By default, AVstream fixes this characteristic so
 
35
that you can see how the bitrate changes for different amounts of time on 
 
36
that disc:
 
37
 
 
38
    >>> avs.set_play_length(180)
 
39
    >>> avs.bitrate.kbps
 
40
    3417.5810370370368
 
41
 
 
42
However, if you know the video is a certain length, you can fix that instead
 
43
and find how bitrates change according to different output sizes:
 
44
 
 
45
    >>> avs.set_fixed_param('LENGTH')
 
46
    >>> avs.set_final_size(2000)
 
47
    >>> avs.bitrate.kbps
 
48
    1537.9114666666667
 
49
 
 
50
Finally, you're not limited to finding bitrates. You can fix the bitrate and
 
51
see how output size and play length are related:
 
52
 
 
53
    >>> avs.set_bitrate(1152, 'kbps')
 
54
    >>> avs.set_fixed_param('RATE')
 
55
    >>> avs.set_final_size(700)
 
56
    >>> avs.play_length
 
57
    84.954074074074072
 
58
    >>> avs.set_play_length(120)
 
59
    >>> avs.final_size
 
60
    988.76953125
 
61
 
 
62
"""
 
63
 
 
64
class AVstream:
 
65
    """Video file bitrate/size/length calculator object
 
66
    
 
67
    An AVstream object lets you calculate a video's bitrate, final size, or
 
68
    play length given the other two. Usually, you want to find the bitrate,
 
69
    and this is what AVstream does by default.
 
70
    
 
71
    Once instantiated, the bitrate can be accessed in three different units:
 
72
        AVstream.bitrate.kbps -- kilobits per second (conventional)
 
73
        AVstream.bitrate.MiBpm -- Mibibytes per minute
 
74
        AVstream.bitrate.GiBph -- Gibibytes per hour
 
75
    
 
76
    There are four attributes:
 
77
        play_length -- the length of the video in minutes
 
78
        final_size -- the size of the video in MiB
 
79
        bitrate -- the bitrate of the video
 
80
        fixed_param -- the fixed characteristic
 
81
    
 
82
    Each of these attributes have a 'set_NAME' method that should be used
 
83
    to make changes so that the other attributes are updated automatically.
 
84
    
 
85
    """
 
86
    def __init__(self, play_length=120.0, final_size=4400.0):
 
87
        """Create a new AVstream object
 
88
        
 
89
        Keyword args:
 
90
        [opt] play_length -- the length in minutes (default = 120.0)
 
91
        [opt] final_size -- the final size in MiB (default = 4400.0)
 
92
        
 
93
        """
 
94
        self.play_length = play_length
 
95
        self.final_size = final_size
 
96
        self.bitrate = Bitrate( (final_size/play_length), 'MiBpm')
 
97
        self.fixed_param = "SIZE"
 
98
 
 
99
    def set_bitrate(self, bitrate, units):
 
100
        """Set the bitrate for the stream and recalculate the variables
 
101
        according to the fixed parameter.
 
102
        
 
103
        Keyword args:
 
104
        bitrate: number (integer or float ok)
 
105
        units: the units that the bitrate is in. Valid unit arguments are
 
106
            kbps (kilobits per second)
 
107
            MiBpm (Mibibytes per minute)
 
108
            GiBph (Gibibytes per hour)
 
109
        
 
110
        """
 
111
        self.bitrate.set(bitrate, units)
 
112
        if self.fixed_param == "RATE":
 
113
            pass
 
114
        elif self.fixed_param == "LENGTH":
 
115
            self._calculate_final_size()
 
116
        elif self.fixed_param == "SIZE":
 
117
            self._calculate_play_length()
 
118
 
 
119
    def set_play_length(self, play_length):
 
120
        """Set the play length in minutes and recalculate variables according
 
121
        to the fixed parameter.
 
122
        
 
123
        Keyword args:
 
124
        play_length -- how long the video is (minutes)
 
125
        
 
126
        """
 
127
        self.play_length = play_length
 
128
        if self.fixed_param == "RATE":
 
129
            self._calculate_final_size()
 
130
        elif self.fixed_param == "LENGTH":
 
131
            pass
 
132
        elif self.fixed_param == "SIZE":
 
133
            self._calculate_bitrate()
 
134
 
 
135
    def set_final_size(self, final_size):
 
136
        """Set the final size in MiB (Mebibytes) and recalculate variables
 
137
        according to the fixed parameter.
 
138
        
 
139
        Keyword args:
 
140
        final_size -- how large the final size can/should be (MiB)
 
141
        
 
142
        """
 
143
        self.final_size = final_size
 
144
        if self.fixed_param == "RATE":
 
145
            self._calculate_play_length()
 
146
        elif self.fixed_param == "LENGTH":
 
147
            self._calculate_bitrate()
 
148
        elif self.fixed_param == "SIZE":
 
149
            pass
 
150
 
 
151
    def set_fixed_param(self, param):
 
152
        """Set the fixed parameter of the AVstream object.
 
153
        
 
154
        Keyword args:
 
155
        param -- the parameter to fix. Valid arguments are
 
156
            RATE (the bitrate of the AVstream)
 
157
            LENGTH (the play length of the AVstream)
 
158
            SIZE (the final size of the AVstream)
 
159
        
 
160
        """
 
161
        valid_params = ["RATE", "SIZE", "LENGTH"]
 
162
        if param in valid_params:
 
163
            self.fixed_param = param
 
164
        else:
 
165
            print "%s: bad new fixed_param -- %s" % ('playtime', param)
 
166
            print "%s: keeping old fixed_param -- %s" \
 
167
                % ('playtime', self.fixed_param)
 
168
 
 
169
    def _calculate_bitrate(self):
 
170
        """Find the bitrate given the length and size"""
 
171
        self.bitrate.set( (self.final_size/self.play_length), 'MiBpm')
 
172
 
 
173
    def _calculate_final_size(self):
 
174
        """Find the final size give the bitrate and length"""
 
175
        self.final_size = self.bitrate.MiBpm * self.play_length
 
176
 
 
177
    def _calculate_play_length(self):
 
178
        """Find the length given the bitrate and size"""
 
179
        self.play_length =  self.final_size / self.bitrate.MiBpm
 
180
 
 
181
class Bitrate:
 
182
    """Convert between different bitrate units
 
183
    
 
184
    A Bitrate object stores a bitrate in three different units:
 
185
        kbps -- kilobits per second (the conventional unit)
 
186
        MiBpm -- Mibibytes per minute (uses for S/VCD sizes)
 
187
        GiBph -- Gibibytes per hour (useful for DVD sizes)
 
188
    
 
189
    Access these by name: 
 
190
        >>> br = playtime.Bitrate(3300)
 
191
        >>> br.kbps
 
192
        3300
 
193
        >>> br.MiBpm
 
194
        23.603439331054688
 
195
        >>> br.GiBph
 
196
        1.3830140233039856
 
197
        
 
198
    Once instantiated or set with a given bitrate and unit, the other
 
199
    remaining bitrates are automatically calculated and updated:
 
200
    
 
201
        >>> br.set(1, 'GiBph')
 
202
        >>> br.kbps
 
203
        2386.0929422222221
 
204
    
 
205
    """
 
206
    def __init__(self, bitrate, unit='kbps'):
 
207
        """Create a new Bitrate object
 
208
        
 
209
        Keyword args:
 
210
        bitrate: the bitrate (int or float ok)
 
211
        [opt] units: a string for units that bitrate is in (default: kbps). 
 
212
            Valid arguments are
 
213
                kbps (kilobits per second)
 
214
                MiBpm (Mibibytes per minute)
 
215
                GiBph (Gibibytes per hour)
 
216
        
 
217
        """
 
218
        self.set(bitrate, unit)
 
219
 
 
220
    def set(self, bitrate, unit):
 
221
        """Set the bitrate in 'unit' units.
 
222
        
 
223
        Keyword args:
 
224
        bitrate: new bitrate (integer or float ok)
 
225
        units: string for units that bitrate is in. Valid arguments are
 
226
            kbps (kilobits per second)
 
227
            MiBpm (Mibibytes per minute)
 
228
            GiBph (Gibibytes per hour)
 
229
        
 
230
        Once set with a given bitrate and unit, the other remaining
 
231
        bitrates are automatically calculated.
 
232
        
 
233
        """
 
234
        valid_units = ["kbps", "MiBpm", "GiBph"]
 
235
        if unit in valid_units:
 
236
            self.unit = unit
 
237
            if self.unit == 'kbps':
 
238
                self.kbps = bitrate
 
239
                self._to_MiBpm()
 
240
                self._to_GiBph()
 
241
            elif self.unit == 'MiBpm':
 
242
                self.MiBpm = bitrate
 
243
                self._to_kbps()
 
244
                self._to_GiBph()
 
245
            elif self.unit == 'GiBph':
 
246
                self.GiBph = bitrate
 
247
                self._to_kbps()
 
248
                self._to_MiBpm()
 
249
        else:
 
250
            print "%s: bad new units -- %s" % ('playtime', unit)
 
251
            print "%s: keeping old units -- %s" % ('playtime', self.unit)
 
252
            print "%s: keeping old bitrate -- %s" % \
 
253
                ('playtime', getattr(self, self.unit))
 
254
 
 
255
    def _to_kbps(self):
 
256
        """Convert the bitrate to kbps"""
 
257
        if self.unit == 'kbps':
 
258
            bitrate = self.kbps
 
259
        elif self.unit == 'MiBpm':
 
260
            bitrate = self.MiBpm * (8.0*1024.0*1024.0) / (60.0*1000.0)
 
261
        elif self.unit == 'GiBph':
 
262
            bitrate = self.GiBph * (8.0*1024.0*1024.0*1024.0) / (60.0*60.0*1000.0)
 
263
        self.unit = 'kbps'
 
264
        self.kbps = bitrate
 
265
 
 
266
    def _to_MiBpm(self):
 
267
        """Convert the bitrate to MiBpm"""
 
268
        if self.unit == 'kbps':
 
269
            bitrate = self.kbps * (60.0*1000.0) / (8.0*1024.0*1024.0)
 
270
        elif self.unit == 'MiBpm':
 
271
            bitrate = self.MiBpm
 
272
        elif self.unit == 'GiBph':
 
273
            bitrate = self.GiBph * 1024.0 / 60.0
 
274
        self.unit = 'MiBpm'
 
275
        self.MiBpm = bitrate
 
276
 
 
277
    def _to_GiBph(self):
 
278
        """Convert the bitrate to GiBph"""
 
279
        if self.unit == 'kbps':
 
280
            bitrate = self.kbps * (60.0*60.0*1000.0) / (8.0*1024.0*1024.0*1024.0)
 
281
        elif self.unit == 'MiBpm':
 
282
            bitrate = self.MiBpm * 60.0 / 1024.0
 
283
        elif self.unit == 'GiBph':
 
284
            bitrate = self.GiBph
 
285
        self.unit = 'GiBph'
 
286
        self.GiBph = bitrate