added some options and enhancements to the print output:
[obnox/wireshark/wip.git] / packet-mpeg1.c
1 /* packet-mpeg1.c
2  *
3  * Routines for RFC 2250 MPEG-1 dissection
4  *
5  * $Id: packet-mpeg1.c,v 1.10 2003/08/23 06:36:46 guy Exp $
6  *
7  * Copyright 2001,
8  * Francisco Javier Cabello Torres, <fjcabello@vtools.es>
9  *
10  * Ethereal - Network traffic analyzer
11  * By Gerald Combs <gerald@ethereal.com>
12  * Copyright 1998 Gerald Combs
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 /*
30  * This dissector tries to dissect the MPEG-1 video streams.
31  */
32
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <glib.h>
39 #include <epan/packet.h>
40
41 #include <stdio.h>
42 #include <string.h>
43
44 #include "rtp_pt.h"
45
46 #define RTP_MPG_MBZ(word) ( word >> 11)
47 #define RTP_MPG_T(word)   ( (word >> 10) & 1 )
48 #define RTP_MPG_TR(word)   ( word & 0x3ff )
49
50 #define RTP_MPG_AN(octet) ( octet >> 7)
51 #define RTP_MPG_N(octet)  ( (octet >> 6) & 1 )
52 #define RTP_MPG_S(octet)  ( (octet >> 5) & 1 )
53 #define RTP_MPG_B(octet)  ( (octet >> 4) & 1 )
54 #define RTP_MPG_E(octet)  ( (octet >> 3) & 1 )
55 #define RTP_MPG_P(octet)  ( octet & 7 )
56
57 #define RTP_MPG_FBV(octet) ( (octet >> 7) & 1 )
58 #define RTP_MPG_BFC(octet) ( (octet >> 4) & 7 )
59 #define RTP_MPG_FFV(octet) ( (octet >> 3) & 1 )
60 #define RTP_MPG_FFC(octet) (  octet & 7 )
61
62
63 /* MPEG1 header fields             */
64
65
66 static int proto_mpg          = -1;
67
68 static int hf_rtp_mpg_mbz     = -1;
69 static int hf_rtp_mpg_T       = -1;
70 static int hf_rtp_mpg_tr      = -1;
71 static int hf_rtp_mpg_an      = -1;
72 static int hf_rtp_mpg_n       = -1;
73 static int hf_rtp_mpg_s       = -1;
74 static int hf_rtp_mpg_b       = -1;
75 static int hf_rtp_mpg_e       = -1;
76 static int hf_rtp_mpg_p       = -1;
77
78
79 static int hf_rtp_mpg_fbv     = -1;
80 static int hf_rtp_mpg_bfc     = -1;
81 static int hf_rtp_mpg_ffv     = -1;
82 static int hf_rtp_mpg_ffc     = -1;
83 static int hf_rtp_mpg_data    = -1;
84
85
86
87 /* MPEG-1 fields defining a sub tree */
88 static gint ett_mpg           = -1;
89
90 static const value_string rtp_mpg_picture_types_vals[] =
91 {
92         { 0, "Forbidden" },
93         { 1, "I-Picture" },
94         { 2, "P-Picture" },
95         { 3, "B-Picture" },
96         { 4, "D-Picture" },
97         { 5, "reserved" },
98         { 6, "reserved" },
99         { 7, "reserved" },
100         { 0, NULL },
101 };
102
103 static void
104 dissect_mpeg1( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
105 {
106         proto_item *ti            = NULL;
107         proto_tree *mpg_tree     = NULL;
108         unsigned int offset       = 0;
109
110         guint8      octet;
111         guint16     word;
112
113
114         guint16     mpg_mbz;
115         guint16     mpg_T;
116         guint16     mpg_tr;
117         guint16     mpg_an;
118         guint16     mpg_n;
119         gboolean    mpg_s;
120         gboolean    mpg_b;
121         gboolean    mpg_e;
122         guint16     mpg_p;
123         guint16     mpg_fbv;
124         guint16     mpg_bfc;
125         guint16     mpg_ffv;
126         guint16     mpg_ffc;
127
128         if ( check_col( pinfo->cinfo, COL_PROTOCOL ) )
129           {
130             col_set_str( pinfo->cinfo, COL_PROTOCOL, "MPEG-1" );
131           }
132
133         if ( check_col( pinfo->cinfo, COL_INFO) )
134           {
135             col_set_str( pinfo->cinfo, COL_INFO, "MPEG-1 message");
136           }
137
138         /* Get MPEG-1  fields */
139
140         word  =   tvb_get_guint8( tvb, offset  );
141         word  = (word << 8) | tvb_get_guint8( tvb, offset +1 );
142         mpg_mbz = RTP_MPG_MBZ(word);
143         mpg_T   = RTP_MPG_T(word);
144         mpg_tr  = RTP_MPG_TR(word);
145
146         octet = tvb_get_guint8( tvb, offset + 2 );
147         mpg_an  = RTP_MPG_AN(octet);
148         mpg_n   = RTP_MPG_N(octet);
149         mpg_s   = RTP_MPG_S(octet);
150         mpg_b   = RTP_MPG_B(octet);
151         mpg_e   = RTP_MPG_E(octet);
152         mpg_p   = RTP_MPG_P(octet);
153
154         octet = tvb_get_guint8( tvb, offset + 3 );
155
156         mpg_fbv   = RTP_MPG_FBV(octet);
157         mpg_bfc   = RTP_MPG_BFC(octet);
158         mpg_ffv   = RTP_MPG_FFV(octet);
159         mpg_ffc   = RTP_MPG_FFC(octet);
160
161
162         if ( tree )
163           {
164             ti = proto_tree_add_item( tree, proto_mpg, tvb, offset, -1, FALSE );
165             mpg_tree = proto_item_add_subtree( ti, ett_mpg );
166
167             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_mbz, tvb, offset, 1, mpg_mbz );
168             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_T  , tvb, offset, 1, mpg_T );
169             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_tr , tvb, offset, 2, mpg_tr );
170             offset += 2;
171             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_an, tvb, offset, 1, mpg_an );
172             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_n , tvb, offset, 1, mpg_n );
173             proto_tree_add_boolean( mpg_tree, hf_rtp_mpg_s , tvb, offset, 1, mpg_s );
174             proto_tree_add_boolean( mpg_tree, hf_rtp_mpg_b , tvb, offset, 1, mpg_b );
175             proto_tree_add_boolean( mpg_tree, hf_rtp_mpg_e , tvb, offset, 1, mpg_e );
176
177             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_p, tvb , offset, 1, mpg_p );
178             offset += 1;
179
180             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_fbv, tvb, offset, 1, mpg_fbv );
181             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_bfc, tvb, offset, 1, mpg_bfc );
182             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_ffv, tvb, offset, 1, mpg_ffv );
183             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_ffc, tvb, offset, 1, mpg_ffc );
184             offset += 1;
185
186             /* The rest of the packet is the MPEG-1 stream */
187             proto_tree_add_item( mpg_tree, hf_rtp_mpg_data, tvb, offset, -1, FALSE );
188
189           }
190 }
191
192 void
193 proto_register_mpeg1(void)
194 {
195         static hf_register_info hf[] =
196         {
197                 {
198                         &hf_rtp_mpg_mbz,
199                         {
200                                 "MBZ",
201                                 "rtp.payload_mpeg_mbz",
202                                 FT_UINT16,
203                                 BASE_DEC,
204                                 NULL,
205                                 0x0,
206                                 "", HFILL
207                         }
208                 },
209                 {
210                         &hf_rtp_mpg_T,
211                         {
212                                 "T",
213                                 "rtp.payload_mpeg_T",
214                                 FT_UINT16,
215                                 BASE_DEC,
216                                 NULL,
217                                 0x0,
218                                 "", HFILL
219                         }
220                 },
221                 {
222                         &hf_rtp_mpg_tr,
223                         {
224                                 "Temporal Reference",
225                                 "rtp.payload_mpeg_tr",
226                                 FT_UINT16,
227                                 BASE_DEC,
228                                 NULL,
229                                 0x0,
230                                 "", HFILL
231                         }
232                 },
233                 {
234                         &hf_rtp_mpg_an,
235                         {
236                                 "AN",
237                                 "rtp.payload_mpeg_an",
238                                 FT_UINT16,
239                                 BASE_DEC,
240                                 NULL,
241                                 0x0,
242                                 "", HFILL
243                         }
244                 },
245
246                 {
247                         &hf_rtp_mpg_n,
248                         {
249                                 "New Picture Header",
250                                 "rtp.payload_mpeg_n",
251                                 FT_UINT16,
252                                 BASE_DEC,
253                                 NULL,
254                                 0x0,
255                                 "", HFILL
256                         }
257                 },
258
259                 {
260                         &hf_rtp_mpg_s,
261                         {
262                                 "Sequence Header",
263                                 "rtp.payload_mpeg_s",
264                                 FT_BOOLEAN,
265                                 BASE_DEC,
266                                 NULL,
267                                 0x0,
268                                 "", HFILL
269                         }
270                 },
271
272                 {
273                         &hf_rtp_mpg_b,
274                         {
275                                 "Beginning-of-slice",
276                                 "rtp.payload_mpeg_b",
277                                 FT_BOOLEAN,
278                                 BASE_DEC,
279                                 NULL,
280                                 0x0,
281                                 "", HFILL
282                         }
283                 },
284
285                 {
286                         &hf_rtp_mpg_e,
287                         {
288                                 "End-of-slice",
289                                 "rtp.payload_mpeg_an",
290                                 FT_BOOLEAN,
291                                 BASE_DEC,
292                                 NULL,
293                                 0x0,
294                                 "", HFILL
295                         }
296                 },
297
298                 {
299                         &hf_rtp_mpg_p,
300                         {
301                                 "Picture type",
302                                 "rtp.payload_mpeg_p",
303                                 FT_UINT16,
304                                 BASE_DEC,
305                                 VALS(rtp_mpg_picture_types_vals),
306                                 0x0,
307                                 "", HFILL
308                         }
309                 },
310
311                 {
312                         &hf_rtp_mpg_fbv,
313                         {
314                                 "FBV",
315                                 "rtp.payload_mpeg_fbv",
316                                 FT_UINT16,
317                                 BASE_DEC,
318                                 NULL,
319                                 0x0,
320                                 "", HFILL
321                         }
322                 },
323
324                 {
325                         &hf_rtp_mpg_bfc,
326                         {
327                                 "BFC",
328                                 "rtp.payload_mpeg_bfc",
329                                 FT_UINT16,
330                                 BASE_DEC,
331                                 NULL,
332                                 0x0,
333                                 "", HFILL
334                         }
335                 },
336                 {
337                         &hf_rtp_mpg_ffv,
338                         {
339                                 "FFV",
340                                 "rtp.payload_mpeg_ffv",
341                                 FT_UINT16,
342                                 BASE_DEC,
343                                 NULL,
344                                 0x0,
345                                 "", HFILL
346                         }
347                 },
348
349                 {
350                         &hf_rtp_mpg_ffc,
351                         {
352                                 "FFC",
353                                 "rtp.payload_mpeg_ffc",
354                                 FT_UINT16,
355                                 BASE_DEC,
356                                 NULL,
357                                 0x0,
358                                 "", HFILL
359                         }
360                 },
361                 {
362                         &hf_rtp_mpg_data,
363                         {
364                                 "MPEG-1 stream",
365                                 "mpeg1.stream",
366                                 FT_BYTES,
367                                 BASE_NONE,
368                                 NULL,
369                                 0x0,
370                                 "", HFILL
371                         }
372                 },
373
374         };
375
376         static gint *ett[] =
377         {
378                 &ett_mpg,
379         };
380
381
382         proto_mpg = proto_register_protocol("RFC 2250 MPEG1","MPEG1","mpeg1");
383         proto_register_field_array(proto_mpg, hf, array_length(hf));
384         proto_register_subtree_array(ett, array_length(ett));
385 }
386
387 void
388 proto_reg_handoff_mpeg1(void)
389 {
390         dissector_handle_t mpeg1_handle;
391
392         mpeg1_handle = create_dissector_handle(dissect_mpeg1, proto_mpg);
393         dissector_add("rtp.pt", PT_MPV, mpeg1_handle);
394 }