Skip to content

Commit

Permalink
Merge pull request #4 from globocom/master
Browse files Browse the repository at this point in the history
merge with upstream
  • Loading branch information
feuvan committed Jan 17, 2013
2 parents 6c18398 + 6c6c105 commit 9620974
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
17 changes: 15 additions & 2 deletions m3u8/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,15 +302,25 @@ def __str__(self):
class Playlist(BasePathMixin):
'''
Playlist object representing a link to a variant M3U8 with a specific bitrate.
Each `stream_info` attribute has: `program_id`, `bandwidth` and `codecs`
Each `stream_info` attribute has: `program_id`, `bandwidth`, `resolution` and `codecs`
`resolution` is a tuple (h, v) of integers
More info: http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.10
'''
def __init__(self, uri, stream_info, baseuri):
self.uri = uri
self.baseuri = baseuri

resolution = stream_info.get('resolution')
if resolution != None:
values = resolution.split('x')
resolution_pair = (int(values[0]), int(values[1]))
else:
resolution_pair = None

self.stream_info = StreamInfo(bandwidth=stream_info['bandwidth'],
program_id=stream_info.get('program_id'),
resolution=resolution_pair,
codecs=stream_info.get('codecs'))

def __str__(self):
Expand All @@ -319,11 +329,14 @@ def __str__(self):
stream_inf.append('PROGRAM-ID=' + self.stream_info.program_id)
if self.stream_info.bandwidth:
stream_inf.append('BANDWIDTH=' + self.stream_info.bandwidth)
if self.stream_info.resolution:
res = str(self.stream_info.resolution[0]) + 'x' + str(self.stream_info.resolution[1])
stream_inf.append('RESOLUTION=' + res)
if self.stream_info.codecs:
stream_inf.append('CODECS=' + quoted(self.stream_info.codecs))
return '#EXT-X-STREAM-INF:' + ','.join(stream_inf) + '\n' + self.uri

StreamInfo = namedtuple('StreamInfo', ['bandwidth', 'program_id', 'codecs'])
StreamInfo = namedtuple('StreamInfo', ['bandwidth', 'program_id', 'resolution', 'codecs'])

class PlaylistList(list, GroupedBasePathMixin):

Expand Down
8 changes: 8 additions & 0 deletions tests/playlists.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@
#EXT-X-ENDLIST
'''

SIMPLE_PLAYLIST_WITH_RESOLUTION = '''
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=445000,RESOLUTION=512x288,CODECS="avc1.77.30, mp4a.40.5"
index_0_av.m3u8?e=b471643725c47acd
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=45000,CODECS="mp4a.40.5"
index_0_a.m3u8?e=b471643725c47acd
'''

RELATIVE_PLAYLIST_FILENAME = abspath(join(dirname(__file__), 'playlists/relative-playlist.m3u8'))

RELATIVE_PLAYLIST_URI = TEST_HOST + '/path/to/relative-playlist.m3u8'
Expand Down
14 changes: 14 additions & 0 deletions tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ def test_playlists_attribute_without_program_id():
assert None == obj.playlists[0].stream_info.codecs
assert None == obj.playlists[0].stream_info.program_id

def test_playlists_attribute_with_resolution():
obj = m3u8.M3U8(SIMPLE_PLAYLIST_WITH_RESOLUTION)

assert 2 == len(obj.playlists)
assert (512, 288) == obj.playlists[0].stream_info.resolution
assert None == obj.playlists[1].stream_info.resolution

def test_version_attribute():
obj = m3u8.M3U8(SIMPLE_PLAYLIST)
mock_parser_data(obj, {'version': '2'})
Expand Down Expand Up @@ -173,6 +180,13 @@ def test_dumps_should_build_same_string():
expected = playlist.replace(', IV', ',IV').strip()
assert expected == obj.dumps().strip()

def test_dump_playlists_with_resolution():
obj = m3u8.M3U8(SIMPLE_PLAYLIST_WITH_RESOLUTION)

expected = SIMPLE_PLAYLIST_WITH_RESOLUTION.strip().splitlines()

assert expected == obj.dumps().strip().splitlines()

def test_dump_should_build_file_with_same_content(tmpdir):
obj = m3u8.M3U8(PLAYLIST_WITH_ENCRIPTED_SEGMENTS_AND_IV)

Expand Down

0 comments on commit 9620974

Please sign in to comment.