3 * ISO/IEC 13818-1 MPEG2-TS file format decoder for the Wiretap library.
4 * Written by Weston Schmidt <weston_schmidt@alumni.purdue.edu>
5 * Copyright 2012 Weston Schmidt
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #ifdef HAVE_SYS_TYPES_H
26 #include <sys/types.h>
36 #include <wsutil/buffer.h>
37 #include "file_wrappers.h"
43 #define MP2T_SYNC_BYTE 0x47
45 #define MP2T_QAM64_BITRATE 26970350 /* bits per second */
46 #define MP2T_PCR_CLOCK 27000000 /* cycles per second - 27MHz */
48 /* we try to detect trailing data up to 40 bytes after each packet */
49 #define TRAILER_LEN_MAX 40
51 /* number of consecutive packets we must read to decide that a file
52 is actually an mpeg2 ts */
59 /* length of trailing data (e.g. FEC) that's appended after each packet */
64 mp2t_read_packet(mp2t_filetype_t *mp2t, FILE_T fh, gint64 offset,
65 struct wtap_pkthdr *phdr, Buffer *buf, int *err,
71 * MP2T_SIZE will always be less than WTAP_MAX_PACKET_SIZE, so
72 * we don't have to worry about the packet being too big.
74 ws_buffer_assure_space(buf, MP2T_SIZE);
75 if (!wtap_read_bytes_or_eof(fh, ws_buffer_start_ptr(buf), MP2T_SIZE, err, err_info))
78 phdr->rec_type = REC_TYPE_PACKET;
80 /* XXX - relative, not absolute, time stamps */
81 phdr->presence_flags = WTAP_HAS_TS;
84 * Every packet in an MPEG2-TS stream is has a fixed size of
85 * MP2T_SIZE plus the number of trailer bytes.
87 * We assume that the bits in the transport stream are supplied at
88 * a constant rate; is that guaranteed by all media that use
89 * MPEG2-TS? If so, the time offset, from the beginning of the
90 * stream, of a given packet is the packet offset, in bits, divided
93 * It would be really cool to be able to configure the bitrate, in
94 * case our attempt to guess it from the PCRs of one of the programs
95 * doesn't get the right answer.
97 tmp = ((guint64)(offset - mp2t->start_offset) * 8); /* offset, in bits */
98 phdr->ts.secs = (time_t)(tmp / mp2t->bitrate);
99 phdr->ts.nsecs = (int)((tmp % mp2t->bitrate) * 1000000000 / mp2t->bitrate);
101 phdr->caplen = MP2T_SIZE;
102 phdr->len = MP2T_SIZE;
108 mp2t_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
110 mp2t_filetype_t *mp2t;
112 mp2t = (mp2t_filetype_t*) wth->priv;
114 *data_offset = file_tell(wth->fh);
116 if (!mp2t_read_packet(mp2t, wth->fh, *data_offset, &wth->phdr,
117 wth->frame_buffer, err, err_info)) {
121 /* if there's a trailer, skip it and go to the start of the next packet */
122 if (mp2t->trailer_len!=0) {
123 if (-1 == file_seek(wth->fh, mp2t->trailer_len, SEEK_CUR, err)) {
132 mp2t_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr,
133 Buffer *buf, int *err, gchar **err_info)
135 mp2t_filetype_t *mp2t;
137 if (-1 == file_seek(wth->random_fh, seek_off, SEEK_SET, err)) {
141 mp2t = (mp2t_filetype_t*) wth->priv;
143 if (!mp2t_read_packet(mp2t, wth->random_fh, seek_off, phdr, buf,
146 *err = WTAP_ERR_SHORT_READ;
153 mp2t_read_pcr(guint8 *buffer)
158 base = pntoh40(buffer);
161 ext = pntoh16(&buffer[4]);
164 return (base * 300 + ext);
168 mp2t_find_next_pcr(wtap *wth, guint8 trailer_len,
169 int *err, gchar **err_info, guint32 *idx, guint64 *pcr, guint16 *pid)
171 guint8 buffer[MP2T_SIZE+TRAILER_LEN_MAX];
177 while (FALSE == found && timeout++ < SYNC_STEPS * SYNC_STEPS) {
179 if (!wtap_read_bytes_or_eof(
180 wth->fh, buffer, MP2T_SIZE+trailer_len, err, err_info)) {
181 /* Read error, short read, or EOF */
185 if (MP2T_SYNC_BYTE != buffer[0]) {
189 /* Read out the AFC value. */
190 afc = 3 & (buffer[3] >> 4);
195 /* Check the length. */
200 /* Check that there is the PCR flag. */
201 if (0x10 != (0x10 & buffer[5])) {
205 /* We have a PCR value! */
206 *pcr = mp2t_read_pcr(&buffer[6]);
207 *pid = 0x01ff & pntoh16(&buffer[1]);
214 static wtap_open_return_val
215 mp2t_bits_per_second(wtap *wth, guint32 first, guint8 trailer_len,
216 guint64 *bitrate, int *err, gchar **err_info)
222 guint64 pcr_delta, bits_passed;
224 /* Find the first PCR + PID.
225 * Then find another PCR in that PID.
226 * Take the difference and that's our bitrate.
227 * All the different PCRs in different PIDs 'should' be the same.
229 * XXX - is this assuming that the time stamps in the PCRs correspond
230 * to the time scale of the underlying transport stream?
234 if (!mp2t_find_next_pcr(wth, trailer_len, err, err_info, &idx, &pcr1, &pid1)) {
235 /* Read error, short read, or EOF */
236 if (*err == WTAP_ERR_SHORT_READ)
237 return WTAP_OPEN_NOT_MINE; /* not a full frame */
239 return WTAP_OPEN_ERROR;
241 /* We don't have any PCRs, so we can't guess the bit rate.
242 * Default to something reasonable.
244 *bitrate = MP2T_QAM64_BITRATE;
245 return WTAP_OPEN_MINE;
252 if (!mp2t_find_next_pcr(wth, trailer_len, err, err_info, &idx, &pcr2, &pid2)) {
253 /* Read error, short read, or EOF */
254 if (*err == WTAP_ERR_SHORT_READ)
255 return WTAP_OPEN_NOT_MINE; /* not a full frame */
257 return WTAP_OPEN_ERROR;
259 /* We don't have two PCRs for the same PID, so we can't guess
261 * Default to something reasonable.
263 *bitrate = MP2T_QAM64_BITRATE;
264 return WTAP_OPEN_MINE;
273 /* The PCRs for that PID didn't go forward; treat that as an
274 * indication that this isn't an MPEG-2 TS.
276 return WTAP_OPEN_NOT_MINE;
278 pcr_delta = pcr2 - pcr1;
279 /* cast one of the factors to guint64
280 otherwise, the multiplication would use guint32 and could
281 overflow before the result is assigned to the guint64 bits_passed */
282 bits_passed = (guint64)MP2T_SIZE * (pn2 - pn1) * 8;
284 *bitrate = ((MP2T_PCR_CLOCK * bits_passed) / pcr_delta);
286 /* pcr_delta < MP2T_PCR_CLOCK * bits_passed (pn2 != pn1,
287 * as that's the test for the loop above, so bits_passed
290 * That will produce a fractional bitrate, which turns
291 * into zero, causing a zero divide later.
293 * XXX - should we report this as "not ours"? A bitrate
294 * of less than 1 bit per second is not very useful for any
295 * form of audio/video, so presumably that's unlikely to
298 return WTAP_OPEN_ERROR;
300 return WTAP_OPEN_MINE;
304 mp2t_open(wtap *wth, int *err, gchar **err_info)
306 guint8 buffer[MP2T_SIZE+TRAILER_LEN_MAX];
307 guint8 trailer_len = 0;
308 guint sync_steps = 0;
311 mp2t_filetype_t *mp2t;
312 wtap_open_return_val status;
316 if (!wtap_read_bytes(wth->fh, buffer, MP2T_SIZE, err, err_info)) {
317 if (*err != WTAP_ERR_SHORT_READ)
318 return WTAP_OPEN_ERROR;
319 return WTAP_OPEN_NOT_MINE;
322 for (i = 0; i < MP2T_SIZE; i++) {
323 if (MP2T_SYNC_BYTE == buffer[i]) {
329 * No sync bytes found, so not an MPEG-2 Transport Stream file.
331 return WTAP_OPEN_NOT_MINE; /* wrong file type - not an mpeg2 ts file */
334 if (-1 == file_seek(wth->fh, first, SEEK_SET, err)) {
335 return WTAP_OPEN_ERROR;
338 /* read some packets and make sure they all start with a sync byte */
340 if (!wtap_read_bytes(wth->fh, buffer, MP2T_SIZE+trailer_len, err, err_info)) {
341 if (*err != WTAP_ERR_SHORT_READ)
342 return WTAP_OPEN_ERROR; /* read error */
343 if(sync_steps<2) return WTAP_OPEN_NOT_MINE; /* wrong file type - not an mpeg2 ts file */
344 break; /* end of file, that's ok if we're still in sync */
346 if (buffer[0] == MP2T_SYNC_BYTE) {
350 /* no sync byte found, check if trailing data is appended
351 and we have to increase the packet size */
353 /* if we've already detected a trailer field, we must remain in sync
354 another mismatch means we have no mpeg2 ts file */
356 return WTAP_OPEN_NOT_MINE;
358 /* check if a trailer is appended to the packet */
359 for (i=0; i<TRAILER_LEN_MAX; i++) {
360 if (buffer[i] == MP2T_SYNC_BYTE) {
362 if (-1 == file_seek(wth->fh, first, SEEK_SET, err)) {
363 return WTAP_OPEN_ERROR;
369 /* no sync byte found in the vicinity, this is no mpeg2 ts file */
370 if (i==TRAILER_LEN_MAX)
371 return WTAP_OPEN_NOT_MINE;
373 } while (sync_steps < SYNC_STEPS);
375 if (-1 == file_seek(wth->fh, first, SEEK_SET, err)) {
376 return WTAP_OPEN_ERROR;
379 /* Ensure there is a valid bitrate */
380 status = mp2t_bits_per_second(wth, first, trailer_len,
381 &bitrate, err, err_info);
382 if (status != WTAP_OPEN_MINE) {
386 if (-1 == file_seek(wth->fh, first, SEEK_SET, err)) {
387 return WTAP_OPEN_ERROR;
390 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_MPEG_2_TS;
391 wth->file_encap = WTAP_ENCAP_MPEG_2_TS;
392 wth->file_tsprec = WTAP_TSPREC_NSEC;
393 wth->subtype_read = mp2t_read;
394 wth->subtype_seek_read = mp2t_seek_read;
395 wth->snapshot_length = 0;
397 mp2t = (mp2t_filetype_t*) g_malloc(sizeof(mp2t_filetype_t));
400 mp2t->start_offset = first;
401 mp2t->trailer_len = trailer_len;
402 mp2t->bitrate = bitrate;
404 return WTAP_OPEN_MINE;
408 * Editor modelines - http://www.wireshark.org/tools/modelines.html
413 * indent-tabs-mode: nil
416 * vi: set shiftwidth=4 tabstop=8 expandtab:
417 * :indentSize=4:tabSize=8:noTabs=true: