support extended size boxes, general cleanup
svn path=/trunk/; revision=50040
This commit is contained in:
parent
a17358cf3f
commit
86c30e2abe
|
@ -45,6 +45,7 @@ static gint ett_mp4_box = -1;
|
||||||
|
|
||||||
static int hf_mp4_box_size = -1;
|
static int hf_mp4_box_size = -1;
|
||||||
static int hf_mp4_box_type_str = -1;
|
static int hf_mp4_box_type_str = -1;
|
||||||
|
static int hf_mp4_box_largesize = -1;
|
||||||
static int hf_mp4_full_box_ver = -1;
|
static int hf_mp4_full_box_ver = -1;
|
||||||
static int hf_mp4_ftyp_brand = -1;
|
static int hf_mp4_ftyp_brand = -1;
|
||||||
static int hf_mp4_ftyp_ver = -1;
|
static int hf_mp4_ftyp_ver = -1;
|
||||||
|
@ -52,7 +53,9 @@ static int hf_mp4_ftyp_add_brand = -1;
|
||||||
static int hf_mp4_mfhd_seq_num = -1;
|
static int hf_mp4_mfhd_seq_num = -1;
|
||||||
|
|
||||||
/* a box must at least have a 32bit len field and a 32bit type */
|
/* a box must at least have a 32bit len field and a 32bit type */
|
||||||
#define MIN_BOX_LEN 8
|
#define MIN_BOX_SIZE 8
|
||||||
|
/* an extended box has the first length field set to 1 */
|
||||||
|
#define BOX_SIZE_EXTENDED 1
|
||||||
|
|
||||||
/* the box type is stored as four text characters
|
/* the box type is stored as four text characters
|
||||||
it is in network byte order and contains only printable characters
|
it is in network byte order and contains only printable characters
|
||||||
|
@ -86,6 +89,7 @@ static int hf_mp4_mfhd_seq_num = -1;
|
||||||
#define BOX_TYPE_TFHD MAKE_TYPE_VAL('t', 'f', 'h', 'd')
|
#define BOX_TYPE_TFHD MAKE_TYPE_VAL('t', 'f', 'h', 'd')
|
||||||
#define BOX_TYPE_TRUN MAKE_TYPE_VAL('t', 'r', 'u', 'n')
|
#define BOX_TYPE_TRUN MAKE_TYPE_VAL('t', 'r', 'u', 'n')
|
||||||
#define BOX_TYPE_MDAT MAKE_TYPE_VAL('m', 'd', 'a', 't')
|
#define BOX_TYPE_MDAT MAKE_TYPE_VAL('m', 'd', 'a', 't')
|
||||||
|
#define BOX_TYPE_UDTA MAKE_TYPE_VAL('u', 'd', 't', 'a')
|
||||||
|
|
||||||
|
|
||||||
static const value_string box_types[] = {
|
static const value_string box_types[] = {
|
||||||
|
@ -116,6 +120,7 @@ static const value_string box_types[] = {
|
||||||
{ BOX_TYPE_TFHD, "Track Fragment Header Box" },
|
{ BOX_TYPE_TFHD, "Track Fragment Header Box" },
|
||||||
{ BOX_TYPE_TRUN, "Track Fragment Run Box" },
|
{ BOX_TYPE_TRUN, "Track Fragment Run Box" },
|
||||||
{ BOX_TYPE_MDAT, "Media Data Box" },
|
{ BOX_TYPE_MDAT, "Media Data Box" },
|
||||||
|
{ BOX_TYPE_UDTA, "User Data Box" },
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -177,54 +182,68 @@ dissect_mp4_ftyp_body(tvbuff_t *tvb, guint offset, guint len,
|
||||||
return offset-offset_start;
|
return offset-offset_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
/* dissect a box, return its (standard or extended) length or 0 for error */
|
||||||
|
static guint64
|
||||||
dissect_mp4_box(guint32 parent_box_type _U_,
|
dissect_mp4_box(guint32 parent_box_type _U_,
|
||||||
tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
|
tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
|
||||||
{
|
{
|
||||||
guint offset_start;
|
guint offset_start;
|
||||||
guint box_len;
|
guint64 box_size;
|
||||||
guint32 box_type;
|
guint32 box_type;
|
||||||
guint8 *box_type_str;
|
guint8 *box_type_str;
|
||||||
proto_item *pi;
|
proto_item *type_pi, *size_pi;
|
||||||
proto_tree *box_tree;
|
proto_tree *box_tree;
|
||||||
gint ret;
|
guint64 ret;
|
||||||
|
guint body_size;
|
||||||
|
|
||||||
|
|
||||||
offset_start = offset;
|
offset_start = offset;
|
||||||
|
|
||||||
/* the following mechanisms are not supported for now
|
/* the following mechanisms are not supported for now
|
||||||
- extended size (size==1, largesize parameter)
|
|
||||||
- size==0, indicating that the box extends to the end of the file
|
- size==0, indicating that the box extends to the end of the file
|
||||||
- extended box types */
|
- extended box types */
|
||||||
|
|
||||||
box_len = tvb_get_ntohl(tvb, offset);
|
box_size = (guint64)tvb_get_ntohl(tvb, offset);
|
||||||
if (box_len<MIN_BOX_LEN)
|
if (box_size!=BOX_SIZE_EXTENDED && box_size<MIN_BOX_SIZE)
|
||||||
return -1;
|
return 0;
|
||||||
|
|
||||||
box_type = tvb_get_ntohl(tvb, offset+4);
|
box_type = tvb_get_ntohl(tvb, offset+4);
|
||||||
box_type_str = tvb_get_ephemeral_string(tvb, offset+4, 4);
|
box_type_str = tvb_get_ephemeral_string(tvb, offset+4, 4);
|
||||||
|
|
||||||
pi = proto_tree_add_text(tree, tvb, offset, box_len, "%s (%s)",
|
type_pi = proto_tree_add_text(tree, tvb, offset, -1, "%s (%s)",
|
||||||
val_to_str_const(box_type, box_types, "unknown"), box_type_str);
|
val_to_str_const(box_type, box_types, "unknown"), box_type_str);
|
||||||
box_tree = proto_item_add_subtree(pi, ett_mp4_box);
|
box_tree = proto_item_add_subtree(type_pi, ett_mp4_box);
|
||||||
|
|
||||||
proto_tree_add_item(box_tree, hf_mp4_box_size,
|
size_pi = proto_tree_add_item(box_tree, hf_mp4_box_size,
|
||||||
tvb, offset, 4, ENC_BIG_ENDIAN);
|
tvb, offset, 4, ENC_BIG_ENDIAN);
|
||||||
|
if (box_size==BOX_SIZE_EXTENDED)
|
||||||
|
proto_item_append_text(size_pi, " (actual size is in largesize)");
|
||||||
|
|
||||||
offset += 4;
|
offset += 4;
|
||||||
proto_tree_add_item(box_tree, hf_mp4_box_type_str,
|
proto_tree_add_item(box_tree, hf_mp4_box_type_str,
|
||||||
tvb, offset, 4, ENC_ASCII|ENC_NA);
|
tvb, offset, 4, ENC_ASCII|ENC_NA);
|
||||||
offset += 4;
|
offset += 4;
|
||||||
|
|
||||||
|
if (box_size==BOX_SIZE_EXTENDED) {
|
||||||
|
box_size = tvb_get_ntoh64(tvb, offset);
|
||||||
|
proto_tree_add_item(box_tree, hf_mp4_box_largesize,
|
||||||
|
tvb, offset, 8, ENC_BIG_ENDIAN);
|
||||||
|
offset += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
proto_item_set_len(type_pi, (gint)box_size);
|
||||||
|
body_size = box_size - (offset-offset_start);
|
||||||
|
|
||||||
/* XXX - check parent box if supplied */
|
/* XXX - check parent box if supplied */
|
||||||
switch (box_type) {
|
switch (box_type) {
|
||||||
case BOX_TYPE_FTYP:
|
case BOX_TYPE_FTYP:
|
||||||
dissect_mp4_ftyp_body(tvb, offset, box_len-8, pinfo, box_tree);
|
dissect_mp4_ftyp_body(tvb, offset, body_size, pinfo, box_tree);
|
||||||
break;
|
break;
|
||||||
case BOX_TYPE_MVHD:
|
case BOX_TYPE_MVHD:
|
||||||
dissect_mp4_mvhd_body(tvb, offset, box_len-8, pinfo, box_tree);
|
dissect_mp4_mvhd_body(tvb, offset, body_size, pinfo, box_tree);
|
||||||
break;
|
break;
|
||||||
case BOX_TYPE_MFHD:
|
case BOX_TYPE_MFHD:
|
||||||
dissect_mp4_mfhd_body(tvb, offset, box_len-8, pinfo, box_tree);
|
dissect_mp4_mfhd_body(tvb, offset, body_size, pinfo, box_tree);
|
||||||
break;
|
break;
|
||||||
case BOX_TYPE_MOOV:
|
case BOX_TYPE_MOOV:
|
||||||
case BOX_TYPE_MOOF:
|
case BOX_TYPE_MOOF:
|
||||||
|
@ -235,9 +254,10 @@ dissect_mp4_box(guint32 parent_box_type _U_,
|
||||||
case BOX_TYPE_MINF:
|
case BOX_TYPE_MINF:
|
||||||
case BOX_TYPE_MVEX:
|
case BOX_TYPE_MVEX:
|
||||||
case BOX_TYPE_DINF:
|
case BOX_TYPE_DINF:
|
||||||
while (offset-offset_start<box_len) {
|
case BOX_TYPE_UDTA:
|
||||||
|
while (offset-offset_start<box_size) {
|
||||||
ret = dissect_mp4_box(box_type, tvb, offset, pinfo, box_tree);
|
ret = dissect_mp4_box(box_type, tvb, offset, pinfo, box_tree);
|
||||||
if (ret<=0)
|
if (ret==0)
|
||||||
break;
|
break;
|
||||||
offset += ret;
|
offset += ret;
|
||||||
}
|
}
|
||||||
|
@ -246,7 +266,7 @@ dissect_mp4_box(guint32 parent_box_type _U_,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return box_len;
|
return box_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -257,14 +277,15 @@ dissect_mp4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
||||||
guint32 box_type;
|
guint32 box_type;
|
||||||
proto_item *pi;
|
proto_item *pi;
|
||||||
proto_tree *mp4_tree;
|
proto_tree *mp4_tree;
|
||||||
gint ret;
|
guint64 ret;
|
||||||
|
|
||||||
/* to make sure that we have an mp4 file, we check that it starts with
|
/* to make sure that we have an mp4 file, we check that it starts with
|
||||||
a box of a known type
|
a box of a known type
|
||||||
this should be safe as long as the dissector is only called for
|
please note that we do not allow the first box to be an extended box
|
||||||
|
this detection should be safe as long as the dissector is only called for
|
||||||
the video/mp4 mime type
|
the video/mp4 mime type
|
||||||
when we read mp4 files directly, we might need stricter checks here */
|
when we read mp4 files directly, we might need stricter checks here */
|
||||||
if (tvb_reported_length(tvb)<MIN_BOX_LEN)
|
if (tvb_reported_length(tvb)<MIN_BOX_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
box_type = tvb_get_ntohl(tvb, 4);
|
box_type = tvb_get_ntohl(tvb, 4);
|
||||||
if (try_val_to_str(box_type, box_types) == NULL)
|
if (try_val_to_str(box_type, box_types) == NULL)
|
||||||
|
@ -279,7 +300,7 @@ dissect_mp4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
||||||
|
|
||||||
while (tvb_reported_length_remaining(tvb, offset) > 0) {
|
while (tvb_reported_length_remaining(tvb, offset) > 0) {
|
||||||
ret = dissect_mp4_box(BOX_TYPE_NONE, tvb, offset, pinfo, mp4_tree);
|
ret = dissect_mp4_box(BOX_TYPE_NONE, tvb, offset, pinfo, mp4_tree);
|
||||||
if (ret<=0)
|
if (ret==0)
|
||||||
break;
|
break;
|
||||||
offset += ret;
|
offset += ret;
|
||||||
}
|
}
|
||||||
|
@ -297,6 +318,9 @@ proto_register_mp4(void)
|
||||||
{ &hf_mp4_box_type_str,
|
{ &hf_mp4_box_type_str,
|
||||||
{ "Box type", "mp4.box.type_str", FT_STRING, BASE_NONE,
|
{ "Box type", "mp4.box.type_str", FT_STRING, BASE_NONE,
|
||||||
NULL, 0, NULL, HFILL } },
|
NULL, 0, NULL, HFILL } },
|
||||||
|
{ &hf_mp4_box_largesize,
|
||||||
|
{ "Box size (largesize)", "mp4.box.largesize", FT_UINT64, BASE_DEC,
|
||||||
|
NULL, 0, NULL, HFILL } },
|
||||||
{ &hf_mp4_full_box_ver,
|
{ &hf_mp4_full_box_ver,
|
||||||
{ "Box version", "mp4.full_box.version", FT_UINT8, BASE_DEC,
|
{ "Box version", "mp4.full_box.version", FT_UINT8, BASE_DEC,
|
||||||
NULL, 0, NULL, HFILL } },
|
NULL, 0, NULL, HFILL } },
|
||||||
|
|
Loading…
Reference in New Issue