Some tests for the Python binding of the TS tools ================================================= We shall assume that our standard sample data has been downloaded and expanded into our sibling ``data`` directory. See the ``../data/setup.sh`` script. >>> test_es_file = '../data/ed24p_11.video.es' First, check we've got the basics working: >>> from tstools import ESFile >>> stream = ESFile(test_es_file) The filename is available as a "readonly" value: >>> stream.name == test_es_file True We've opened it for read: >>> stream.is_readable() == True True >>> stream.is_writable() == False True >>> stream.mode 'r' We should be able to iterate over its ES units: >>> count = 0 >>> es_unit_list = [] >>> for unit in stream: ... count += 1 ... print unit ... es_unit_list.append(unit) ... if count > 5: ... break ES unit: start code 00, len 9: 00 00 01 00 01 df ff fb b8 ES unit: start code b5, len 9: 00 00 01 b5 85 45 4b 5d 80 ES unit: start code 01, len 1645: 00 00 01 01 0a b0 10 09... ES unit: start code 02, len 1634: 00 00 01 02 0a b0 10 09... ES unit: start code 03, len 16: 00 00 01 03 0a b0 10 07... ES unit: start code 04, len 15: 00 00 01 04 0a b0 10 02... From ``hexdump -C`` I get (something that can be written out as):: 00 00 01 00 01 df ff fb b8 00 00 01 b5 85 45 4b 5d 80 00 00 01 01 0a b0 10 09 1c 56 ec d8 72 94 01 ... which tends to support those results. And close it: >>> stream.close() >>> stream.is_writable() == False True >>> stream.is_readable() == False True >>> stream.mode is None True We can ask an ES unit about itself: >>> unit = es_unit_list[0] >>> unit.start_posn 0+0 >>> unit.start_code 0 >>> unit.PES_had_PTS 0 >>> data = unit.data >>> len(data) 9 >>> data[0] '\x00' >>> text = 'data:' >>> for ii in range(8): ... text += ' %02x'%ord(data[ii]) >>> print text data: 00 00 01 00 01 df ff fb >>> unit.fred Traceback (most recent call last): ... AttributeError ES units can be compared for equality (but not order): >>> es_unit_list[0] == es_unit_list[0] 1 >>> es_unit_list[0] == es_unit_list[1] 0 >>> es_unit_list[0] != es_unit_list[1] 1 >>> es_unit_list[0] != es_unit_list[0] 0 >>> es_unit_list[0] < es_unit_list[1] Traceback (most recent call last): ... TypeError: ESUnit only supports == and != comparisons We can create an ES unit from a Python 'string': >>> from tstools import ESUnit >>> print 'old ',repr(es_unit_list[0]) old ES unit: start code 00, len 9: 00 00 01 00 01 df ff fb b8 >>> new = ESUnit(es_unit_list[0].data) >>> print 'new ',repr(new) new ES unit: start code 00, len 9: 00 00 01 00 01 df ff fb b8 >>> print 'old ',repr(es_unit_list[0]) old ES unit: start code 00, len 9: 00 00 01 00 01 df ff fb b8 >>> new == es_unit_list[0] True And write another file... >>> import tempfile >>> import os >>> directory = tempfile.mkdtemp() >>> filename = os.path.join(directory,'tstools_test_1.es') >>> out = ESFile(filename,'w') >>> out.name == filename True >>> out.is_readable() == False True >>> out.is_writable() == True True >>> out.mode 'w' >>> for unit in es_unit_list: ... out.write(unit) >>> out.close() Did that do the right thing? Check that we can read the units back (one by one, to test the ``read`` method), and that the units we read back are identical to those we wrote. >>> infile = ESFile(filename,'r') >>> other_units = [] >>> for ii in range(0,6): ... other_units.append(infile.read()) >>> >>> for ii in range(0,6): ... if es_unit_list[ii] != other_units[ii]: ... print 'Error: unit %d does not match'%ii ... break We already saw an ESOffset being returned: >>> es_unit_list[0].start_posn 0+0 >>> es_unit_list[1].start_posn 9+0 >>> es_unit_list[1].start_posn.report() Offset 0 in packet at offset 9 in file Output more like that produced by the C report tools can also be obtained: >>> print es_unit_list[1].start_posn.formatted() 00000000/00000009 We can create our own: >>> from tstools import ESOffset >>> offset = ESOffset(59,27) >>> offset.report() Offset 27 in packet at offset 59 in file >>> offset.infile 59L >>> offset.inpacket 27 There are keywords for the arguments, as well, for clarity: >>> ESOffset(infile=59,inpacket=27) == offset True And both default to 0: >>> ESOffset(infile=37).report() Offset 0 in packet at offset 37 in file >>> ESOffset().report() Offset 0 in packet at offset 0 in file Files can get very long -- the underlying ``lseek`` call can probably take 64-bit offsets. With luck, the Pyrex implementation can too: >>> loffset = ESOffset(0x1111111111111111,5) >>> loffset.report() Offset 5 in packet at offset 1229782938247303441 in file That's why we got the "59L" in an earlier example... And it may be useful to be able to compare them: >>> es_unit_list[1].start_posn > es_unit_list[0].start_posn True >>> es_unit_list[1].start_posn == es_unit_list[1].start_posn True >>> es_unit_list[0].start_posn < es_unit_list[1].start_posn True Seeking (to the start of an ES unit) is useful. However, the following are just testing the three ways of specifying the location to seek to (which may be overkill, but all seemed sensible at the time): >>> f = ESFile(test_es_file) >>> o = ESOffset(10,20) >>> f.seek(o) 10+20 >>> f.seek(20) 20+0 >>> f.seek(30,40) 30+40 >>> f.seek(10,20,30) Traceback (most recent call last): ... TypeError: Seek argument must be one integer, two integers or an ESOffset >>> f.seek('fred') Traceback (most recent call last): ... TypeError: Seek argument must be one integer, two integers or an ESOffset >>> f.seek(-1) Traceback (most recent call last): ... TSToolsException: Error seeking to (-1,) in file '../data/ed24p_11.video.es' Let's try proper seeking, though: >>> p = f.seek(es_unit_list[-1].start_posn) >>> p == es_unit_list[-1].start_posn True >>> u = f.read() >>> u.start_posn == es_unit_list[-1].start_posn True >>> u == es_unit_list[-1] True OK. So ``seek()`` returns a tuple of (infile,inpacket), whilst the ``start_posn`` attribute is an ``ESOffset``. Which may or may not make sense -- but I really would rather the latter had *some* annotation explicit as to what each field means, because it *is* impossible to decide rationally which order they should come in. // Local Variables: // tab-width: 8 // indent-tabs-mode: nil // c-basic-offset: 2 // End: // vim: set filetype=rst tabstop=8 shiftwidth=2 expandtab: