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:
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.
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 */
};
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 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 */
};
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.
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 */
};
Warren Toomey, September 2002.