2 * routines for dissection of MP4 files
3 * Copyright 2013-2014, Martin Kaiser <martin@kaiser.cx>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 /* this dissector is based on
25 * ISO/IEC 14496-12 (ISO base media file format) and
26 * ISO/IEC 14496-14 (MP4 file format)
28 * at the moment, it dissects the basic box structure and the payload of
29 * some simple boxes */
36 #include <epan/expert.h>
37 #include <epan/packet.h>
39 #define MAKE_TYPE_VAL(a, b, c, d) ((a)<<24 | (b)<<16 | (c)<<8 | (d))
41 void proto_register_mp4(void);
42 void proto_reg_handoff_mp4(void);
44 static gint dissect_mp4_box(guint32 parent_box_type _U_,
45 tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree);
47 static int proto_mp4 = -1;
49 static gint ett_mp4 = -1;
50 static gint ett_mp4_box = -1;
52 static int hf_mp4_box_size = -1;
53 static int hf_mp4_box_type_str = -1;
54 static int hf_mp4_box_largesize = -1;
55 static int hf_mp4_full_box_ver = -1;
56 static int hf_mp4_full_box_flags = -1;
57 static int hf_mp4_ftyp_brand = -1;
58 static int hf_mp4_ftyp_ver = -1;
59 static int hf_mp4_ftyp_add_brand = -1;
60 static int hf_mp4_mfhd_seq_num = -1;
61 static int hf_mp4_tkhd_creat_time = -1;
62 static int hf_mp4_tkhd_mod_time = -1;
63 static int hf_mp4_tkhd_track_id = -1;
64 static int hf_mp4_tkhd_duration = -1;
65 static int hf_mp4_tkhd_width = -1;
66 static int hf_mp4_tkhd_height = -1;
67 static int hf_mp4_hdlr_type = -1;
68 static int hf_mp4_hdlr_name = -1;
69 static int hf_mp4_dref_entry_cnt = -1;
70 static int hf_mp4_stsd_entry_cnt = -1;
72 static expert_field ei_mp4_box_too_large = EI_INIT;
74 /* a box must at least have a 32bit len field and a 32bit type */
75 #define MIN_BOX_SIZE 8
76 /* an extended box has the first length field set to 1 */
77 #define BOX_SIZE_EXTENDED 1
79 /* the box type is stored as four text characters
80 it is in network byte order and contains only printable characters
81 for our internal handling, we convert this to a 32bit value */
83 #define BOX_TYPE_NONE 0x0 /* used for parent_box_type of a top-level box */
84 #define BOX_TYPE_FTYP MAKE_TYPE_VAL('f', 't', 'y', 'p')
85 #define BOX_TYPE_MOOV MAKE_TYPE_VAL('m', 'o', 'o', 'v')
86 #define BOX_TYPE_MVHD MAKE_TYPE_VAL('m', 'v', 'h', 'd')
87 #define BOX_TYPE_TRAK MAKE_TYPE_VAL('t', 'r', 'a', 'k')
88 #define BOX_TYPE_TKHD MAKE_TYPE_VAL('t', 'k', 'h', 'd')
89 #define BOX_TYPE_MDIA MAKE_TYPE_VAL('m', 'd', 'i', 'a')
90 #define BOX_TYPE_MDHD MAKE_TYPE_VAL('m', 'd', 'h', 'd')
91 #define BOX_TYPE_HDLR MAKE_TYPE_VAL('h', 'd', 'l', 'r')
92 #define BOX_TYPE_MINF MAKE_TYPE_VAL('m', 'i', 'n', 'f')
93 #define BOX_TYPE_VMHD MAKE_TYPE_VAL('v', 'm', 'h', 'd')
94 #define BOX_TYPE_SMHD MAKE_TYPE_VAL('s', 'm', 'h', 'd')
95 #define BOX_TYPE_DINF MAKE_TYPE_VAL('d', 'i', 'n', 'f')
96 #define BOX_TYPE_DREF MAKE_TYPE_VAL('d', 'r', 'e', 'f')
97 #define BOX_TYPE_STBL MAKE_TYPE_VAL('s', 't', 'b', 'l')
98 #define BOX_TYPE_STTS MAKE_TYPE_VAL('s', 't', 't', 's')
99 #define BOX_TYPE_CTTS MAKE_TYPE_VAL('c', 't', 't', 's')
100 #define BOX_TYPE_STSD MAKE_TYPE_VAL('s', 't', 's', 'd')
101 #define BOX_TYPE_STSZ MAKE_TYPE_VAL('s', 't', 's', 'z')
102 #define BOX_TYPE_STSC MAKE_TYPE_VAL('s', 't', 's', 'c')
103 #define BOX_TYPE_STCO MAKE_TYPE_VAL('s', 't', 'c', 'o')
104 #define BOX_TYPE_STSS MAKE_TYPE_VAL('s', 't', 's', 's')
105 #define BOX_TYPE_MVEX MAKE_TYPE_VAL('m', 'v', 'e', 'x')
106 #define BOX_TYPE_MOOF MAKE_TYPE_VAL('m', 'o', 'o', 'f')
107 #define BOX_TYPE_MEHD MAKE_TYPE_VAL('m', 'e', 'h', 'd')
108 #define BOX_TYPE_TREX MAKE_TYPE_VAL('t', 'r', 'e', 'x')
109 #define BOX_TYPE_MFHD MAKE_TYPE_VAL('m', 'f', 'h', 'd')
110 #define BOX_TYPE_TRAF MAKE_TYPE_VAL('t', 'r', 'a', 'f')
111 #define BOX_TYPE_TFHD MAKE_TYPE_VAL('t', 'f', 'h', 'd')
112 #define BOX_TYPE_TRUN MAKE_TYPE_VAL('t', 'r', 'u', 'n')
113 #define BOX_TYPE_MDAT MAKE_TYPE_VAL('m', 'd', 'a', 't')
114 #define BOX_TYPE_UDTA MAKE_TYPE_VAL('u', 'd', 't', 'a')
115 /* the box name is url + <space>, all names must be 4 characters long */
116 #define BOX_TYPE_URL_ MAKE_TYPE_VAL('u', 'r', 'l', ' ')
118 /* the location for this URL box is the same as in the upper-level movie box */
119 #define ENTRY_FLAG_MOVIE 0x000001
121 static const value_string box_types[] = {
122 { BOX_TYPE_FTYP, "File Type Box" },
123 { BOX_TYPE_MOOV, "Movie Box" },
124 { BOX_TYPE_MVHD, "Movie Header Box" },
125 { BOX_TYPE_TRAK, "Track Box" },
126 { BOX_TYPE_TKHD, "Track Header Box" },
127 { BOX_TYPE_MDIA, "Media Box" },
128 { BOX_TYPE_MDHD, "Media Header Box" },
129 { BOX_TYPE_HDLR, "Handler Reference Box" },
130 { BOX_TYPE_MINF, "Media Information Box" },
131 { BOX_TYPE_VMHD, "Video Media Header Box" },
132 { BOX_TYPE_SMHD, "Sound Media Header Box" },
133 { BOX_TYPE_DINF, "Data Information Box" },
134 { BOX_TYPE_DREF, "Data Reference Box" },
135 { BOX_TYPE_STBL, "Sample to Group Box" },
136 { BOX_TYPE_STTS, "Decoding Time To Sample Box" },
137 { BOX_TYPE_CTTS, "Composition Time To Sample Box" },
138 { BOX_TYPE_STSD, "Sample Description Box" },
139 { BOX_TYPE_STSZ, "Sample Size Box" },
140 { BOX_TYPE_STSC, "Sample To Chunk Box" },
141 { BOX_TYPE_STCO, "Chunk Offset Box" },
142 { BOX_TYPE_STSS, "Sync Sample Table" },
143 { BOX_TYPE_MVEX, "Movie Extends Box" },
144 { BOX_TYPE_MOOF, "Movie Fragment Box" },
145 { BOX_TYPE_MEHD, "Movie Extends Header Box" },
146 { BOX_TYPE_TREX, "Track Extends Box" },
147 { BOX_TYPE_MFHD, "Movie Fragment Header Box" },
148 { BOX_TYPE_TRAF, "Track Fragment Box" },
149 { BOX_TYPE_TFHD, "Track Fragment Header Box" },
150 { BOX_TYPE_TRUN, "Track Fragment Run Box" },
151 { BOX_TYPE_MDAT, "Media Data Box" },
152 { BOX_TYPE_UDTA, "User Data Box" },
153 { BOX_TYPE_URL_, "URL Box" },
157 /* convert a decimal number x into a double 0.x (e.g. 123 becomes 0.123) */
164 return (double)(x / exp(log(10.0)*(1+floor(log((double)x)/log(10.0)))));
168 dissect_mp4_mvhd_body(tvbuff_t *tvb, gint offset, gint len _U_,
169 packet_info *pinfo _U_, proto_tree *tree)
173 offset_start = offset;
174 proto_tree_add_item(tree, hf_mp4_full_box_ver,
175 tvb, offset, 1, ENC_BIG_ENDIAN);
177 proto_tree_add_item(tree, hf_mp4_full_box_flags,
178 tvb, offset, 3, ENC_BIG_ENDIAN);
181 return offset-offset_start;
185 dissect_mp4_mfhd_body(tvbuff_t *tvb, gint offset, gint len _U_,
186 packet_info *pinfo _U_, proto_tree *tree)
190 offset_start = offset;
191 proto_tree_add_item(tree, hf_mp4_full_box_ver,
192 tvb, offset, 1, ENC_BIG_ENDIAN);
194 proto_tree_add_item(tree, hf_mp4_full_box_flags,
195 tvb, offset, 3, ENC_BIG_ENDIAN);
198 proto_tree_add_item(tree, hf_mp4_mfhd_seq_num,
199 tvb, offset, 4, ENC_BIG_ENDIAN);
202 return offset-offset_start;
207 dissect_mp4_tkhd_body(tvbuff_t *tvb, gint offset, gint len _U_,
208 packet_info *pinfo _U_, proto_tree *tree)
213 double width, height;
216 offset_start = offset;
218 version = tvb_get_guint8(tvb, offset);
219 proto_tree_add_item(tree, hf_mp4_full_box_ver,
220 tvb, offset, 1, ENC_BIG_ENDIAN);
222 proto_tree_add_item(tree, hf_mp4_full_box_flags,
223 tvb, offset, 3, ENC_BIG_ENDIAN);
226 time_len = (version==0) ? 4 : 8;
227 proto_tree_add_item(tree, hf_mp4_tkhd_creat_time,
228 tvb, offset, time_len, ENC_BIG_ENDIAN);
230 proto_tree_add_item(tree, hf_mp4_tkhd_mod_time,
231 tvb, offset, time_len, ENC_BIG_ENDIAN);
234 proto_tree_add_item(tree, hf_mp4_tkhd_track_id,
235 tvb, offset, 4, ENC_BIG_ENDIAN);
238 offset += 4; /* 32bit reserved */
240 proto_tree_add_item(tree, hf_mp4_tkhd_duration,
241 tvb, offset, time_len, ENC_BIG_ENDIAN);
244 offset += 2*4; /* 2*32bit reserved */
245 offset += 2; /* 16bit layer */
246 offset += 2; /* 16bit alternate_group */
247 offset += 2; /* 16bit volume */
248 offset += 2; /* 16bit reserved */
249 offset += 9*4; /* 9*32bit matrix */
251 width = tvb_get_ntohs(tvb, offset);
252 fract_dec = tvb_get_ntohs(tvb, offset+2);
253 width += make_fract(fract_dec);
254 proto_tree_add_double_format_value(tree, hf_mp4_tkhd_width,
255 tvb, offset, 4, width, "%f", width);
258 height = tvb_get_ntohs(tvb, offset);
259 fract_dec = tvb_get_ntohs(tvb, offset+2);
260 height += make_fract(fract_dec);
261 proto_tree_add_double_format_value(tree, hf_mp4_tkhd_height,
262 tvb, offset, 4, height, "%f", height);
265 return offset-offset_start;
270 dissect_mp4_ftyp_body(tvbuff_t *tvb, gint offset, gint len,
271 packet_info *pinfo _U_, proto_tree *tree)
275 offset_start = offset;
276 proto_tree_add_item(tree, hf_mp4_ftyp_brand,
277 tvb, offset, 4, ENC_ASCII|ENC_NA);
279 proto_tree_add_item(tree, hf_mp4_ftyp_ver,
280 tvb, offset, 4, ENC_BIG_ENDIAN);
283 while ((offset-offset_start) < len) {
284 proto_tree_add_item(tree, hf_mp4_ftyp_add_brand,
285 tvb, offset, 4, ENC_ASCII|ENC_NA);
289 return offset - offset_start;
294 dissect_mp4_hdlr_body(tvbuff_t *tvb, gint offset, gint len _U_,
295 packet_info *pinfo _U_, proto_tree *tree)
300 offset_start = offset;
302 proto_tree_add_item(tree, hf_mp4_full_box_ver,
303 tvb, offset, 1, ENC_BIG_ENDIAN);
304 /* XXX - put up an expert info if version!=0 */
306 proto_tree_add_item(tree, hf_mp4_full_box_flags,
307 tvb, offset, 3, ENC_BIG_ENDIAN);
310 offset += 4; /* four reserved 0 bytes */
312 proto_tree_add_item(tree, hf_mp4_hdlr_type,
313 tvb, offset, 4, ENC_ASCII|ENC_NA);
316 offset += 12; /* 3x32bit reserved */
318 /* name is a 0-terminated UTF-8 string, len includes the final 0 */
319 hdlr_name_len = tvb_strsize(tvb, offset);
320 proto_tree_add_item(tree, hf_mp4_hdlr_name,
321 tvb, offset, hdlr_name_len, ENC_UTF_8|ENC_NA);
322 offset += hdlr_name_len;
324 return offset-offset_start;
329 dissect_mp4_dref_body(tvbuff_t *tvb, gint offset, gint len _U_,
330 packet_info *pinfo, proto_tree *tree)
333 guint32 entry_cnt, i;
336 offset_start = offset;
338 proto_tree_add_item(tree, hf_mp4_full_box_ver,
339 tvb, offset, 1, ENC_BIG_ENDIAN);
340 /* XXX - put up an expert info if version!=0 */
342 proto_tree_add_item(tree, hf_mp4_full_box_flags,
343 tvb, offset, 3, ENC_BIG_ENDIAN);
346 entry_cnt = tvb_get_ntohl(tvb, offset);
347 proto_tree_add_item(tree, hf_mp4_dref_entry_cnt,
348 tvb, offset, 4, ENC_BIG_ENDIAN);
351 for(i=0; i<entry_cnt; i++) {
352 ret = dissect_mp4_box(BOX_TYPE_DREF, tvb, offset, pinfo, tree);
359 return offset-offset_start;
364 dissect_mp4_url_body(tvbuff_t *tvb, gint offset, gint len,
365 packet_info *pinfo _U_, proto_tree *tree)
369 proto_tree_add_item(tree, hf_mp4_full_box_ver,
370 tvb, offset, 1, ENC_BIG_ENDIAN);
371 /* XXX - put up an expert info if version!=0 */
374 flags = tvb_get_ntoh24(tvb, offset);
375 proto_tree_add_item(tree, hf_mp4_full_box_flags,
376 tvb, offset, 3, ENC_BIG_ENDIAN);
379 if (flags&ENTRY_FLAG_MOVIE) {
380 proto_tree_add_text(tree, tvb, 0, 0,
381 "Media data location is defined in the movie box");
384 /* XXX - dissect location string */
392 dissect_mp4_stsd_body(tvbuff_t *tvb, gint offset, gint len,
393 packet_info *pinfo _U_, proto_tree *tree)
395 guint32 entry_cnt, i;
398 proto_tree_add_item(tree, hf_mp4_full_box_ver,
399 tvb, offset, 1, ENC_BIG_ENDIAN);
400 /* XXX - put up an expert info if version!=0 */
402 proto_tree_add_item(tree, hf_mp4_full_box_flags,
403 tvb, offset, 3, ENC_BIG_ENDIAN);
406 entry_cnt = tvb_get_ntohl(tvb, offset);
407 proto_tree_add_item(tree, hf_mp4_dref_entry_cnt,
408 tvb, offset, 4, ENC_BIG_ENDIAN);
411 for(i=0; i<entry_cnt; i++) {
412 /* a sample entry has the same format as an mp4 box
413 we call dissect_mp4_box() to dissect it
414 alternatively, we could parse it ourselves, we'd then have to
415 handle the extended lengths etc */
417 /* XXX - dissect the content of each Sample Entry,
418 this depends on the handler_type, we could add an optional
419 void *data parameter to dissect_mp4_box() and handle sample
420 entry boxes based on parent box and data parameter */
421 ret = dissect_mp4_box(BOX_TYPE_STSD, tvb, offset, pinfo, tree);
432 /* dissect a box, return its (standard or extended) length or 0 for error */
434 dissect_mp4_box(guint32 parent_box_type _U_,
435 tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree)
440 guint8 *box_type_str;
441 proto_item *type_pi, *size_pi, *ext_size_pi = NULL;
442 proto_tree *box_tree;
447 offset_start = offset;
449 /* the following mechanisms are not supported for now
450 - size==0, indicating that the box extends to the end of the file
451 - extended box types */
453 box_size = (guint64)tvb_get_ntohl(tvb, offset);
454 if ((box_size != BOX_SIZE_EXTENDED) && (box_size < MIN_BOX_SIZE))
457 box_type = tvb_get_ntohl(tvb, offset+4);
458 box_type_str = tvb_get_string_enc(wmem_packet_scope(), tvb,
459 offset+4, 4, ENC_ASCII|ENC_NA);
461 box_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1, ett_mp4_box, &type_pi, "%s (%s)",
462 val_to_str_const(box_type, box_types, "unknown"), box_type_str);
464 size_pi = proto_tree_add_item(box_tree, hf_mp4_box_size,
465 tvb, offset, 4, ENC_BIG_ENDIAN);
466 if (box_size == BOX_SIZE_EXTENDED)
467 proto_item_append_text(size_pi, " (actual size is in largesize)");
470 proto_tree_add_item(box_tree, hf_mp4_box_type_str,
471 tvb, offset, 4, ENC_ASCII|ENC_NA);
474 if (box_size == BOX_SIZE_EXTENDED) {
475 box_size = tvb_get_ntoh64(tvb, offset);
476 ext_size_pi = proto_tree_add_item(box_tree, hf_mp4_box_largesize,
477 tvb, offset, 8, ENC_BIG_ENDIAN);
481 if (box_size > G_MAXINT) {
482 /* this should be ok for ext_size_pi==NULL */
483 expert_add_info(pinfo, ext_size_pi, &ei_mp4_box_too_large);
486 proto_item_set_len(type_pi, (gint)box_size);
487 body_size = (gint)box_size - (offset-offset_start);
489 /* we do not dissect full box version and flags here
490 these two components are required by the function dissecting the body
491 some fields of the body depend on the version and flags */
493 /* XXX - check parent box if supplied */
496 dissect_mp4_ftyp_body(tvb, offset, body_size, pinfo, box_tree);
499 dissect_mp4_mvhd_body(tvb, offset, body_size, pinfo, box_tree);
502 dissect_mp4_mfhd_body(tvb, offset, body_size, pinfo, box_tree);
505 dissect_mp4_tkhd_body(tvb, offset, body_size, pinfo, box_tree);
508 dissect_mp4_hdlr_body(tvb, offset, body_size, pinfo, box_tree);
511 dissect_mp4_dref_body(tvb, offset, body_size, pinfo, box_tree);
514 dissect_mp4_url_body(tvb, offset, body_size, pinfo, box_tree);
517 dissect_mp4_stsd_body(tvb, offset, body_size, pinfo, box_tree);
529 while (offset-offset_start < (gint)box_size) {
530 ret = dissect_mp4_box(box_type, tvb, offset, pinfo, box_tree);
540 return (gint)box_size;
545 dissect_mp4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
550 proto_tree *mp4_tree;
553 /* to make sure that we have an mp4 file, we check that it starts with
554 a box of a known type
555 please note that we do not allow the first box to be an extended box
556 this detection should be safe as long as the dissector is only called for
557 the video/mp4 mime type
558 when we read mp4 files directly, we might need stricter checks here */
559 if (tvb_reported_length(tvb) < MIN_BOX_SIZE)
561 box_type = tvb_get_ntohl(tvb, 4);
562 if (try_val_to_str(box_type, box_types) == NULL)
565 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MP4");
566 col_clear(pinfo->cinfo, COL_INFO);
568 pi = proto_tree_add_protocol_format(tree, proto_mp4,
569 tvb, 0, (gint)tvb_reported_length(tvb), "MP4");
570 mp4_tree = proto_item_add_subtree(pi, ett_mp4);
572 while (tvb_reported_length_remaining(tvb, offset) > 0) {
573 ret = dissect_mp4_box(BOX_TYPE_NONE, tvb, offset, pinfo, mp4_tree);
583 proto_register_mp4(void)
585 static hf_register_info hf[] = {
587 { "Box size", "mp4.box.size", FT_UINT32, BASE_DEC,
588 NULL, 0, NULL, HFILL } },
589 { &hf_mp4_box_type_str,
590 { "Box type", "mp4.box.type_str", FT_STRING, BASE_NONE,
591 NULL, 0, NULL, HFILL } },
592 { &hf_mp4_box_largesize,
593 { "Box size (largesize)", "mp4.box.largesize", FT_UINT64, BASE_DEC,
594 NULL, 0, NULL, HFILL } },
595 { &hf_mp4_full_box_ver,
596 { "Box version", "mp4.full_box.version", FT_UINT8, BASE_DEC,
597 NULL, 0, NULL, HFILL } },
598 { &hf_mp4_full_box_flags,
599 { "Flags", "mp4.full_box.flags", FT_UINT24, BASE_HEX,
600 NULL, 0, NULL, HFILL } },
601 { &hf_mp4_ftyp_brand,
602 { "Brand", "mp4.ftyp.brand", FT_STRING, BASE_NONE,
603 NULL, 0, NULL, HFILL } },
605 { "Version", "mp4.ftyp.version", FT_UINT32, BASE_DEC,
606 NULL, 0, NULL, HFILL } },
607 { &hf_mp4_ftyp_add_brand,
608 { "Additional brand", "mp4.ftyp.additional_brand", FT_STRING,
609 BASE_NONE, NULL, 0, NULL, HFILL } },
610 { &hf_mp4_mfhd_seq_num,
611 { "Sequence number", "mp4.mfhd.sequence_number", FT_UINT32,
612 BASE_DEC, NULL, 0, NULL, HFILL } },
613 { &hf_mp4_tkhd_creat_time,
614 { "Creation time", "mp4.tkhd.creation_time", FT_UINT64,
615 BASE_DEC, NULL, 0, NULL, HFILL } },
616 { &hf_mp4_tkhd_mod_time,
617 { "Modification time", "mp4.tkhd.modification_time", FT_UINT64,
618 BASE_DEC, NULL, 0, NULL, HFILL } },
619 { &hf_mp4_tkhd_track_id,
620 { "Track ID", "mp4.tkhd.track_id", FT_UINT32,
621 BASE_DEC, NULL, 0, NULL, HFILL } },
622 { &hf_mp4_tkhd_duration,
623 { "Duration", "mp4.tkhd.duration", FT_UINT64,
624 BASE_DEC, NULL, 0, NULL, HFILL } },
625 { &hf_mp4_tkhd_width,
626 { "Width", "mp4.tkhd.width", FT_DOUBLE,
627 BASE_NONE, NULL, 0, NULL, HFILL } },
628 { &hf_mp4_tkhd_height,
629 { "Height", "mp4.tkhd.height", FT_DOUBLE,
630 BASE_NONE, NULL, 0, NULL, HFILL } },
632 { "Handler type", "mp4.hdlr.type", FT_STRING,
633 BASE_NONE, NULL, 0, NULL, HFILL } },
635 { "Handler name", "mp4.hdlr.name", FT_STRINGZ,
636 BASE_NONE, NULL, 0, NULL, HFILL } },
637 { &hf_mp4_dref_entry_cnt,
638 { "Number of entries", "mp4.dref.entry_count", FT_UINT32,
639 BASE_DEC, NULL, 0, NULL, HFILL } },
640 { &hf_mp4_stsd_entry_cnt,
641 { "Number of entries", "mp4.stsd.entry_count", FT_UINT32,
642 BASE_DEC, NULL, 0, NULL, HFILL } }
645 static gint *ett[] = {
650 static ei_register_info ei[] = {
651 { &ei_mp4_box_too_large,
652 { "mp4.box_too_large", PI_PROTOCOL, PI_WARN,
653 "box size too large, dissection of this box is not supported", EXPFILL }}
656 expert_module_t *expert_mp4;
658 proto_mp4 = proto_register_protocol("MP4 / ISOBMFF file format", "mp4", "mp4");
660 proto_register_field_array(proto_mp4, hf, array_length(hf));
661 proto_register_subtree_array(ett, array_length(ett));
662 expert_mp4 = expert_register_protocol(proto_mp4);
663 expert_register_field_array(expert_mp4, ei, array_length(ei));
667 proto_reg_handoff_mp4(void)
669 dissector_handle_t mp4_handle = new_create_dissector_handle(dissect_mp4, proto_mp4);
670 dissector_add_string("media_type", "video/mp4", mp4_handle);
675 * Editor modelines - http://www.wireshark.org/tools/modelines.html
680 * indent-tabs-mode: nil
683 * vi: set shiftwidth=4 tabstop=8 expandtab:
684 * :indentSize=4:tabSize=8:noTabs=true: