3 * MPEG file format decoder for the Wiretap library.
4 * Written by Shaun Jackman <sjackman@gmail.com>
5 * Copyright 2007 Shaun Jackman
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #ifdef HAVE_SYS_TYPES_H
30 #include <sys/types.h>
38 #include "wsutil/mpeg-audio.h"
42 #include "file_wrappers.h"
49 #define PES_VALID(n) (((n) >> 8 & 0xffffff) == PES_PREFIX)
52 struct wtap_nstime now;
57 mpeg_resync(wtap *wth, int *err, gchar **err_info _U_)
59 gint64 offset = file_tell(wth->fh);
61 int byte = file_getc(wth->fh);
64 if (byte == 0xff && count > 0) {
65 byte = file_getc(wth->fh);
66 if (byte != EOF && (byte & 0xe0) == 0xe0)
69 byte = file_getc(wth->fh);
72 if (file_seek(wth->fh, offset, SEEK_SET, err) == -1)
78 mpeg_read_header(wtap *wth, int *err, gchar **err_info, guint32 *n)
82 errno = WTAP_ERR_CANT_READ;
83 bytes_read = file_read(n, sizeof *n, wth->fh);
84 if (bytes_read != sizeof *n) {
85 *err = file_error(wth->fh, err_info);
86 if (*err == 0 && bytes_read != 0)
87 *err = WTAP_ERR_SHORT_READ;
91 if (file_seek(wth->fh, -(gint64)(sizeof *n), SEEK_CUR, err) == -1)
97 mpeg_read_rec_data(FILE_T fh, guchar *pd, int length, int *err,
102 errno = WTAP_ERR_CANT_READ;
103 bytes_read = file_read(pd, length, fh);
105 if (bytes_read != length) {
106 *err = file_error(fh, err_info);
108 *err = WTAP_ERR_SHORT_READ;
114 #define SCRHZ 27000000
117 mpeg_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
119 mpeg_t *mpeg = (mpeg_t *)wth->priv;
121 int bytes_read = mpeg_read_header(wth, err, err_info, &n);
122 unsigned int packet_size;
123 struct wtap_nstime ts = mpeg->now;
125 if (bytes_read == -1)
128 gint64 offset = file_tell(wth->fh);
133 if (file_seek(wth->fh, 3, SEEK_CUR, err) == -1)
136 bytes_read = file_read(&stream, sizeof stream, wth->fh);
137 if (bytes_read != sizeof stream) {
138 *err = file_error(wth->fh, err_info);
142 if (stream == 0xba) {
148 bytes_read = file_read(&pack1, sizeof pack1, wth->fh);
149 if (bytes_read != sizeof pack1) {
150 *err = file_error(wth->fh, err_info);
151 if (*err == 0 && bytes_read != 0)
152 *err = WTAP_ERR_SHORT_READ;
155 bytes_read = file_read(&pack0, sizeof pack0, wth->fh);
156 if (bytes_read != sizeof pack0) {
157 *err = file_error(wth->fh, err_info);
158 if (*err == 0 && bytes_read != 0)
159 *err = WTAP_ERR_SHORT_READ;
162 pack = (guint64)g_ntohl(pack1) << 32 | g_ntohl(pack0);
164 switch (pack >> 62) {
166 if (file_seek(wth->fh, 1, SEEK_CUR, err) == -1)
168 bytes_read = file_read(&stuffing,
169 sizeof stuffing, wth->fh);
170 if (bytes_read != sizeof stuffing) {
171 *err = file_error(wth->fh, err_info);
175 packet_size = 14 + stuffing;
178 guint64 bytes = pack >> 16;
180 (bytes >> 43 & 0x0007) << 30 |
181 (bytes >> 27 & 0x7fff) << 15 |
182 (bytes >> 11 & 0x7fff) << 0;
183 unsigned ext = (unsigned)((bytes >> 1) & 0x1ff);
184 guint64 cr = 300 * ts_val + ext;
185 unsigned rem = (unsigned)(cr % SCRHZ);
187 = mpeg->t0 + (time_t)(cr / SCRHZ);
189 = (int)(G_GINT64_CONSTANT(1000000000) * rem / SCRHZ);
198 bytes_read = file_read(&length, sizeof length, wth->fh);
199 if (bytes_read != sizeof length) {
200 *err = file_error(wth->fh, err_info);
201 if (*err == 0 && bytes_read != 0)
202 *err = WTAP_ERR_SHORT_READ;
205 length = g_ntohs(length);
206 packet_size = 6 + length;
209 if (file_seek(wth->fh, offset, SEEK_SET, err) == -1)
214 MPA_UNMARSHAL(&mpa, n);
215 if (MPA_VALID(&mpa)) {
216 packet_size = MPA_BYTES(&mpa);
217 mpeg->now.nsecs += MPA_DURATION_NS(&mpa);
218 if (mpeg->now.nsecs >= 1000000000) {
220 mpeg->now.nsecs -= 1000000000;
223 packet_size = mpeg_resync(wth, err, err_info);
224 if (packet_size == 0)
228 *data_offset = wth->data_offset;
230 buffer_assure_space(wth->frame_buffer, packet_size);
231 if (!mpeg_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
232 packet_size, err, err_info))
234 wth->data_offset += packet_size;
236 wth->phdr.caplen = packet_size;
237 wth->phdr.len = packet_size;
242 mpeg_seek_read(wtap *wth, gint64 seek_off,
243 union wtap_pseudo_header *pseudo_header _U_, guchar *pd, int length,
244 int *err, gchar **err_info)
246 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
248 return mpeg_read_rec_data(wth->random_fh, pd, length, err, err_info);
255 { 3, "TAG" }, /* ID3v1 */
256 { 3, "ID3" }, /* ID3v2 */
257 { 3, "\0\0\1" }, /* MPEG PES */
258 { 2, "\xff\xfb" }, /* MP3, taken from http://en.wikipedia.org/wiki/MP3#File_structure */
263 mpeg_open(wtap *wth, int *err, gchar **err_info)
267 struct _mpeg_magic* m;
270 errno = WTAP_ERR_CANT_READ;
271 bytes_read = file_read(magic_buf, sizeof magic_buf, wth->fh);
272 if (bytes_read != (int) sizeof magic_buf) {
273 *err = file_error(wth->fh, err_info);
279 for (m=magic; m->match; m++) {
280 if (memcmp(magic_buf, m->match, m->len) == 0)
287 /* This appears to be a file with MPEG data. */
288 if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
291 wth->file_type = WTAP_FILE_MPEG;
292 wth->file_encap = WTAP_ENCAP_MPEG;
293 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
294 wth->subtype_read = mpeg_read;
295 wth->subtype_seek_read = mpeg_seek_read;
296 wth->snapshot_length = 0;
298 mpeg = (mpeg_t *)g_malloc(sizeof(mpeg_t));
299 wth->priv = (void *)mpeg;
300 mpeg->now.secs = time(NULL);
302 mpeg->t0 = mpeg->now.secs;