241af0d34251c0aab6153a52ce6d823ded00dd74
[obnox/wireshark/wip.git] / epan / dissectors / packet-mp4ves.c
1 /*
2  * packet-mp4ves.c
3  * Routines for MPEG4 dissection
4  * Copyright 2007-2008, Anders Broman <anders.broman[at]ericsson.com>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  * 
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  *
26  * References:
27  * http://www.ietf.org/rfc/rfc3016.txt?number=3016
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include <glib.h>
39
40 #include <epan/packet.h>
41 #include <epan/proto.h>
42 #include <epan/asn1.h>
43
44 #include "prefs.h"
45
46 /* Initialize the protocol and registered fields */
47 static int proto_mp4ves                                                         = -1;
48
49 static int hf_mp4ves_config = -1;
50 static int hf_mp4ves_start_code_prefix = -1;
51 static int hf_mp4ves_start_code = -1;
52 static int hf_mp4ves_vop_coding_type = -1;
53 static int hf_mp4ves_profile_and_level_indication = -1;
54 static int hf_mp4ves_is_visual_object_identifier = -1;
55 static int hf_mp4ves_visual_object_type = -1;
56 static int hf_mp4ves_video_signal_type = -1;
57 static int hf_mp4ves_stuffing = -1;
58 static int hf_mp4ves_video_object_type_indication = -1;
59 static int hf_mp4ves_random_accessible_vol = -1;
60 static int hf_mp4ves_is_object_layer_identifier = -1;
61 static int hf_mp4ves_aspect_ratio_info = -1;
62 static int hf_mp4ves_vol_control_parameters = -1;
63 static int hf_mp4ves_video_object_layer_shape = -1;
64
65 /* Initialize the subtree pointers */
66 static int ett_mp4ves = -1;
67 static int ett_mp4ves_config = -1;
68
69 /* The dynamic payload type which will be dissected as MP4V-ES */
70
71 static guint global_dynamic_payload_type = 0;
72
73
74 /*
75 14496-2, Annex G, Table G-1.
76 Table G-1 FLC table for profile_and_level_indication Profile/Level Code
77 */
78 const value_string mp4ves_level_indication_vals[] =
79 {
80         { 0,    "Reserved" },
81         { 1,    "Simple Profile/Level 1" },
82         { 2,    "Simple Profile/Level 2" },
83         { 3,    "Reserved" },
84         { 4,    "Reserved" },
85         { 5,    "Reserved" },
86         { 6,    "Reserved" },
87         { 7,    "Reserved" },
88         { 8,    "Simple Profile/Level 0" },
89         { 9,    "Simple Profile/Level 0b" },
90         /* Reserved 00001001 - 00010000 */
91         { 0x11, "Simple Scalable Profile/Level 1" },
92         { 0x12, "Simple Scalable Profile/Level 2" },
93         /* Reserved 00010011 - 00100000 */
94         { 0x21, "Core Profile/Level 1" },
95         { 0x22, "Core Profile/Level 2" },
96         /* Reserved 00100011 - 00110001 */
97         { 0x32, "Main Profile/Level 2" },
98         { 0x33, "Main Profile/Level 3" },
99         { 0x34, "Main Profile/Level 4" },
100         /* Reserved 00110101 - 01000001  */
101         { 0x42, "N-bit Profile/Level 2" },
102         /* Reserved 01000011 - 01010000  */
103         { 0x51, "Scalable Texture Profile/Level 1" },
104         /* Reserved 01010010 - 01100000 */
105         { 0x61, "Simple Face Animation Profile/Level 1" },
106         { 0x62, "Simple Face Animation Profile/Level 2" },
107         { 0x63, "Simple FBA Profile/Level 1" },
108         { 0x64, "Simple FBA Profile/Level 2" },
109         /* Reserved 01100101 - 01110000 */
110         { 0x71, "Basic Animated Texture Profile/Level 1" },
111         { 0x72, "Basic Animated Texture Profile/Level 2" },
112         /* Reserved 01110011 - 10000000 */
113         { 0x81, "Hybrid Profile/Level 1" },
114         { 0x82, "Hybrid Profile/Level 2" },
115         /* Reserved 10000011 - 10010000 */
116         { 0x91, "Advanced Real Time Simple Profile/Level 1" },
117         { 0x92, "Advanced Real Time Simple Profile/Level 2" },
118         { 0x93, "Advanced Real Time Simple Profile/Level 3" },
119         { 0x94, "Advanced Real Time Simple Profile/Level 4" },
120         /* Reserved 10010101 - 10100000 */
121         { 0xa1, "Core Scalable Profile/Level 1" },
122         { 0xa2, "Core Scalable Profile/Level 2" },
123         { 0xa3, "Core Scalable Profile/Level 3" },
124         /* Reserved 10100100 - 10110000  */
125         { 0xb1, "Advanced Coding Efficiency Profile/Level 1" },
126         { 0xb2, "Advanced Coding Efficiency Profile/Level 2" },
127         { 0xb3, "Advanced Coding Efficiency Profile/Level 3" },
128         { 0xb4, "Advanced Coding Efficiency Profile/Level 4" },
129         /* Reserved 10110101 - 11000000 */
130         { 0xc1, "Advanced Core Profile/Level 1" },
131         { 0xc2, "Advanced Core Profile/Level 2" },
132         /* Reserved 11000011 - 11010000 */
133         { 0xd1, "Advanced Scalable Texture/Level 1" },
134         { 0xd2, "Advanced Scalable Texture/Level 2" },
135         { 0xd3, "Advanced Scalable Texture/Level 3" },
136         /* Reserved 11010100 - 11100000 */
137         { 0xe1, "Simple Studio Profile/Level 1" },
138         { 0xe2, "Simple Studio Profile/Level 2" },
139         { 0xe3, "Simple Studio Profile/Level 3" },
140         { 0xe4, "Simple Studio Profile/Level 4" },
141         { 0xe5, "Core Studio Profile/Level 1" },
142         { 0xe6, "Core Studio Profile/Level 2" },
143         { 0xe7, "Core Studio Profile/Level 3" },
144         { 0xe8, "Core Studio Profile/Level 4" },
145         /* Reserved 11101001 - 11101111 */
146         { 0xf0, "Advanced Simple Profile/Level 0" },
147         { 0xf1, "Advanced Simple Profile/Level 1" },
148         { 0xf2, "Advanced Simple Profile/Level 2" },
149         { 0xf3, "Advanced Simple Profile/Level 3" },
150         { 0xf4, "Advanced Simple Profile/Level 4" },
151         { 0xf5, "Advanced Simple Profile/Level 5" },
152         /* Reserved 11110110 - 11110111 */
153         { 0xf8, "Fine Granularity Scalable Profile/Level 0" },
154         { 0xf9, "Fine Granularity Scalable Profile/Level 1" },
155         { 0xfa, "Fine Granularity Scalable Profile/Level 2" },
156         { 0xfb, "Fine Granularity Scalable Profile/Level 3" },
157         { 0xfc, "Fine Granularity Scalable Profile/Level 4" },
158         { 0xfd, "Fine Granularity Scalable Profile/Level 5" },
159         { 0xfe, "Reserved" },
160         { 0xff, "Reserved for Escape" },
161         { 0, NULL },
162 };
163 static const range_string mp4ves_startcode_vals[] = {
164         { 0x00, 0x1f, "video_object_start_code" },
165         { 0x20, 0x2f, "video_object_layer_start_code" },
166         { 0x30, 0xaf, "reserved" },
167         { 0xb0, 0xb0, "visual_object_sequence_start_code" },
168         { 0xb1, 0xb1, "visual_object_sequence_end_code" },
169         { 0xb2, 0xb2, "user_data_start_code" },
170         { 0xb3, 0xb3, "group_of_vop_start_code" },
171         { 0xb4, 0xb4, "video_session_error_code" },
172         { 0xb5, 0xb5, "visual_object_start_code" },
173         { 0xb6, 0xb6, "vop_start_code" },
174         { 0xb7, 0xb9, "reserved" },
175         { 0xba, 0xba, "fba_object_start_code" },
176         { 0xbb, 0xbb, "fba_object_plane_start_code" },
177         { 0xbc, 0xbc, "mesh_object_start_code" },
178         { 0xbd, 0xbd, "mesh_object_plane_start_code" },
179         { 0xbe, 0xbe, "still_texture_object_start_code" },
180         { 0xbf, 0xbf, "texture_spatial_layer_start_code" },
181         { 0xc0, 0xc0, "texture_snr_layer_start_code" },
182         { 0xc1, 0xc1, "texture_tile_start_code" },
183         { 0xc2, 0xc2, "texture_shape_layer_start_code" },
184         { 0xc3, 0xc3, "stuffing_start_code" },
185         { 0xc4, 0xc5, "reserved" },
186         { 0xc6, 0xcf, "System start codes" }, /* NOTE System start codes are defined in ISO/IEC 14496-1:1999 */
187         { 0,     0, NULL }
188 };
189
190 static const value_string mp4ves_vop_coding_type_vals[] = {
191         { 0,    "intra-coded (I)" },
192         { 1,    "predictive-coded (P)" },
193         { 2,    "bidirectionally-predictive-coded (B)" },
194         { 3,    "sprite (S)" },
195         { 0,    NULL }
196 };
197
198 /* 
199  * FLC table for video_object_type indication
200  */
201 static const value_string mp4ves_video_object_type_vals[] = {
202         { 0x0,  "Reserved" },
203         { 0x1,  "Simple Object Type" },
204         { 0x2,  "Simple Scalable Object Type" },
205         { 0x3,  "Core Object Type" },
206         { 0x4,  "Main Object Type" },
207         { 0x5,  "N-bit Object Type" },
208         { 0x6,  "Basic Anim. 2D Texture" },
209         { 0x7,  "Anim. 2D Mesh" },
210         { 0x8,  "Simple Face" },
211         { 0x9,  "Still Scalable Texture" },
212         { 0xa,  "Advanced Real Time Simple" },
213         { 0xb,  "Core Scalable" },
214         { 0xc,  "Advanced Coding Efficiency" },
215         { 0xd,  "Advanced Scalable Texture" },
216         { 0xe,  "Simple FBA" },
217         { 0,    NULL }
218 };
219 /* Visual object type */
220 static const value_string mp4ves_visual_object_type_vals[] = {
221         { 0x0,  "reserved" },
222         { 0x1,  "video ID" },
223         { 0x2,  "still texture ID" },
224         { 0x3,  "mesh ID" },
225         { 0x4,  "FBA ID" },
226         { 0x5,  "3D mesh ID" },
227         { 0x6,  "reserved" },
228         { 0x7,  "reserved" },
229         { 0x8,  "reserved" },
230         { 0x9,  "reserved" },
231         { 0xa,  "reserved" },
232         { 0xb,  "reserved" },
233         { 0xc,  "reserved" },
234         { 0xd,  "reserved" },
235         { 0xe,  "reserved" },
236         { 0xf,  "reserved" },
237         { 0,    NULL }
238 };
239
240 static const value_string mp4ves_video_object_type_indication_vals[] = {
241         { 0x0,  "Reserved" },
242         { 0x1,  "Simple Object Type" },
243         { 0x2,  "Simple Scalable Object Type" },
244         { 0x3,  "Core Object Type" },
245         { 0x4,  "Main Object Type" },
246         { 0x5,  "N-bit Object Type" },
247         { 0x6,  "Basic Anim. 2D Texture" },
248         { 0x7,  "Anim. 2D Mesh" },
249         { 0x8,  "Simple Face" },
250         { 0x9,  "Still Scalable Texture" },
251         { 0xa,  "Advanced Real Time Simple" },
252         { 0xb,  "Core Scalable" },
253         { 0xc,  "Advanced Coding Efficiency" },
254         { 0xd,  "Advanced Scalable Texture" },
255         { 0xe,  "Simple FBA" },
256         { 0xf,  "Reserved" },
257         /* Reserved 00001111 - 11111111 */
258         { 0,    NULL }
259 };
260 /* 6.2.2.1 User data */
261 static int
262 dissect_mp4ves_user_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int bit_offset)
263 {
264         int start_bit_offset;
265
266         /* user_data_start_code */
267         proto_tree_add_bits_item(tree, hf_mp4ves_start_code_prefix, tvb, bit_offset, 24, FALSE);
268         bit_offset+=24;
269         proto_tree_add_bits_item(tree, hf_mp4ves_start_code, tvb, bit_offset, 8, FALSE);
270         bit_offset+=8;
271         start_bit_offset = bit_offset;
272         /* while( next_bits() != '000 0000 0000 0000 0000 0001') { */
273         while ( tvb_get_bits32(tvb,bit_offset, 24, FALSE) != 1){
274                 bit_offset+=8;
275                 /* user_data 8 bits */
276         }
277         proto_tree_add_text(tree, tvb, start_bit_offset>>3, (bit_offset - start_bit_offset)>>2, "User data");
278
279         return bit_offset;
280 }
281 /*
282 next_start_code() { 
283 zero_bit 
284 while (!bytealigned())
285 one_bit 
286 }
287 */
288 static int
289 dissect_mp4ves_next_start_code(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int bit_offset)
290 {
291         guint8 zero_bit;
292         int start_bit_offset;
293
294         start_bit_offset = bit_offset;
295
296         zero_bit = tvb_get_bits8(tvb,bit_offset,1);
297         if (zero_bit != 0){
298                 /* Error */
299         }
300         bit_offset++;
301         
302         /* zero stuffing bits */
303         if(bit_offset %8 == 0)
304                 return bit_offset;
305
306         while(bit_offset %8 != 0){
307                 bit_offset++;
308         }
309
310         proto_tree_add_bits_item(tree, hf_mp4ves_stuffing, tvb, start_bit_offset, bit_offset-start_bit_offset, FALSE);
311
312         return bit_offset;
313 }
314
315 /*
316 video_signal_type() { 
317         video_signal_type
318         if (video_signal_type) {
319                 video_format 3 uimsbf
320                 video_range 1 bslbf
321                 colour_description 1 bslbf
322                 if (colour_description) {
323                         colour_primaries 8 uimsbf
324                         transfer_characteristics 8 uimsbf
325                         matrix_coefficients 8 uimsbf
326                 }
327         }
328 }
329 */
330 static int
331 dissect_mp4ves_visual_object_type(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int bit_offset)
332 {
333         guint8 video_signal_type, colour_description;
334
335         video_signal_type = tvb_get_bits8(tvb,bit_offset,1);
336         proto_tree_add_bits_item(tree, hf_mp4ves_video_signal_type, tvb, bit_offset, 1, FALSE);
337         bit_offset++;
338         if (video_signal_type) {
339                 /* video_format 3 bits */
340                 bit_offset+=3;
341                 /* video_range 1 bit */
342                 bit_offset++;
343                 /* colour_description 1 bit */
344                 colour_description = tvb_get_bits8(tvb,bit_offset,1);
345                 if (colour_description) {
346                         /* colour_primaries 8 bits */
347                         bit_offset+=8;
348                         /* transfer_characteristics 8 bits */
349                         bit_offset+=8;
350                         /* matrix_coefficients 8 bits*/
351                         bit_offset+=8;
352                 }
353         }
354
355         return bit_offset;
356 }
357 /* 
358  * 6.2.3 Video Object Layer
359  */
360
361 /*
362  * Table 6-12 -- Meaning of pixel aspect ratio
363  */
364
365 static const value_string mp4ves_aspect_ratio_info_vals[] = {
366         { 0x0,  "reserved" },
367         { 0x0,  "Forbidden" },
368         { 0x1,  "1:1 (Square)" },
369         { 0x2,  "12:11 (625-type for 4:3 picture)" },
370         { 0x3,  "10:11 (525-type for 4:3 picture)" },
371         { 0x4,  "16:11 (625-type stretched for 16:9 picture)" },
372         { 0x5,  "40:33 (525-type stretched for 16:9 picture)" },
373         { 0x6,  "Reserved" },
374         { 0x7,  "Reserved" },
375         { 0x8,  "Reserved" },
376         { 0x9,  "Reserved" },
377         { 0xa,  "Reserved" },
378         { 0xb,  "Reserved" },
379         { 0xc,  "Reserved" },
380         { 0xd,  "Reserved" },
381         { 0xe,  "Reserved" },
382         { 0xf,  "Extended PAR" },
383         { 0,    NULL }
384 };
385
386 /* Table 6-14 Video Object Layer shape type */
387 static const value_string mp4ves_video_object_layer_shape_vals[] = {
388         { 0x0,  "rectangular" },
389         { 0x1,  "binary" },
390         { 0x2,  "binary only" },
391         { 0x3,  "grayscale" },
392         { 0,    NULL }
393 };
394
395 static int
396 dissect_mp4ves_VideoObjectLayer(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int bit_offset)
397 {
398         guint32 dword;
399         int current_bit_offset;
400         guint8 octet, is_object_layer_identifier, aspect_ratio_info, vol_control_parameters, vbv_parameters;
401         guint8 video_object_layer_shape, video_object_layer_verid = 0;
402
403         /* if(next_bits() == video_object_layer_start_code) { */
404         dword = tvb_get_bits32(tvb,bit_offset, 24, FALSE);
405         if (dword != 1){
406                 return bit_offset;
407         }
408         octet = tvb_get_bits8(tvb,bit_offset+24, 8);
409         if((octet>=0x20)&&(octet<=0x2f)){
410                 /* Continue */
411         }else{
412                 return bit_offset;
413         }
414         /* video_object_layer_start_code */
415         proto_tree_add_bits_item(tree, hf_mp4ves_start_code_prefix, tvb, bit_offset, 24, FALSE);
416         bit_offset+=24;
417         proto_tree_add_bits_item(tree, hf_mp4ves_start_code, tvb, bit_offset, 8, FALSE);
418         bit_offset+= 8;
419
420         /* short_video_header = 0 */
421         /* random_accessible_vol 1 */
422         proto_tree_add_bits_item(tree, hf_mp4ves_random_accessible_vol, tvb, bit_offset, 1, FALSE);
423         bit_offset++;
424         /* video_object_type_indication 8 */
425         proto_tree_add_bits_item(tree, hf_mp4ves_video_object_type_indication, tvb, bit_offset, 8, FALSE);
426         bit_offset+= 8;
427         /* is_object_layer_identifier 1 */
428         is_object_layer_identifier = tvb_get_bits8(tvb,bit_offset, 1);
429         proto_tree_add_bits_item(tree, hf_mp4ves_is_object_layer_identifier, tvb, bit_offset, 1, FALSE);
430         bit_offset++;
431         if(is_object_layer_identifier) { 
432                 /* video_object_layer_verid 4 uimsbf */
433                 bit_offset+=4;
434                 /* video_object_layer_priority 3 uimsbf */
435                 bit_offset+=3;
436         } 
437         /* aspect_ratio_info 4 uimsbf */
438         aspect_ratio_info = tvb_get_bits8(tvb,bit_offset, 1);
439         proto_tree_add_bits_item(tree, hf_mp4ves_aspect_ratio_info, tvb, bit_offset, 4, FALSE);
440         if (aspect_ratio_info == 0xf /*"extended_PAR"*/ ) {
441                 /* par_width 8 uimsbf */
442                 bit_offset+=8;
443                 /* par_height 8 uimsbf */
444                 bit_offset+=8;
445         }
446         /* vol_control_parameters 1 bslbf */
447         /* vol_control_parameters 1 bslbf */
448         vol_control_parameters = tvb_get_bits8(tvb,bit_offset, 1);
449         proto_tree_add_bits_item(tree, hf_mp4ves_vol_control_parameters, tvb, bit_offset, 1, FALSE);
450         bit_offset++;
451         current_bit_offset = bit_offset;
452         if (vol_control_parameters) { 
453                 /* chroma_format 2 uimsbf */
454                 bit_offset+=2;
455                 /* low_delay 1 uimsbf */
456                 bit_offset++;
457                 /* vbv_parameters 1 blsbf */
458                 vbv_parameters = tvb_get_bits8(tvb,bit_offset, 1);
459                 bit_offset++;
460                 if (vbv_parameters) {
461                         /* first_half_bit_rate 15 uimsbf */
462                         bit_offset+=15;
463                         /* marker_bit 1 bslbf */
464                         bit_offset++;
465                         /* latter_half_bit_rate 15 uimsbf */
466                         bit_offset+=15;
467                         /* marker_bit 1 bslbf */
468                         bit_offset++;
469                         /* first_half_vbv_buffer_size 15 uimsbf */
470                         bit_offset+=15;
471                         /* marker_bit 1 bslbf */
472                         bit_offset++;
473                         /* latter_half_vbv_buffer_size 3 uimsbf */
474                         bit_offset+=3;
475                         /* first_half_vbv_occupancy 11 uimsbf */
476                         bit_offset+=11;
477                         /* marker_bit 1 blsbf */
478                         bit_offset++;
479                         /* latter_half_vbv_occupancy 15 uimsbf */
480                         bit_offset+=15;
481                         /* marker_bit 1 blsbf */
482                         bit_offset++;
483                 }
484         }
485         if(bit_offset-current_bit_offset > 0)
486                 proto_tree_add_text(tree, tvb, current_bit_offset>>3, (bit_offset+7)>>3, "Not dissected bits");
487         /* video_object_layer_shape 2 uimsbf */
488         video_object_layer_shape = tvb_get_bits8(tvb,bit_offset, 2);
489         proto_tree_add_bits_item(tree, hf_mp4ves_video_object_layer_shape, tvb, bit_offset, 2, FALSE);
490         bit_offset+=2;
491         if (video_object_layer_shape == 3/*"grayscale"*/&& video_object_layer_verid != 1){
492                 /* video_object_layer_shape_extension 4 uimsbf */
493                 bit_offset+=4;
494         }
495         /* marker_bit 1 bslbf */
496         bit_offset++;
497         /* vop_time_increment_resolution 16 uimsbf */
498         bit_offset+=16;
499         /* marker_bit 1 bslbf */
500         bit_offset++;
501         /* fixed_vop_rate 1 bslbf */
502         bit_offset++;
503
504
505         return bit_offset;
506 }
507 /* Visual object */
508 /*
509 VisualObject() { 
510         visual_object_start_code
511         is_visual_object_identifier
512         if (is_visual_object_identifier) {
513                 visual_object_verid
514                 visual_object_priority
515         }
516         visual_object_type
517         if (visual_object_type == "Video ID" || visual_object_type == "still textureID") {
518                 video_signal_type()
519         }
520         next_start_code()
521         while ( next_bits()== user_data_start_code){
522                 user_data()
523         }
524         if (visual_object_type == "Video ID") {
525                 video_object_start_code 
526                 VideoObjectLayer()
527         }
528         else if (visual_object_type == "still texture ID") {
529                 StillTextureObject()
530         }
531         else if (visual_object_type == "mesh ID") {
532                 MeshObject()
533         }
534         else if (visual_object_type == "FBA ID") {
535                 FBAObject()
536         }
537         else if (visual_object_type == "3D mesh ID") {
538                 3D_Mesh_Object()
539         }
540         if (next_bits() != "0000 0000 0000 0000 0000 0001")
541                 next_start_code()
542 }
543 */
544 static int
545 dissect_mp4ves_VisualObject(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int bit_offset)
546 {
547         proto_item *item;
548         guint8 is_visual_object_identifier, visual_object_type;
549         guint32 dword;
550         guint8 octet;
551
552         is_visual_object_identifier = tvb_get_bits8(tvb,bit_offset,1);
553         proto_tree_add_bits_item(tree, hf_mp4ves_is_visual_object_identifier, tvb, bit_offset, 1, FALSE);
554         bit_offset++;
555         if(is_visual_object_identifier){
556                 /* visual_object_verid 4 bits*/
557                 bit_offset+=4;
558                 /* visual_object_priority 3 bits*/
559                 bit_offset+=3;
560         }
561         /* visual_object_type 4 bits*/
562         visual_object_type = tvb_get_bits8(tvb,bit_offset,4);
563         proto_tree_add_bits_item(tree, hf_mp4ves_visual_object_type, tvb, bit_offset, 4, FALSE);
564         bit_offset+=4;
565         if ((visual_object_type == 1/*"Video ID"*/) || (visual_object_type == 2/*"still textureID"*/)) {
566                 /* video_signal_type() */
567                 bit_offset = dissect_mp4ves_visual_object_type(tvb, pinfo, tree, bit_offset);
568         }
569         /* next_start_code() */
570         bit_offset = dissect_mp4ves_next_start_code(tvb, pinfo, tree, bit_offset);
571         dword = tvb_get_bits32(tvb,bit_offset, 32, FALSE);
572 /*
573         while ( next_bits()== user_data_start_code){
574                 user_data()
575         }
576 */
577         while(dword==0x1b2){
578                 bit_offset = dissect_mp4ves_user_data(tvb, pinfo, tree, bit_offset);
579                 dword = tvb_get_bits32(tvb,bit_offset, 32, FALSE);
580         }
581         if (visual_object_type == 1/*"Video ID"*/) {
582                 /* 
583                  * video_object_start_code
584                  */ 
585                 dword = tvb_get_bits32(tvb,bit_offset, 24, FALSE);
586                 if (dword != 1){
587                         /* no start code */
588                         return -1;
589                 }
590                 octet = tvb_get_bits8(tvb,bit_offset+24, 8);
591                 if(octet>0x20){
592                         /* Error */
593                         return -1;
594                 }
595                 proto_tree_add_bits_item(tree, hf_mp4ves_start_code_prefix, tvb, bit_offset, 24, FALSE);
596                 bit_offset+=24;
597                 proto_tree_add_bits_item(tree, hf_mp4ves_start_code, tvb, bit_offset, 8, FALSE);
598                 bit_offset+= 8;
599                 if(tvb_length_remaining(tvb,(bit_offset>>3))==0){
600                         item = proto_tree_add_text(tree, tvb, 0, -1, "Config string to short");
601                         PROTO_ITEM_SET_GENERATED(item);
602                         return -1;
603                 }
604                 /*
605                 VideoObjectLayer()
606                 */
607                 bit_offset = dissect_mp4ves_VideoObjectLayer(tvb, pinfo, tree, bit_offset);
608         }
609
610         return bit_offset;
611 }
612
613 static int
614 dissect_mp4ves_VisualObjectSequence(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int bit_offset)
615 {
616         guint32 dword;
617
618         /*VisualObjectSequence() { 
619         do {
620                 visual_object_sequence_start_code 
621         */
622
623         /* Get start code prefix */
624         dword = tvb_get_bits32(tvb,bit_offset, 32, FALSE);
625         if ((dword & 0x00000100) != 0x00000100){
626                 /* No start code prefix */
627                 return -1;
628         }
629         proto_tree_add_bits_item(tree, hf_mp4ves_start_code_prefix, tvb, bit_offset, 24, FALSE);
630         bit_offset+= 24;
631
632         proto_tree_add_bits_item(tree, hf_mp4ves_start_code, tvb, bit_offset, 8, FALSE);
633         bit_offset+= 8;
634
635         /* Expect visual_object_sequence_start_code */
636         if(dword != 0x1b0)
637                 return -1;
638         /*      profile_and_level_indication */
639         proto_tree_add_bits_item(tree, hf_mp4ves_profile_and_level_indication, tvb, bit_offset, 8, FALSE);
640         bit_offset+= 8;
641
642         /*      while ( next_bits()== user_data_start_code){
643                 user_data()
644         }
645         */
646         dword = tvb_get_bits32(tvb,bit_offset, 32, FALSE);
647         bit_offset+= 32;
648         if ((dword & 0x00000100) != 0x00000100){
649                 /* No start code prefix */
650                 return -1;
651         }
652         if(dword==0x1b2){
653                 /* 
654                  * user_data_start_code
655                  * XXX call user data dissection here 
656                  */
657                 return -1;
658         }
659         if(dword==0x1b5){
660         /*
661          * VisualObject()
662          */
663                 bit_offset = dissect_mp4ves_VisualObject(tvb, pinfo, tree, bit_offset);
664         }
665                 /*
666         } while ( next_bits() != visual_object_sequence_end_code)
667         visual_object_sequence_end_code 
668         */
669         return bit_offset;
670 }
671
672 void 
673 dissect_mp4ves_config(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
674 {
675         proto_item *item;
676         proto_tree *mp4ves_tree;
677
678         item = proto_tree_add_item(tree, hf_mp4ves_config, tvb, 0, -1, FALSE);
679         mp4ves_tree = proto_item_add_subtree(item, ett_mp4ves_config);
680
681         dissect_mp4ves_VisualObjectSequence(tvb, pinfo, tree, 0);
682 }
683
684 void
685 dissect_mp4ves(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
686 {
687         int bit_offset = 0;
688         proto_item *item;
689         proto_tree *mp4ves_tree;
690         guint32 dword;
691
692         /* Make entries in Protocol column and Info column on summary display */
693         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MP4V-ES");
694         if (tree) {
695                 item = proto_tree_add_item(tree, proto_mp4ves, tvb, 0, -1, FALSE);
696                 mp4ves_tree = proto_item_add_subtree(item, ett_mp4ves);
697         /*
698             +------+------+------+------+
699         (a) | RTP  |  VS  |  VO  | VOL  |
700             |header|header|header|header|
701             +------+------+------+------+
702
703             +------+------+------+------+------------+
704         (b) | RTP  |  VS  |  VO  | VOL  |Video Packet|
705             |header|header|header|header|            |
706             +------+------+------+------+------------+
707
708             +------+-----+------------------+
709         (c) | RTP  | GOV |Video Object Plane|
710             |header|     |                  |
711             +------+-----+------------------+
712
713             +------+------+------------+  +------+------+------------+
714         (d) | RTP  | VOP  |Video Packet|  | RTP  |  VP  |Video Packet|
715             |header|header|    (1)     |  |header|header|    (2)     |
716             +------+------+------------+  +------+------+------------+
717
718             +------+------+------------+------+------------+------+------------+
719         (e) | RTP  |  VP  |Video Packet|  VP  |Video Packet|  VP  |Video Packet|
720             |header|header|     (1)    |header|    (2)     |header|    (3)     |
721             +------+------+------------+------+------------+------+------------+
722
723            +------+------+------------+  +------+------------+
724         (f) | RTP  | VOP  |VOP fragment|  | RTP  |VOP fragment|
725             |header|header|    (1)     |  |header|    (2)     | ___
726             +------+------+------------+  +------+------------+
727
728              Figure 2 - Examples of RTP packetized MPEG-4 Visual bitstream
729
730         So a valid packet should start with
731         VS      - Visual Object Sequence Header
732         GOV     - Group_of_VideoObjectPlane
733         VOP     - Video Object Plane 
734         VP      - Video Plane
735         Otherwies it's a VOP fragment.
736
737         visual_object_sequence_start_code: The visual_object_sequence_start_code is 
738         the bit string '000001B0' in hexadecimal. It initiates a visual session.
739
740         group_of_vop_start_code: The group_of_vop_start_code is the bit string '000001B3' in hexadecimal. It identifies 
741         the beginning of a GOV header.
742
743         vop_start_code: This is the bit string '000001B6' in hexadecimal.
744
745
746         */
747                 if (tvb_length(tvb)< 4){
748                         /* To short to be a start code */
749                         proto_tree_add_text(tree, tvb, bit_offset>>3, -1, "Data");
750                         return;
751                 }
752                 dword = tvb_get_bits32(tvb,bit_offset, 24, FALSE);
753                 if (dword != 1){
754                         /* if it's not 23 zeros followed by 1 it isn't a start code */
755                         proto_tree_add_text(tree, tvb, bit_offset>>3, -1, "Data");
756                         return;
757                 }
758                 dword = tvb_get_bits8(tvb,24, 8);
759                 bit_offset = bit_offset+8;
760                 switch(dword){
761                 /* vop_start_code */
762                 case 0xb6:
763                         proto_tree_add_bits_item(tree, hf_mp4ves_start_code_prefix, tvb, bit_offset, 24, FALSE);
764                         bit_offset = bit_offset+24;
765                         /* vop_coding_type 2 bits */
766                         proto_tree_add_bits_item(tree, hf_mp4ves_vop_coding_type, tvb, bit_offset, 2, FALSE);
767                         break;
768                 case 0xb0:
769                         /* VS start code */
770                         bit_offset = dissect_mp4ves_VisualObjectSequence(tvb, pinfo, tree, 0);
771                         break;
772                 default:
773                         proto_tree_add_bits_item(tree, hf_mp4ves_start_code_prefix, tvb, bit_offset, 24, FALSE);
774                         bit_offset = bit_offset+24;
775                         break;
776                 }
777         }
778
779 }
780 /*
781  * Parameter name profileAndLevel
782  * Parameter description This is a nonCollapsing GenericParameter
783  * Parameter identifier value 0
784  * Parameter status Mandatory
785  * Parameter type unsignedMax. Shall be in the range 0..255.
786  * H245:
787  * unsignedMax       INTEGER(0..65535), -- Look for max 
788  */
789 static int
790 dissect_mp4ves_par_profile(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_)
791 {
792         int offset = 0;
793         guint16 lvl;
794         const gchar *p = NULL;
795         asn1_ctx_t *actx;
796
797         actx = get_asn1_ctx(pinfo->private_data);
798         DISSECTOR_ASSERT(actx);
799
800         lvl = tvb_get_ntohs(tvb, offset);
801         p = match_strval(lvl, VALS(mp4ves_level_indication_vals));
802         if (p) {
803                 proto_item_append_text(actx->created_item, " - profileAndLevel %s", p);
804         }
805         offset += 2;
806         return offset;
807 }
808 static int
809 dissect_mp4ves_par_video_object_type(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_)
810 {
811         int offset = 0;
812         guint16 lvl;
813         const gchar *p = NULL;
814         asn1_ctx_t *actx;
815
816         actx = get_asn1_ctx(pinfo->private_data);
817         DISSECTOR_ASSERT(actx);
818
819         lvl = tvb_get_ntohs(tvb, offset);
820         p = match_strval(lvl, VALS(mp4ves_video_object_type_vals));
821         if (p) {
822                 proto_item_append_text(actx->created_item, " - video_object_type %s", p);
823         }
824         offset += 2;
825         return offset;
826 }
827
828 static int
829 dissect_mp4ves_par_decoderConfigurationInformation(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_)
830 {
831         asn1_ctx_t *actx;
832
833         actx = get_asn1_ctx(pinfo->private_data);
834         DISSECTOR_ASSERT(actx);
835
836         dissect_mp4ves_config(tvb, pinfo, tree);
837
838         return tvb_length(tvb);
839 }
840
841 typedef struct _mp4ves_capability_t {
842         const gchar *id;
843         const gchar *name;
844         new_dissector_t content_pdu;
845 } mp4ves_capability_t;
846
847 static mp4ves_capability_t mp4ves_capability_tab[] = {
848         /* ITU-T H.245  capabilities ISO/IEC 14496-2(m*/
849         { "GenericCapability/0.0.8.245.1.0.0/nonCollapsing/0", "profileAndLevel", dissect_mp4ves_par_profile },
850         { "GenericCapability/0.0.8.245.1.0.0/nonCollapsing/1", "object", dissect_mp4ves_par_video_object_type },
851         { "GenericCapability/0.0.8.245.1.0.0/nonCollapsing/2", "decoderConfigurationInformation", dissect_mp4ves_par_decoderConfigurationInformation },
852         { "GenericCapability/0.0.8.245.1.0.0/nonCollapsing/3", "drawingOrder", NULL },
853         { "GenericCapability/0.0.8.245.1.0.0/collapsing/4", "visualBackChannelHandle", NULL },
854         { NULL, NULL, NULL },
855 };                                 
856
857 static mp4ves_capability_t *find_cap(const gchar *id) {
858         mp4ves_capability_t *ftr = NULL;
859         mp4ves_capability_t *f;
860
861         for (f=mp4ves_capability_tab; f->id; f++) {
862                 if (!strcmp(id, f->id)) { ftr = f; break; }
863         }
864         return ftr;
865 }
866
867 static void
868 dissect_mp4ves_name(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree) 
869 {
870         asn1_ctx_t *actx;
871         mp4ves_capability_t *ftr = NULL;
872
873         actx = get_asn1_ctx(pinfo->private_data);
874         DISSECTOR_ASSERT(actx);
875         if (tree) {
876                 ftr = find_cap(pinfo->match_string);
877                 if (ftr) {
878                         proto_item_append_text(actx->created_item, " - %s", ftr->name);
879                         proto_item_append_text(proto_item_get_parent(proto_tree_get_parent(tree)), ": %s", ftr->name);
880                 } else {
881                         proto_item_append_text(actx->created_item, " - unknown(%s)", pinfo->match_string);
882                 }
883         }
884 }
885
886 void
887 proto_reg_handoff_mp4ves(void);
888
889 void
890 proto_register_mp4ves(void)
891 {                 
892
893
894 /* Setup list of header fields  See Section 1.6.1 for details*/
895         static hf_register_info hf[] = {
896                 { &hf_mp4ves_config,
897                   { "Configuration",        "mp4ves.configuration", 
898                     FT_BYTES, BASE_NONE, NULL, 0x0,
899                     NULL, HFILL }
900                 },
901                 { &hf_mp4ves_start_code_prefix,
902                   { "start code prefix",                "mp4ves.start_code_prefix", 
903                     FT_UINT32, BASE_HEX, NULL, 0x0,
904                     NULL, HFILL }
905                 },
906                 { &hf_mp4ves_start_code,
907                   { "Start code",               "mp4ves.start_code", 
908                     FT_UINT8, BASE_RANGE_STRING|BASE_HEX, RVALS(&mp4ves_startcode_vals), 0x0,
909                     NULL, HFILL }
910                 },
911                 { &hf_mp4ves_vop_coding_type,
912                   { "vop_coding_type",          "mp4ves.vop_coding_type", 
913                     FT_UINT8, BASE_DEC, VALS(mp4ves_vop_coding_type_vals), 0x0,
914                     "Start code", HFILL }
915                 },
916                 {&hf_mp4ves_profile_and_level_indication,
917                  { "profile_and_level_indication",              "mp4ves.profile_and_level_indication",
918                    FT_UINT8, BASE_DEC,VALS(mp4ves_level_indication_vals), 0x0,
919                    NULL, HFILL }
920                 },
921                 { &hf_mp4ves_is_visual_object_identifier,
922                   { "visual_object_identifier",         "mp4ves.visual_object_identifier",
923                     FT_UINT8, BASE_DEC, NULL, 0x0,
924                     NULL, HFILL }
925                 },
926                 { &hf_mp4ves_visual_object_type,
927                   { "visual_object_type",               "mp4ves.visual_object_type",
928                     FT_UINT32, BASE_DEC, VALS(mp4ves_visual_object_type_vals), 0x0,
929                     NULL, HFILL }
930                 },
931                 { &hf_mp4ves_video_signal_type,
932                   { "video_signal_type",                "mp4ves.video_signal_type",
933                     FT_UINT8, BASE_DEC, NULL, 0x0,
934                     NULL, HFILL }
935                 },
936                 { &hf_mp4ves_stuffing,
937                   { "Stuffing",         "mp4ves.stuffing",
938                     FT_UINT8, BASE_DEC, NULL, 0x0,
939                     NULL, HFILL }
940                 },
941                 { &hf_mp4ves_video_object_type_indication,
942                   { "video_object_type_indication",             "mp4ves.video_object_type_indication",
943                     FT_UINT8, BASE_DEC, VALS(mp4ves_video_object_type_indication_vals), 0x0,
944                     NULL, HFILL }
945                 },
946                 { &hf_mp4ves_random_accessible_vol,
947                   { "random_accessible_vol",            "mp4ves.random_accessible_vol",
948                     FT_UINT8, BASE_DEC, NULL, 0x0,
949                     "video_object_type_indication", HFILL }
950                 },
951                 { &hf_mp4ves_is_object_layer_identifier,
952                   { "is_object_layer_identifier",               "mp4ves.is_object_layer_identifier",
953                     FT_UINT8, BASE_DEC, NULL, 0x0,
954                     NULL, HFILL }
955                 },
956                 { &hf_mp4ves_aspect_ratio_info,
957                   { "aspect_ratio_info",                "mp4ves.aspect_ratio_info",
958                     FT_UINT8, BASE_DEC, VALS(mp4ves_aspect_ratio_info_vals), 0x0,
959                     NULL, HFILL }
960                 },
961                 { &hf_mp4ves_vol_control_parameters,
962                   { "vol_control_parameters",           "mp4ves.vol_control_parameters",
963                     FT_UINT8, BASE_DEC, NULL, 0x0,
964                     NULL, HFILL }
965                 },
966                 { &hf_mp4ves_video_object_layer_shape,
967                   { "video_object_layer_shape",         "mp4ves.video_object_layer_shape",
968                     FT_UINT8, BASE_DEC, VALS(mp4ves_video_object_layer_shape_vals), 0x0,
969                     NULL, HFILL }
970                 },
971         };
972
973 /* Setup protocol subtree array */
974         static gint *ett[] = {
975                 &ett_mp4ves,
976                 &ett_mp4ves_config,
977         };
978
979         module_t *mp4ves_module;
980
981 /* Register the protocol name and description */
982         proto_mp4ves = proto_register_protocol("MP4V-ES","MP4V-ES", "mp4v-es");
983
984 /* Required function calls to register the header fields and subtrees used */
985         proto_register_field_array(proto_mp4ves, hf, array_length(hf));
986         proto_register_subtree_array(ett, array_length(ett));
987         /* Register a configuration option for port */
988
989         register_dissector("mp4ves", dissect_mp4ves, proto_mp4ves);
990
991         /* Register a configuration option for port */  
992         mp4ves_module = prefs_register_protocol(proto_mp4ves, proto_reg_handoff_mp4ves);
993
994         prefs_register_uint_preference(mp4ves_module, 
995                                        "dynamic.payload.type",
996                                        "MP4V-ES dynamic payload type",
997                                        "The dynamic payload type which will be interpreted as MP4V-ES",
998                                        10,
999                                        &global_dynamic_payload_type);
1000
1001 }
1002
1003 void
1004 proto_reg_handoff_mp4ves(void)
1005 {
1006         static dissector_handle_t mp4ves_handle;
1007         static guint dynamic_payload_type;
1008         static gboolean mp4ves_prefs_initialized = FALSE;
1009
1010         if (!mp4ves_prefs_initialized) {
1011                 dissector_handle_t mp4ves_name_handle;
1012                 mp4ves_capability_t *ftr;
1013
1014                 mp4ves_handle = find_dissector("mp4ves");
1015                 dissector_add_string("rtp_dyn_payload_type","MP4V-ES", mp4ves_handle);
1016                 mp4ves_prefs_initialized = TRUE;
1017
1018                 mp4ves_name_handle = create_dissector_handle(dissect_mp4ves_name, proto_mp4ves);
1019                 for (ftr=mp4ves_capability_tab; ftr->id; ftr++) {
1020                     if (ftr->name) 
1021                                 dissector_add_string("h245.gef.name", ftr->id, mp4ves_name_handle);
1022                         if (ftr->content_pdu)
1023                                 dissector_add_string("h245.gef.content", ftr->id, new_create_dissector_handle(ftr->content_pdu, proto_mp4ves));
1024                 }
1025         }else{
1026                 if ( dynamic_payload_type > 95 )
1027                         dissector_delete("rtp.pt", dynamic_payload_type, mp4ves_handle);
1028         }
1029         dynamic_payload_type = global_dynamic_payload_type;
1030
1031         if ( dynamic_payload_type > 95 ){
1032                 dissector_add("rtp.pt", dynamic_payload_type, mp4ves_handle);
1033         }
1034 }
1035