From Ronnie Sahlberg:
[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.6 2002/01/24 09:20:49 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  * This dissector is called by the RTP dissector
33  */
34
35
36 #ifdef HAVE_CONFIG_H
37 # include "config.h"
38 #endif
39
40 #include <glib.h>
41 #include <epan/packet.h>
42
43 #ifdef HAVE_SYS_TYPES_H
44 #  include <sys/types.h>
45 #endif
46
47 #ifdef HAVE_NETINET_IN_H
48 #  include <netinet/in.h>
49 #endif
50
51 #include <stdio.h>
52 #include <string.h>
53
54 #define RTP_MPG_MBZ(word) ( word >> 11)
55 #define RTP_MPG_T(word)   ( (word >> 10) & 1 )
56 #define RTP_MPG_TR(word)   ( word & 0x3ff )
57
58 #define RTP_MPG_AN(octet) ( octet >> 7)
59 #define RTP_MPG_N(octet)  ( (octet >> 6) & 1 )
60 #define RTP_MPG_S(octet)  ( (octet >> 5) & 1 )
61 #define RTP_MPG_B(octet)  ( (octet >> 4) & 1 )
62 #define RTP_MPG_E(octet)  ( (octet >> 3) & 1 )
63 #define RTP_MPG_P(octet)  ( octet & 7 )
64
65 #define RTP_MPG_FBV(octet) ( (octet >> 7) & 1 )
66 #define RTP_MPG_BFC(octet) ( (octet >> 4) & 7 )
67 #define RTP_MPG_FFV(octet) ( (octet >> 3) & 1 )
68 #define RTP_MPG_FFC(octet) (  octet & 7 )
69
70
71 /* MPEG1 header fields             */
72
73
74 static int proto_mpg          = -1;
75
76 static int hf_rtp_mpg_mbz     = -1;
77 static int hf_rtp_mpg_T       = -1;
78 static int hf_rtp_mpg_tr      = -1;
79 static int hf_rtp_mpg_an      = -1;
80 static int hf_rtp_mpg_n       = -1;
81 static int hf_rtp_mpg_s       = -1;
82 static int hf_rtp_mpg_b       = -1;
83 static int hf_rtp_mpg_e       = -1;
84 static int hf_rtp_mpg_p       = -1;
85
86
87 static int hf_rtp_mpg_fbv     = -1;
88 static int hf_rtp_mpg_bfc     = -1;
89 static int hf_rtp_mpg_ffv     = -1;
90 static int hf_rtp_mpg_ffc     = -1;
91 static int hf_rtp_mpg_data    = -1;
92
93
94
95 /* MPEG-1 fields defining a sub tree */
96 static gint ett_mpg           = -1;
97
98 static const value_string rtp_mpg_picture_types_vals[] = 
99 {
100         { 0, "Forbidden" },
101         { 1, "I-Picture" },
102         { 2, "P-Picture" },
103         { 3, "B-Picture" },
104         { 4, "D-Picture" },
105         { 5, "reserved" },
106         { 6, "reserved" },
107         { 7, "reserved" },
108         { 0, NULL },
109 };
110
111 static void
112 dissect_mpeg1( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
113 {
114         proto_item *ti            = NULL;
115         proto_tree *mpg_tree     = NULL;
116         unsigned int offset       = 0;
117
118         guint8      octet;
119         guint16     word;
120         
121         
122         guint16     mpg_mbz;
123         guint16     mpg_T;
124         guint16     mpg_tr;  
125         guint16     mpg_an;
126         guint16     mpg_n;
127         gboolean    mpg_s;  
128         gboolean    mpg_b;
129         gboolean    mpg_e;
130         guint16     mpg_p;  
131         guint16     mpg_fbv;
132         guint16     mpg_bfc;
133         guint16     mpg_ffv;
134         guint16     mpg_ffc;    
135         
136         if ( check_col( pinfo->cinfo, COL_PROTOCOL ) )   
137           {
138             col_set_str( pinfo->cinfo, COL_PROTOCOL, "MPEG-1" );
139           }
140         
141         if ( check_col( pinfo->cinfo, COL_INFO) ) 
142           {
143             col_set_str( pinfo->cinfo, COL_INFO, "MPEG-1 message");
144           }
145         
146         /* Get MPEG-1  fields */
147         
148         word  =   tvb_get_guint8( tvb, offset  );
149         word  = (word << 8) | tvb_get_guint8( tvb, offset +1 );
150         mpg_mbz = RTP_MPG_MBZ(word);
151         mpg_T   = RTP_MPG_T(word);
152         mpg_tr  = RTP_MPG_TR(word);
153         
154         octet = tvb_get_guint8( tvb, offset + 2 );
155         mpg_an  = RTP_MPG_AN(octet);
156         mpg_n   = RTP_MPG_N(octet);
157         mpg_s   = RTP_MPG_S(octet);
158         mpg_b   = RTP_MPG_B(octet);
159         mpg_e   = RTP_MPG_E(octet);
160         mpg_p   = RTP_MPG_P(octet);
161         
162         octet = tvb_get_guint8( tvb, offset + 3 );
163         
164         mpg_fbv   = RTP_MPG_FBV(octet);
165         mpg_bfc   = RTP_MPG_BFC(octet);
166         mpg_ffv   = RTP_MPG_FFV(octet);
167         mpg_ffc   = RTP_MPG_FFC(octet);         
168
169         
170         if ( tree ) 
171           {
172             ti = proto_tree_add_item( tree, proto_mpg, tvb, offset, -1, FALSE );
173             mpg_tree = proto_item_add_subtree( ti, ett_mpg );
174             
175             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_mbz, tvb, offset, 1, mpg_mbz );
176             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_T  , tvb, offset, 1, mpg_T );
177             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_tr , tvb, offset, 2, mpg_tr );
178             offset += 2;
179             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_an, tvb, offset, 1, mpg_an );
180             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_n , tvb, offset, 1, mpg_n );
181             proto_tree_add_boolean( mpg_tree, hf_rtp_mpg_s , tvb, offset, 1, mpg_s );
182             proto_tree_add_boolean( mpg_tree, hf_rtp_mpg_b , tvb, offset, 1, mpg_b );
183             proto_tree_add_boolean( mpg_tree, hf_rtp_mpg_e , tvb, offset, 1, mpg_e );
184             
185             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_p, tvb , offset, 1, mpg_p );
186             offset += 1;
187             
188             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_fbv, tvb, offset, 1, mpg_fbv );
189             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_bfc, tvb, offset, 1, mpg_bfc );
190             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_ffv, tvb, offset, 1, mpg_ffv );
191             proto_tree_add_uint( mpg_tree, hf_rtp_mpg_ffc, tvb, offset, 1, mpg_ffc );
192             offset += 1;
193           
194             /* The rest of the packet is the MPEG-1 stream */
195             proto_tree_add_item( mpg_tree, hf_rtp_mpg_data, tvb, offset, tvb_length_remaining( tvb, offset ), FALSE );
196
197           }
198 }
199
200 void
201 proto_register_mpeg1(void)
202 {
203         static hf_register_info hf[] = 
204         {
205                 { 
206                         &hf_rtp_mpg_mbz,
207                         { 
208                                 "MBZ", 
209                                 "rtp.payload_mpeg_mbz", 
210                                 FT_UINT16, 
211                                 BASE_DEC, 
212                                 NULL, 
213                                 0x0,
214                                 "", HFILL 
215                         }
216                 },
217                 { 
218                         &hf_rtp_mpg_T,
219                         { 
220                                 "T", 
221                                 "rtp.payload_mpeg_T", 
222                                 FT_UINT16, 
223                                 BASE_DEC, 
224                                 NULL, 
225                                 0x0,
226                                 "", HFILL 
227                         }
228                 },
229                 { 
230                         &hf_rtp_mpg_tr,
231                         { 
232                                 "Temporal Reference", 
233                                 "rtp.payload_mpeg_tr", 
234                                 FT_UINT16, 
235                                 BASE_DEC, 
236                                 NULL, 
237                                 0x0,
238                                 "", HFILL 
239                         }
240                 },
241                 { 
242                         &hf_rtp_mpg_an,
243                         { 
244                                 "AN", 
245                                 "rtp.payload_mpeg_an", 
246                                 FT_UINT16, 
247                                 BASE_DEC, 
248                                 NULL, 
249                                 0x0,
250                                 "", HFILL 
251                         }
252                 },
253
254                 { 
255                         &hf_rtp_mpg_n,
256                         { 
257                                 "New Picture Header", 
258                                 "rtp.payload_mpeg_n", 
259                                 FT_UINT16, 
260                                 BASE_DEC, 
261                                 NULL, 
262                                 0x0,
263                                 "", HFILL 
264                         }
265                 },
266
267                 { 
268                         &hf_rtp_mpg_s,
269                         { 
270                                 "Sequence Header", 
271                                 "rtp.payload_mpeg_s", 
272                                 FT_BOOLEAN, 
273                                 BASE_DEC, 
274                                 NULL, 
275                                 0x0,
276                                 "", HFILL 
277                         }
278                 },
279
280                 { 
281                         &hf_rtp_mpg_b,
282                         { 
283                                 "Beginning-of-slice", 
284                                 "rtp.payload_mpeg_b", 
285                                 FT_BOOLEAN, 
286                                 BASE_DEC, 
287                                 NULL, 
288                                 0x0,
289                                 "", HFILL 
290                         }
291                 },
292
293                 { 
294                         &hf_rtp_mpg_e,
295                         { 
296                                 "End-of-slice", 
297                                 "rtp.payload_mpeg_an", 
298                                 FT_BOOLEAN, 
299                                 BASE_DEC, 
300                                 NULL, 
301                                 0x0,
302                                 "", HFILL 
303                         }
304                 },
305
306                 { 
307                         &hf_rtp_mpg_p,
308                         { 
309                                 "Picture type", 
310                                 "rtp.payload_mpeg_p", 
311                                 FT_UINT16, 
312                                 BASE_DEC, 
313                                 VALS(rtp_mpg_picture_types_vals), 
314                                 0x0,
315                                 "", HFILL 
316                         }
317                 },
318
319                 { 
320                         &hf_rtp_mpg_fbv,
321                         { 
322                                 "FBV", 
323                                 "rtp.payload_mpeg_fbv", 
324                                 FT_UINT16, 
325                                 BASE_DEC, 
326                                 NULL, 
327                                 0x0,
328                                 "", HFILL 
329                         }
330                 },
331
332                 { 
333                         &hf_rtp_mpg_bfc,
334                         { 
335                                 "BFC", 
336                                 "rtp.payload_mpeg_bfc", 
337                                 FT_UINT16, 
338                                 BASE_DEC, 
339                                 NULL, 
340                                 0x0,
341                                 "", HFILL 
342                         }
343                 },
344                 { 
345                         &hf_rtp_mpg_ffv,
346                         { 
347                                 "FFV", 
348                                 "rtp.payload_mpeg_ffv", 
349                                 FT_UINT16, 
350                                 BASE_DEC, 
351                                 NULL, 
352                                 0x0,
353                                 "", HFILL 
354                         }
355                 },
356  
357                 { 
358                         &hf_rtp_mpg_ffc,
359                         { 
360                                 "FFC", 
361                                 "rtp.payload_mpeg_ffc", 
362                                 FT_UINT16, 
363                                 BASE_DEC, 
364                                 NULL, 
365                                 0x0,
366                                 "", HFILL 
367                         }
368                 },
369                 { 
370                         &hf_rtp_mpg_data,
371                         { 
372                                 "MPEG-1 stream", 
373                                 "mpeg1.stream", 
374                                 FT_BYTES, 
375                                 BASE_NONE, 
376                                 NULL, 
377                                 0x0,
378                                 "", HFILL 
379                         }
380                 },
381
382         };
383         
384         static gint *ett[] = 
385         {
386                 &ett_mpg,
387         };
388
389
390         proto_mpg = proto_register_protocol("RFC 2250 MPEG1","MPEG1","mpeg1");
391         proto_register_field_array(proto_mpg, hf, array_length(hf));
392         proto_register_subtree_array(ett, array_length(ett));
393
394         register_dissector("mpeg1", dissect_mpeg1, proto_mpg);
395 }