Playitsam v1: The End of the Line

After wrestling with Playitsam version 1.x for some time, I've come to the realisation that the TiVo's tystream format is useless when it comes to editing. The main problems with the tystream format, in terms of editing it are:

For more details of the difficulties, have a read through chunk.c. There are so many special cases and multi-chunk handling issues that I can safely say that Playitsam v1 will never accurately edit 100% of the tystreams from the TiVo. Therefore, I have decided to completely stop developing Playitsam v1, and start thinking of how to build a version 2 from scratch.

Design Ideas

So far, all I've done is to sketch out a file format for the purpose of editing. I will write some intermediary routines to read TiVo streams at the chunk level, but convert into the new format on the fly, so that the upper levels of Playitsam v2 will only see the new stream format. Here are the ideas so far:

The new tystream file format will consist of a number of variable-sized records. Each record will start with the following header.

#define NEW_TY_VERSION  0x6e747901 /* Version this header describes */

struct new_ty_header {

  u_int32_t version;               /* Version of this stream format */

  u_int32_t total_size;            /* Size in octets of the whole record */

  u_int32_t index;                 /* Index number of this record */

  u_int32_t next_index;            /* Index number of the next record */

  u_int32_t num_entries;           /* Number of entries in the table below */

};

All field entries are stored in big-endian (i.e network) format. The version number is 'n', 't', 'y' followed by the number 1. Future versions, if any, will be numbered 2 upwards.

The total size is the size in octets of the whole record, including the header, the table, and the data itself.

The index number is the number of this record in the file. Note: index numbers must be monotonically increasing, but are not necessarily contiguous. In other words, numbers 1, 2, 3, 7, 11, 51 ... are valid. This allows us to use the original chunk numbers as index numbers, or simply 0,1,2,3,4 if we are creating a new file.

Because the next index number is not predictable, this is also stored in the record. To indicate that there is no next record, the next_index field in the last record is set to 0.

The number of entries in the table following the header is num_entries. The table consists of the following entries, again in big-endian format.

#define INVALID_ENTRY   0

#define GOP_ENTRY       1

#define I_ENTRY         2

#define P_ENTRY         3

#define B_ENTRY         4

#define AUDIO_ENTRY     5

struct new_ty_entry {

  u_int32_t type;            /* Type of entry */

  u_int32_t timestamp;       /* Timestamp for the entry */

  u_int32_t size;            /* Size of data area in octets */

};

The type field holds one of the constants defined above. The timestamp is the timestamp from the TiVo recording, in 90kHz units. The size is the size of the data area following the table in octets.

Each record (header, table, data area) holds a whole Group of Pictures and their associated audio segments. The video entries are in the usual MPEG stored format, i.e GOP I3 B1 B2 P6 B4 B5 P9 B7 B8 P12 B10 B11.

Interspersed between the video records are the audio records whose timestamps fit into the time-period of this Group, i.e whose timestamps are >= the lowest video timestamp and are also <= the highest timestamp. Note that the audio records that relate to the B1 and B2 records are stored before the B1 record.

After the table, there is a data area containing the video and audio data in the order given in the table. The size of the data area is the sum of the size entries in the table, and also equal to total_size - num_entries * sizeof(struct new_ty_entry).

Internally, we store the table in a linked list of the following type.

struct new_ty_list {

  u_int32_t type;               /* Type of entry */

  u_int32_t timestamp;          /* Timestamp for the entry */

  u_int8_t  *buf;               /* Pointer to the data area in memory */

  struct new_ty_table *next;    /* Next entry in the linked list */

};

If you have any questions or comments, please e-mail me at wkt@tuhs.org.

Warren Toomey, September 2002.


File translated from TEX by TTH, version 2.78.
On 3 Sep 2002, 08:06.