Remove write capabilities from wtap_optionblocks.
[metze/wireshark/wip.git] / wiretap / mp2t.c
1 /* mp2t.c
2  *
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
6  *
7  * Wiretap Library
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.
12  *
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.
17  *
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.
21  */
22
23 #include "config.h"
24
25 #ifdef HAVE_SYS_TYPES_H
26 #include <sys/types.h>
27 #endif
28
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #include "mp2t.h"
34
35 #include "wtap-int.h"
36 #include <wsutil/buffer.h>
37 #include "file_wrappers.h"
38 #include <errno.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <time.h>
42
43 #define MP2T_SYNC_BYTE      0x47
44 #define MP2T_SIZE           188
45 #define MP2T_QAM64_BITRATE  26970350    /* bits per second */
46 #define MP2T_PCR_CLOCK      27000000    /* cycles per second - 27MHz */
47
48 /* we try to detect trailing data up to 40 bytes after each packet */
49 #define TRAILER_LEN_MAX 40
50
51 /* number of consecutive packets we must read to decide that a file
52    is actually an mpeg2 ts */
53 #define SYNC_STEPS   10
54
55
56 typedef struct {
57     guint32 start_offset;
58     guint64 bitrate;
59     /* length of trailing data (e.g. FEC) that's appended after each packet */
60     guint8  trailer_len;
61 } mp2t_filetype_t;
62
63 static gboolean
64 mp2t_read_packet(mp2t_filetype_t *mp2t, FILE_T fh, gint64 offset,
65                  struct wtap_pkthdr *phdr, Buffer *buf, int *err,
66                  gchar **err_info)
67 {
68     guint64 tmp;
69
70     /*
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.
73      */
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))
76         return FALSE;
77
78     phdr->rec_type = REC_TYPE_PACKET;
79
80     /* XXX - relative, not absolute, time stamps */
81     phdr->presence_flags = WTAP_HAS_TS;
82
83     /*
84      * Every packet in an MPEG2-TS stream is has a fixed size of
85      * MP2T_SIZE plus the number of trailer bytes.
86      *
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
91      * by the bitrate.
92      *
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.
96      */
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);
100
101     phdr->caplen = MP2T_SIZE;
102     phdr->len = MP2T_SIZE;
103
104     return TRUE;
105 }
106
107 static gboolean
108 mp2t_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
109 {
110     mp2t_filetype_t *mp2t;
111
112     mp2t = (mp2t_filetype_t*) wth->priv;
113
114     *data_offset = file_tell(wth->fh);
115
116     if (!mp2t_read_packet(mp2t, wth->fh, *data_offset, &wth->phdr,
117                           wth->frame_buffer, err, err_info)) {
118         return FALSE;
119     }
120
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)) {
124             return FALSE;
125         }
126     }
127
128     return TRUE;
129 }
130
131 static gboolean
132 mp2t_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr,
133         Buffer *buf, int *err, gchar **err_info)
134 {
135     mp2t_filetype_t *mp2t;
136
137     if (-1 == file_seek(wth->random_fh, seek_off, SEEK_SET, err)) {
138         return FALSE;
139     }
140
141     mp2t = (mp2t_filetype_t*) wth->priv;
142
143     if (!mp2t_read_packet(mp2t, wth->random_fh, seek_off, phdr, buf,
144                           err, err_info)) {
145         if (*err == 0)
146             *err = WTAP_ERR_SHORT_READ;
147         return FALSE;
148     }
149     return TRUE;
150 }
151
152 static guint64
153 mp2t_read_pcr(guint8 *buffer)
154 {
155     guint64 base;
156     guint64 ext;
157
158     base = pntoh40(buffer);
159     base >>= 7;
160
161     ext = pntoh16(&buffer[4]);
162     ext &= 0x01ff;
163
164     return (base * 300 + ext);
165 }
166
167 static gboolean
168 mp2t_find_next_pcr(wtap *wth, guint8 trailer_len,
169         int *err, gchar **err_info, guint32 *idx, guint64 *pcr, guint16 *pid)
170 {
171     guint8 buffer[MP2T_SIZE+TRAILER_LEN_MAX];
172     gboolean found;
173     guint8 afc;
174     guint timeout = 0;
175
176     found = FALSE;
177     while (FALSE == found && timeout++ < SYNC_STEPS * SYNC_STEPS) {
178         (*idx)++;
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 */
182             return FALSE;
183         }
184
185         if (MP2T_SYNC_BYTE != buffer[0]) {
186             continue;
187         }
188
189         /* Read out the AFC value. */
190         afc = 3 & (buffer[3] >> 4);
191         if (afc < 2) {
192             continue;
193         }
194
195         /* Check the length. */
196         if (buffer[4] < 7) {
197             continue;
198         }
199
200         /* Check that there is the PCR flag. */
201         if (0x10 != (0x10 & buffer[5])) {
202             continue;
203         }
204
205         /* We have a PCR value! */
206         *pcr = mp2t_read_pcr(&buffer[6]);
207         *pid = 0x01ff & pntoh16(&buffer[1]);
208         found = TRUE;
209     }
210
211     return found;
212 }
213
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)
217 {
218     guint32 pn1, pn2;
219     guint64 pcr1, pcr2;
220     guint16 pid1, pid2;
221     guint32 idx;
222     guint64 pcr_delta, bits_passed;
223
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.
228      *
229      * XXX - is this assuming that the time stamps in the PCRs correspond
230      * to the time scale of the underlying transport stream?
231      */
232     idx = first;
233
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 */
238         if (*err != 0)
239             return WTAP_OPEN_ERROR;
240
241         /* We don't have any PCRs, so we can't guess the bit rate.
242          * Default to something reasonable.
243          */
244         *bitrate = MP2T_QAM64_BITRATE;
245         return WTAP_OPEN_MINE;
246     }
247
248     pn1 = idx;
249     pn2 = pn1;
250
251     while (pn1 == pn2) {
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 */
256             if (*err != 0)
257                 return WTAP_OPEN_ERROR;
258
259             /* We don't have two PCRs for the same PID, so we can't guess
260              * the bit rate.
261              * Default to something reasonable.
262              */
263             *bitrate = MP2T_QAM64_BITRATE;
264             return WTAP_OPEN_MINE;
265         }
266
267         if (pid1 == pid2) {
268             pn2 = idx;
269         }
270     }
271
272     if (pcr2 <= pcr1) {
273         /* The PCRs for that PID didn't go forward; treat that as an
274          * indication that this isn't an MPEG-2 TS.
275          */
276         return WTAP_OPEN_NOT_MINE;
277     }
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;
283
284     *bitrate = ((MP2T_PCR_CLOCK * bits_passed) / pcr_delta);
285     if (*bitrate == 0) {
286         /* pcr_delta < MP2T_PCR_CLOCK * bits_passed (pn2 != pn1,
287          * as that's the test for the loop above, so bits_passed
288          * is non-zero).
289          *
290          * That will produce a fractional bitrate, which turns
291          * into zero, causing a zero divide later.
292          *
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
296          * be an MP2T file.
297          */
298         return WTAP_OPEN_ERROR;
299     }
300     return WTAP_OPEN_MINE;
301 }
302
303 wtap_open_return_val
304 mp2t_open(wtap *wth, int *err, gchar **err_info)
305 {
306     guint8 buffer[MP2T_SIZE+TRAILER_LEN_MAX];
307     guint8 trailer_len = 0;
308     guint sync_steps = 0;
309     guint i;
310     guint32 first = 0;
311     mp2t_filetype_t *mp2t;
312     wtap_open_return_val status;
313     guint64 bitrate;
314
315
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;
320     }
321
322     for (i = 0; i < MP2T_SIZE; i++) {
323         if (MP2T_SYNC_BYTE == buffer[i]) {
324             first = i;
325             goto found;
326         }
327     }
328     /*
329      * No sync bytes found, so not an MPEG-2 Transport Stream file.
330      */
331     return WTAP_OPEN_NOT_MINE; /* wrong file type - not an mpeg2 ts file */
332
333 found:
334     if (-1 == file_seek(wth->fh, first, SEEK_SET, err)) {
335         return WTAP_OPEN_ERROR;
336     }
337
338     /* read some packets and make sure they all start with a sync byte */
339     do {
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 */
345        }
346        if (buffer[0] == MP2T_SYNC_BYTE) {
347                sync_steps++;
348        }
349        else {
350            /* no sync byte found, check if trailing data is appended
351               and we have to increase the packet size */
352
353            /* if we've already detected a trailer field, we must remain in sync
354               another mismatch means we have no mpeg2 ts file */
355            if (trailer_len>0)
356                return WTAP_OPEN_NOT_MINE;
357
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) {
361                    trailer_len = i;
362                    if (-1 == file_seek(wth->fh, first, SEEK_SET, err)) {
363                        return WTAP_OPEN_ERROR;
364                    }
365                    sync_steps = 0;
366                    break;
367                }
368            }
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;
372        }
373     } while (sync_steps < SYNC_STEPS);
374
375     if (-1 == file_seek(wth->fh, first, SEEK_SET, err)) {
376         return WTAP_OPEN_ERROR;
377     }
378
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) {
383         return status;
384     }
385
386     if (-1 == file_seek(wth->fh, first, SEEK_SET, err)) {
387         return WTAP_OPEN_ERROR;
388     }
389
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;
396
397     mp2t = (mp2t_filetype_t*) g_malloc(sizeof(mp2t_filetype_t));
398
399     wth->priv = mp2t;
400     mp2t->start_offset = first;
401     mp2t->trailer_len = trailer_len;
402     mp2t->bitrate = bitrate;
403
404     return WTAP_OPEN_MINE;
405 }
406
407 /*
408  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
409  *
410  * Local variables:
411  * c-basic-offset: 4
412  * tab-width: 8
413  * indent-tabs-mode: nil
414  * End:
415  *
416  * vi: set shiftwidth=4 tabstop=8 expandtab:
417  * :indentSize=4:tabSize=8:noTabs=true:
418  */