* Prefer col_append_str instead of col_append_fstr for constant strings
[metze/wireshark/wip.git] / epan / dissectors / packet-h263p.c
1 /* packet-h263p.c
2  *
3  * Routines for RFC-4629-encapsulated H.263 dissection
4  *
5  * Copyright 2003 Niklas Ogren <niklas.ogren@7l.se>
6  * Seven Levels Consultants AB
7  *
8  * Copyright 2008 Richard van der Hoff, MX Telecom
9  * <richardv@mxtelecom.com>
10  *
11  * $Id$
12  *
13  * Wireshark - Network traffic analyzer
14  * By Gerald Combs <gerald@wireshark.org>
15  * Copyright 1998 Gerald Combs
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License
19  * as published by the Free Software Foundation; either version 2
20  * of the License, or (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <glib.h>
37 #include <epan/packet.h>
38
39 #include <stdio.h>
40 #include <string.h>
41
42 #include <epan/prefs.h>
43
44 #include "packet-h263.h"
45
46 static int proto_h263P                  = -1;
47
48 /* H.263 RFC 4629 fields */
49 static int hf_h263P_payload = -1;
50 static int hf_h263P_rr = -1;
51 static int hf_h263P_pbit = -1;
52 static int hf_h263P_vbit = -1;
53 static int hf_h263P_plen = -1;
54 static int hf_h263P_pebit = -1;
55 static int hf_h263P_tid = -1;
56 static int hf_h263P_trun = -1;
57 static int hf_h263P_s = -1;
58 static int hf_h263P_extra_hdr = -1;
59 static int hf_h263P_PSC = -1;
60 static int hf_h263P_TR = -1;
61
62
63 /* H.263-1998 fields defining a sub tree */
64 static gint ett_h263P                   = -1;
65 static gint ett_h263P_extra_hdr = -1;
66 static gint ett_h263P_payload   = -1;
67 static gint ett_h263P_data = -1;
68
69 /* The dynamic payload type which will be dissected as H.263-1998/H263-2000 */
70
71 static guint temp_dynamic_payload_type = 0;
72
73 /* RFC 4629 */
74 static void
75 dissect_h263P( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
76 {
77         proto_item *ti                                  = NULL;
78         proto_item *data_item                   = NULL;
79         proto_item *extra_hdr_item              = NULL;
80         proto_tree *h263P_tree                  = NULL;
81         proto_tree *h263P_extr_hdr_tree = NULL;
82         proto_tree *h263P_data_tree             = NULL;
83         unsigned int offset                             = 0;
84         guint16 data16, plen;
85         guint8 startcode;
86
87         /*
88         tvbuff_t *next_tvb;
89         */
90
91         col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.263 RFC4629 ");
92
93         if ( tree ) {
94           ti = proto_tree_add_item( tree, proto_h263P, tvb, offset, -1, FALSE );
95           h263P_tree = proto_item_add_subtree( ti, ett_h263P );
96           
97           data16 = tvb_get_ntohs(tvb,offset);
98           proto_tree_add_item( h263P_tree, hf_h263P_rr, tvb, offset, 2, FALSE );
99           proto_tree_add_item( h263P_tree, hf_h263P_pbit, tvb, offset, 2, FALSE );
100           proto_tree_add_item( h263P_tree, hf_h263P_vbit, tvb, offset, 2, FALSE );
101           proto_tree_add_item( h263P_tree, hf_h263P_plen, tvb, offset, 2, FALSE );
102           proto_tree_add_item( h263P_tree, hf_h263P_pebit, tvb, offset, 2, FALSE );
103           offset = offset +2;
104           /*
105            *   V: 1 bit
106            *
107            *      Indicates the presence of an 8-bit field containing information
108            *      for Video Redundancy Coding (VRC), which follows immediately after
109            *      the initial 16 bits of the payload header, if present.  For syntax
110            *      and semantics of that 8-bit VRC field, see Section 5.2.
111            */
112
113           if ((data16&0x0200)==0x0200){
114                   /* V bit = 1 
115                    *   The format of the VRC header extension is as follows:
116                    *
117                    *         0 1 2 3 4 5 6 7
118                    *        +-+-+-+-+-+-+-+-+
119                    *        | TID | Trun  |S|
120                    *        +-+-+-+-+-+-+-+-+
121                    *
122                    *   TID: 3 bits
123                    *
124                    *   Thread ID.  Up to 7 threads are allowed.  Each frame of H.263+ VRC
125                    *   data will use as reference information only sync frames or frames
126                    *   within the same thread.  By convention, thread 0 is expected to be
127                    *   the "canonical" thread, which is the thread from which the sync frame
128                    *   should ideally be used.  In the case of corruption or loss of the
129                    *   thread 0 representation, a representation of the sync frame with a
130                    *   higher thread number can be used by the decoder.  Lower thread
131                    *   numbers are expected to contain representations of the sync frames
132                    *   equal to or better than higher thread numbers in the absence of data
133                    *   corruption or loss.  See [Vredun] for a detailed discussion of VRC.
134                    *
135                    *   Trun: 4 bits
136                    *
137                    *   Monotonically increasing (modulo 16) 4-bit number counting the packet
138                    *   number within each thread.
139                    *
140                    *   S: 1 bit
141                    *
142                    *   A bit that indicates that the packet content is for a sync frame.  
143                    *   :
144                    */
145                   proto_tree_add_item( h263P_tree, hf_h263P_tid, tvb, offset, 1, FALSE );
146                   proto_tree_add_item( h263P_tree, hf_h263P_trun, tvb, offset, 1, FALSE );
147                   proto_tree_add_item( h263P_tree, hf_h263P_s, tvb, offset, 1, FALSE );
148                   offset++;
149           }
150
151           /* Length, in bytes, of the extra picture header. */
152           plen = (data16 & 0x01f8) >> 3;
153           if (plen != 0){
154                   extra_hdr_item = proto_tree_add_item( h263P_tree, hf_h263P_extra_hdr, tvb, offset, plen, FALSE );
155                   h263P_extr_hdr_tree = proto_item_add_subtree( extra_hdr_item, ett_h263P_extra_hdr );
156                   dissect_h263_picture_layer( tvb, pinfo, h263P_extr_hdr_tree, offset, plen, TRUE);
157                   offset += plen;               
158           }
159           if ((data16&0x0400)!=0){
160                   /* P bit = 1 */
161                   data_item = proto_tree_add_item( h263P_tree, hf_h263P_payload, tvb, offset, -1, FALSE );
162                   h263P_data_tree = proto_item_add_subtree( data_item, ett_h263P_data );
163                   /* Startc code holds bit 17 -23 of the codeword */
164                   startcode = tvb_get_guint8(tvb,offset)&0xfe;
165                   if (startcode & 0x80){
166                           /* All picture, slice, and EOSBS start codes
167                            * shall be byte aligned, and GOB and EOS start codes may be byte aligned.
168                            */
169                           switch(startcode){
170                           case 0xf8:
171                                   /* End Of Sub-Bitstream code (EOSBS) 
172                                    * EOSBS codes shall be byte aligned
173                                    * ( 1111 100. )
174                                    */
175                                   break;
176                           case 0x80:
177                           case 0x82:
178                                   /* Picture Start Code (PSC)
179                                    * ( 1000 00x.)
180                                    */
181                                   col_append_str( pinfo->cinfo, COL_INFO, "(PSC) ");
182                                   offset = dissect_h263_picture_layer( tvb, pinfo, h263P_data_tree, offset, -1, TRUE);
183                                   break;
184                           case 0xfc:
185                           case 0xfe:
186                                   /* End Of Sequence (EOS)
187                                    * ( 1111 11x. )
188                                    */
189                           default:
190                                   /* Group of Block Start Code (GBSC) or
191                                    * Slice Start Code (SSC)
192                                    */
193                                   col_append_str( pinfo->cinfo, COL_INFO, "(GBSC) ");
194                                   dissect_h263_group_of_blocks_layer( tvb, h263P_data_tree, offset,TRUE);
195                                   break;
196                           }
197                   }else{
198                           /* Error */
199                   }
200                   return;
201           }
202           proto_tree_add_item( h263P_tree, hf_h263P_payload, tvb, offset, -1, FALSE );
203         }
204 }
205
206 void
207 proto_reg_handoff_h263P(void)
208 {
209         static dissector_handle_t h263P_handle;
210         static guint dynamic_payload_type;
211         static gboolean h263P_prefs_initialized = FALSE;
212
213         if (!h263P_prefs_initialized) {
214                 h263P_handle = find_dissector("h263P");
215                 dissector_add_string("rtp_dyn_payload_type","H263-1998", h263P_handle);
216                 dissector_add_string("rtp_dyn_payload_type","H263-2000", h263P_handle);
217                 h263P_prefs_initialized = TRUE;
218           }
219         else {
220                 if ( dynamic_payload_type > 95 )
221                         dissector_delete("rtp.pt", dynamic_payload_type, h263P_handle);
222         }
223         dynamic_payload_type = temp_dynamic_payload_type;
224
225         if ( dynamic_payload_type > 95 ){
226                 dissector_add("rtp.pt", dynamic_payload_type, h263P_handle);
227         }
228 }
229
230
231 void
232 proto_register_h263P(void)
233 {
234         module_t *h263P_module;
235
236         static hf_register_info hf[] =
237         {
238                 {
239                         &hf_h263P_payload,
240                         {
241                                 "H.263 RFC4629 payload",
242                                 "h263P.payload",
243                                 FT_NONE,
244                                 BASE_NONE,
245                                 NULL,
246                                 0x0,
247                                 "The actual H.263 RFC4629 data", HFILL
248                         }
249                 },
250                 {
251                         &hf_h263P_rr,
252                         {
253                                 "Reserved",
254                                 "h263P.rr",
255                                 FT_UINT16,
256                                 BASE_DEC,
257                                 NULL,
258                                 0xf800,
259                                 "Reserved SHALL be zero", HFILL
260                         }
261                 },
262                 {
263                         &hf_h263P_pbit,
264                         {
265                                 "P",
266                                 "h263P.p",
267                                 FT_BOOLEAN,
268                                 16,
269                                 NULL,
270                                 0x0400,
271                                 "Indicates (GOB/Slice) start or (EOS or EOSBS)", HFILL
272                         }
273                 },
274                 {
275                         &hf_h263P_vbit,
276                         {
277                                 "V",
278                                 "h263P.v",
279                                 FT_BOOLEAN,
280                                 16,
281                                 NULL,
282                                 0x0200,
283                                 "presence of Video Redundancy Coding (VRC) field", HFILL
284                         }
285                 },
286                 {
287                         &hf_h263P_plen,
288                         {
289                                 "PLEN",
290                                 "h263P.plen",
291                                 FT_UINT16,
292                                 BASE_DEC,
293                                 NULL,
294                                 0x01f8,
295                                 "Length, in bytes, of the extra picture header", HFILL
296                         }
297                 },
298                 {
299                         &hf_h263P_pebit,
300                         {
301                                 "PEBIT",
302                                 "h263P.pebit",
303                                 FT_UINT16,
304                                 BASE_DEC,
305                                 NULL,
306                                 0x0003,
307                                 "number of bits that shall be ignored in the last byte of the picture header", HFILL
308                         }
309                 },
310
311
312                 {
313                         &hf_h263P_tid,
314                         {
315                                 "Thread ID",
316                                 "h263P.tid",
317                                 FT_UINT8,
318                                 BASE_DEC,
319                                 NULL,
320                                 0xe0,
321                                 NULL, HFILL
322                         }
323                 },
324                 {
325                         &hf_h263P_trun,
326                         {
327                                 "Trun",
328                                 "h263P.trun",
329                                 FT_UINT8,
330                                 BASE_DEC,
331                                 NULL,
332                                 0x1e,
333                                 "Monotonically increasing (modulo 16) 4-bit number counting the packet number within each thread", HFILL
334                         }
335                 },
336                 {
337                         &hf_h263P_s,
338                         {
339                                 "S",
340                                 "h263P.s",
341                                 FT_UINT8,
342                                 BASE_DEC,
343                                 NULL,
344                                 0x01,
345                                 "Indicates that the packet content is for a sync frame", HFILL
346                         }
347                 },
348                 {
349                         &hf_h263P_extra_hdr,
350                         {
351                                 "Extra picture header",
352                                 "h263P.extra_hdr",
353                                 FT_BYTES,
354                                 BASE_NONE,
355                                 NULL,
356                                 0x0,
357                                 NULL, HFILL
358                         }
359                 },
360                 {
361                         &hf_h263P_PSC,
362                         {
363                                 "H.263 PSC",
364                                 "h263P.PSC",
365                                 FT_UINT16,
366                                 BASE_HEX,
367                                 NULL,
368                                 0xfc00,
369                                 "Picture Start Code(PSC)", HFILL
370                         }
371                 },
372                 {
373                         &hf_h263P_TR,
374                         {
375                                 "H.263 Temporal Reference",
376                                 "h263P.tr",
377                                 FT_UINT16,
378                                 BASE_HEX,
379                                 NULL,
380                                 0x03fc,
381                                 "Temporal Reference, TR", HFILL
382                         }
383                 },
384
385         };
386
387         static gint *ett[] =
388         {
389                 &ett_h263P,
390                 &ett_h263P_extra_hdr,
391                 &ett_h263P_payload,
392                 &ett_h263P_data,
393         };
394
395
396         proto_h263P = proto_register_protocol("ITU-T Recommendation H.263 RTP Payload header (RFC4629)",
397             "H263P", "h263p");
398
399         proto_register_field_array(proto_h263P, hf, array_length(hf));
400         proto_register_subtree_array(ett, array_length(ett));
401
402         h263P_module = prefs_register_protocol(proto_h263P, proto_reg_handoff_h263P);
403
404         prefs_register_uint_preference(h263P_module, "dynamic.payload.type",
405                                                      "H263-1998 and H263-2000 dynamic payload type",
406                                                      "The dynamic payload type which will be interpreted as H264"
407                                                      "; The value must be greater than 95",
408                                                      10,
409                                                      &temp_dynamic_payload_type);
410
411         register_dissector("h263P", dissect_h263P, proto_h263P);
412
413 }