aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/file-mp4.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/file-mp4.c')
-rw-r--r--epan/dissectors/file-mp4.c301
1 files changed, 229 insertions, 72 deletions
diff --git a/epan/dissectors/file-mp4.c b/epan/dissectors/file-mp4.c
index 2725675d2c..0d1888f913 100644
--- a/epan/dissectors/file-mp4.c
+++ b/epan/dissectors/file-mp4.c
@@ -12,6 +12,7 @@
/* this dissector is based on
* ISO/IEC 14496-12 (ISO base media file format) and
* ISO/IEC 14496-14 (MP4 file format)
+ * 3GPP TS 26.244 (Adaptive-Streaming profile)
*
* at the moment, it dissects the basic box structure and the payload of
* some simple boxes */
@@ -24,6 +25,7 @@
#include <epan/packet.h>
#include <epan/to_str.h>
#include <epan/expert.h>
+#include <wiretap/wtap.h>
#define MAKE_TYPE_VAL(a, b, c, d) ((a)<<24 | (b)<<16 | (c)<<8 | (d))
@@ -36,71 +38,94 @@
void proto_register_mp4(void);
void proto_reg_handoff_mp4(void);
+static dissector_handle_t mp4_handle;
+
static gint dissect_mp4_box(guint32 parent_box_type _U_, guint depth,
tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree);
-static int proto_mp4 = -1;
-
-static gint ett_mp4 = -1;
-static gint ett_mp4_box = -1;
-static gint ett_mp4_full_box_flags = -1;
-static gint ett_mp4_entry = -1;
-
-static int hf_mp4_box_size = -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_flags = -1;
-static int hf_mp4_ftyp_brand = -1;
-static int hf_mp4_ftyp_ver = -1;
-static int hf_mp4_ftyp_add_brand = -1;
-static int hf_mp4_stsz_sample_size = -1;
-static int hf_mp4_stsz_sample_count = -1;
-static int hf_mp4_stsz_entry_size = -1;
-static int hf_mp4_stsc_entry_count = -1;
-static int hf_mp4_stsc_first_chunk = -1;
-static int hf_mp4_stsc_samples_per_chunk = -1;
-static int hf_mp4_stsc_sample_description_index = -1;
-static int hf_mp4_stco_entry_cnt = -1;
-static int hf_mp4_stco_chunk_offset = -1;
-static int hf_mp4_mvhd_creat_time = -1;
-static int hf_mp4_mvhd_mod_time = -1;
-static int hf_mp4_mvhd_timescale = -1;
-static int hf_mp4_mvhd_duration = -1;
-static int hf_mp4_mvhd_rate = -1;
-static int hf_mp4_mvhd_vol = -1;
-static int hf_mp4_mvhd_next_tid = -1;
-static int hf_mp4_mfhd_seq_num = -1;
-static int hf_mp4_tkhd_flags_enabled = -1;
-static int hf_mp4_tkhd_flags_in_movie = -1;
-static int hf_mp4_tkhd_flags_in_preview = -1;
-static int hf_mp4_tkhd_flags_size_is_aspect_ratio = -1;
-static int hf_mp4_tkhd_creat_time = -1;
-static int hf_mp4_tkhd_mod_time = -1;
-static int hf_mp4_tkhd_track_id = -1;
-static int hf_mp4_tkhd_duration = -1;
-static int hf_mp4_tkhd_width = -1;
-static int hf_mp4_tkhd_height = -1;
-static int hf_mp4_hdlr_type = -1;
-static int hf_mp4_hdlr_name = -1;
-static int hf_mp4_dref_entry_cnt = -1;
-static int hf_mp4_stsd_entry_cnt = -1;
-static int hf_mp4_url_flags_media_data_location = -1;
-static int hf_mp4_stts_entry_cnt = -1;
-static int hf_mp4_stts_sample_count = -1;
-static int hf_mp4_stts_sample_delta = -1;
-static int hf_mp4_ctts_sample_count = -1;
-static int hf_mp4_ctts_sample_offset_signed = -1;
-static int hf_mp4_ctts_sample_offset_unsigned = -1;
-static int hf_mp4_elst_entry_cnt = -1;
-static int hf_mp4_elst_segment_duration = -1;
-static int hf_mp4_elst_media_time = -1;
-static int hf_mp4_elst_media_rate_integer = -1;
-static int hf_mp4_elst_media_rate_fraction = -1;
-
-static expert_field ei_mp4_box_too_large = EI_INIT;
-static expert_field ei_mp4_too_many_rec_lvls = EI_INIT;
-static expert_field ei_mp4_mvhd_next_tid_unknown = EI_INIT;
+static int proto_mp4;
+
+static gint ett_mp4;
+static gint ett_mp4_box;
+static gint ett_mp4_full_box_flags;
+static gint ett_mp4_entry;
+
+static int hf_mp4_box_size;
+static int hf_mp4_box_type_str;
+static int hf_mp4_box_largesize;
+static int hf_mp4_full_box_ver;
+static int hf_mp4_full_box_flags;
+static int hf_mp4_ftyp_brand;
+static int hf_mp4_ftyp_ver;
+static int hf_mp4_ftyp_add_brand;
+static int hf_mp4_stsz_sample_size;
+static int hf_mp4_stsz_sample_count;
+static int hf_mp4_stsz_entry_size;
+static int hf_mp4_stsc_entry_count;
+static int hf_mp4_stsc_first_chunk;
+static int hf_mp4_stsc_samples_per_chunk;
+static int hf_mp4_stsc_sample_description_index;
+static int hf_mp4_stco_entry_cnt;
+static int hf_mp4_stco_chunk_offset;
+static int hf_mp4_mvhd_creat_time;
+static int hf_mp4_mvhd_mod_time;
+static int hf_mp4_mvhd_timescale;
+static int hf_mp4_mvhd_duration;
+static int hf_mp4_mvhd_rate;
+static int hf_mp4_mvhd_vol;
+static int hf_mp4_mvhd_next_tid;
+static int hf_mp4_mfhd_seq_num;
+static int hf_mp4_tkhd_flags_enabled;
+static int hf_mp4_tkhd_flags_in_movie;
+static int hf_mp4_tkhd_flags_in_preview;
+static int hf_mp4_tkhd_flags_size_is_aspect_ratio;
+static int hf_mp4_tkhd_creat_time;
+static int hf_mp4_tkhd_mod_time;
+static int hf_mp4_tkhd_track_id;
+static int hf_mp4_tkhd_duration;
+static int hf_mp4_tkhd_width;
+static int hf_mp4_tkhd_height;
+static int hf_mp4_hdlr_type;
+static int hf_mp4_hdlr_name;
+static int hf_mp4_dref_entry_cnt;
+static int hf_mp4_stsd_entry_cnt;
+static int hf_mp4_url_flags_media_data_location;
+static int hf_mp4_stts_entry_cnt;
+static int hf_mp4_stts_sample_count;
+static int hf_mp4_stts_sample_delta;
+static int hf_mp4_ctts_sample_count;
+static int hf_mp4_ctts_sample_offset_signed;
+static int hf_mp4_ctts_sample_offset_unsigned;
+static int hf_mp4_elst_entry_cnt;
+static int hf_mp4_elst_segment_duration;
+static int hf_mp4_elst_media_time;
+static int hf_mp4_elst_media_rate_integer;
+static int hf_mp4_elst_media_rate_fraction;
+static int hf_mp4_sidx_reference_id;
+static int hf_mp4_sidx_timescale;
+static int hf_mp4_sidx_earliest_presentation_time_v0;
+static int hf_mp4_sidx_first_offset_v0;
+static int hf_mp4_sidx_earliest_presentation_time;
+static int hf_mp4_sidx_first_offset;
+static int hf_mp4_sidx_reserved;
+static int hf_mp4_sidx_entry_cnt;
+static int hf_mp4_sidx_reference_type;
+static int hf_mp4_sidx_reference_size;
+static int hf_mp4_sidx_subsegment_duration;
+static int hf_mp4_sidx_starts_with_sap;
+static int hf_mp4_sidx_sap_type;
+static int hf_mp4_sidx_sap_delta_time;
+
+static const value_string mp4_sidx_reference_type_vals[] = {
+ { 0, "Movie" },
+ { 1, "Index" },
+
+ { 0, NULL }
+};
+
+static expert_field ei_mp4_box_too_large;
+static expert_field ei_mp4_too_many_rec_lvls;
+static expert_field ei_mp4_mvhd_next_tid_unknown;
static guint32 mvhd_timescale = 0;
@@ -150,6 +175,8 @@ static guint32 mvhd_timescale = 0;
#define BOX_TYPE_URL_ MAKE_TYPE_VAL('u', 'r', 'l', ' ')
#define BOX_TYPE_EDTS MAKE_TYPE_VAL('e', 'd', 't', 's')
#define BOX_TYPE_ELST MAKE_TYPE_VAL('e', 'l', 's', 't')
+#define BOX_TYPE_SIDX MAKE_TYPE_VAL('s', 'i', 'd', 'x')
+#define BOX_TYPE_STYP MAKE_TYPE_VAL('s', 't', 'y', 'p')
#define TKHD_FLAG_ENABLED 0x000001
#define TKHD_FLAG_IN_MOVIE 0x000002
@@ -195,6 +222,8 @@ static const value_string box_types[] = {
{ BOX_TYPE_URL_, "URL Box" },
{ BOX_TYPE_EDTS, "Edit Box" },
{ BOX_TYPE_ELST, "Edit List Box" },
+ { BOX_TYPE_SIDX, "Segment Index Box"},
+ { BOX_TYPE_STYP, "Segment Type Box" },
{ 0, NULL }
};
@@ -290,12 +319,12 @@ dissect_mp4_mvhd_body(tvbuff_t *tvb, gint offset, gint len _U_,
if (mvhd_timescale == 0) {
proto_tree_add_uint64_format(tree, hf_mp4_mvhd_duration,
tvb, offset, time_len, duration,
- "Duration: no timescale (%" G_GUINT64_FORMAT ")",
+ "Duration: no timescale (%" PRIu64 ")",
duration);
} else {
proto_tree_add_uint64_format(tree, hf_mp4_mvhd_duration,
tvb, offset, time_len, duration,
- "Duration: %f seconds (%" G_GUINT64_FORMAT ")",
+ "Duration: %f seconds (%" PRIu64 ")",
(double) duration / mvhd_timescale, duration);
}
offset += time_len;
@@ -416,7 +445,7 @@ dissect_mp4_ftyp_body(tvbuff_t *tvb, gint offset, gint len,
offset_start = offset;
proto_tree_add_item(tree, hf_mp4_ftyp_brand,
- tvb, offset, 4, ENC_ASCII|ENC_NA);
+ tvb, offset, 4, ENC_ASCII);
offset += 4;
proto_tree_add_item(tree, hf_mp4_ftyp_ver,
tvb, offset, 4, ENC_BIG_ENDIAN);
@@ -424,7 +453,7 @@ dissect_mp4_ftyp_body(tvbuff_t *tvb, gint offset, gint len,
while ((offset-offset_start) < len) {
proto_tree_add_item(tree, hf_mp4_ftyp_add_brand,
- tvb, offset, 4, ENC_ASCII|ENC_NA);
+ tvb, offset, 4, ENC_ASCII);
offset += 4;
}
@@ -532,7 +561,7 @@ dissect_mp4_hdlr_body(tvbuff_t *tvb, gint offset, gint len _U_,
offset += 4; /* four reserved 0 bytes */
proto_tree_add_item(tree, hf_mp4_hdlr_type,
- tvb, offset, 4, ENC_ASCII|ENC_NA);
+ tvb, offset, 4, ENC_ASCII);
offset += 4;
offset += 12; /* 3x32bit reserved */
@@ -540,7 +569,7 @@ dissect_mp4_hdlr_body(tvbuff_t *tvb, gint offset, gint len _U_,
/* name is a 0-terminated UTF-8 string, len includes the final 0 */
hdlr_name_len = tvb_strsize(tvb, offset);
proto_tree_add_item(tree, hf_mp4_hdlr_name,
- tvb, offset, hdlr_name_len, ENC_UTF_8|ENC_NA);
+ tvb, offset, hdlr_name_len, ENC_UTF_8);
offset += hdlr_name_len;
return offset-offset_start;
@@ -548,6 +577,7 @@ dissect_mp4_hdlr_body(tvbuff_t *tvb, gint offset, gint len _U_,
static gint
+// NOLINTNEXTLINE(misc-no-recursion)
dissect_mp4_dref_body(tvbuff_t *tvb, gint offset, gint len _U_,
packet_info *pinfo, guint depth, proto_tree *tree)
{
@@ -604,6 +634,7 @@ dissect_mp4_url_body(tvbuff_t *tvb, gint offset, gint len,
static gint
+// NOLINTNEXTLINE(misc-no-recursion)
dissect_mp4_stsd_body(tvbuff_t *tvb, gint offset, gint len,
packet_info *pinfo, guint depth, proto_tree *tree)
{
@@ -785,7 +816,7 @@ dissect_mp4_elst_body(tvbuff_t *tvb, gint offset, gint len,
segment_duration_str = timescaled_val_to_str(pinfo->pool, segment_duration);
proto_tree_add_uint64_format(subtree, hf_mp4_elst_segment_duration,
tvb, offset, field_length, segment_duration,
- "Segment duration: %s (%" G_GUINT64_FORMAT ")",
+ "Segment duration: %s (%" PRIu64 ")",
segment_duration_str, segment_duration);
offset += field_length;
@@ -797,7 +828,7 @@ dissect_mp4_elst_body(tvbuff_t *tvb, gint offset, gint len,
media_time_str = timescaled_val_to_str(pinfo->pool, media_time);
proto_tree_add_int64_format(subtree, hf_mp4_elst_media_time,
tvb, offset, field_length, media_time,
- "Media time: %s (%" G_GINT64_FORMAT ")",
+ "Media time: %s (%" PRId64 ")",
media_time_str, media_time);
offset += field_length;
@@ -817,9 +848,87 @@ dissect_mp4_elst_body(tvbuff_t *tvb, gint offset, gint len,
return len;
}
+/* 3GPP TS 26.244 version 16.1.0 Release 16: 13.4 Segment Index Box */
+static gint
+dissect_mp4_sidx_body(tvbuff_t *tvb, gint offset, gint len _U_,
+ packet_info *pinfo _U_, guint depth _U_, proto_tree *tree)
+{
+ guint8 version;
+ gint offset_start;
+ guint16 entry_cnt, i;
+
+ offset_start = offset;
+
+ offset += dissect_mp4_full_box (tvb, offset, tree, NULL, &version, NULL);
+
+ proto_tree_add_item(tree, hf_mp4_sidx_reference_id,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_mp4_sidx_timescale,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ if (version == 0) {
+ proto_tree_add_item(tree, hf_mp4_sidx_earliest_presentation_time_v0,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_mp4_sidx_first_offset_v0,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ } else {
+ proto_tree_add_item(tree, hf_mp4_sidx_earliest_presentation_time,
+ tvb, offset, 8, ENC_BIG_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(tree, hf_mp4_sidx_first_offset,
+ tvb, offset, 8, ENC_BIG_ENDIAN);
+ offset += 8;
+ }
+
+ proto_tree_add_item(tree, hf_mp4_sidx_reserved,
+ tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ entry_cnt = tvb_get_guint16(tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(tree, hf_mp4_sidx_entry_cnt,
+ tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ for(i=1; i<=entry_cnt; i++) {
+ proto_tree *subtree;
+ proto_item *subtree_item;
+
+ subtree = proto_tree_add_subtree_format (tree, tvb, offset, 8,
+ ett_mp4_entry, &subtree_item, "Entry %u:", i);
+
+ proto_tree_add_item(subtree, hf_mp4_sidx_reference_type,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(subtree, hf_mp4_sidx_reference_size,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(subtree, hf_mp4_sidx_subsegment_duration,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(subtree, hf_mp4_sidx_starts_with_sap,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(subtree, hf_mp4_sidx_sap_type,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ proto_tree_add_item(subtree, hf_mp4_sidx_sap_delta_time,
+ tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ }
+
+ return offset-offset_start;
+}
+
/* dissect a box, return its (standard or extended) length or 0 for error
depth is the recursion level of the parent box */
static gint
+// NOLINTNEXTLINE(misc-no-recursion)
dissect_mp4_box(guint32 parent_box_type _U_, guint depth,
tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree)
{
@@ -857,7 +966,7 @@ dissect_mp4_box(guint32 parent_box_type _U_, guint depth,
offset += 4;
proto_tree_add_item(box_tree, hf_mp4_box_type_str,
- tvb, offset, 4, ENC_ASCII|ENC_NA);
+ tvb, offset, 4, ENC_ASCII);
offset += 4;
if (box_size == BOX_SIZE_EXTENDED) {
@@ -888,7 +997,9 @@ dissect_mp4_box(guint32 parent_box_type _U_, guint depth,
/* XXX - check parent box if supplied */
switch (box_type) {
+ /* As per 3GPP TS 26.244 styp and ftyp boxes have the same format*/
case BOX_TYPE_FTYP:
+ case BOX_TYPE_STYP:
dissect_mp4_ftyp_body(tvb, offset, body_size, pinfo, depth, box_tree);
break;
case BOX_TYPE_MVHD:
@@ -930,6 +1041,9 @@ dissect_mp4_box(guint32 parent_box_type _U_, guint depth,
case BOX_TYPE_ELST:
dissect_mp4_elst_body(tvb, offset, body_size, pinfo, depth, box_tree);
break;
+ case BOX_TYPE_SIDX:
+ dissect_mp4_sidx_body(tvb, offset, body_size, pinfo, depth, box_tree);
+ break;
case BOX_TYPE_MOOV:
case BOX_TYPE_MOOF:
case BOX_TYPE_STBL:
@@ -1152,6 +1266,48 @@ proto_register_mp4(void)
{ &hf_mp4_elst_media_rate_fraction,
{ "Media rate fraction", "mp4.elst.media_rate_fraction", FT_INT16,
BASE_DEC, NULL, 0, NULL, HFILL } },
+ { &hf_mp4_sidx_reference_id,
+ { "Reference ID", "mp4.sidx.reference_id", FT_UINT32,
+ BASE_DEC, NULL, 0, NULL, HFILL } },
+ { &hf_mp4_sidx_timescale,
+ { "Timescale", "mp4.sidx.timescale", FT_UINT32,
+ BASE_DEC, NULL, 0, NULL, HFILL } },
+ { &hf_mp4_sidx_earliest_presentation_time_v0,
+ { "Earliest Presentation Time", "mp4.sidx.earliest_presentation_time", FT_UINT32,
+ BASE_DEC, NULL, 0, NULL, HFILL } },
+ { &hf_mp4_sidx_first_offset_v0,
+ { "First Offset", "mp4.sidx.first_offset", FT_UINT32,
+ BASE_DEC, NULL, 0, NULL, HFILL } },
+ { &hf_mp4_sidx_earliest_presentation_time,
+ { "Earliest Presentation Time", "mp4.sidx.earliest_presentation_time", FT_UINT64,
+ BASE_DEC, NULL, 0, NULL, HFILL } },
+ { &hf_mp4_sidx_first_offset,
+ { "First Offset", "mp4.sidx.first_offset", FT_UINT64,
+ BASE_DEC, NULL, 0, NULL, HFILL } },
+ { &hf_mp4_sidx_reserved,
+ { "Reserved", "mp4.sidx.reserved", FT_UINT16,
+ BASE_HEX, NULL, 0, NULL, HFILL } },
+ { &hf_mp4_sidx_entry_cnt,
+ { "Number of entries", "mp4.sidx.entry_count", FT_UINT16,
+ BASE_DEC, NULL, 0, NULL, HFILL } },
+ { &hf_mp4_sidx_reference_type,
+ { "Reference Type", "mp4.sidx.reference_type", FT_UINT32,
+ BASE_DEC, VALS(mp4_sidx_reference_type_vals), 0x80000000, NULL, HFILL } },
+ { &hf_mp4_sidx_reference_size,
+ { "Reference size", "mp4.sidx.reference_size", FT_UINT32,
+ BASE_DEC, NULL, 0x7FFFFFFF, NULL, HFILL } },
+ { &hf_mp4_sidx_subsegment_duration,
+ { "Segment duration", "mp4.sidx.subsegment_duration", FT_UINT32,
+ BASE_DEC, NULL, 0, NULL, HFILL } },
+ { &hf_mp4_sidx_starts_with_sap,
+ { "Starts With SAP", "mp4.sidx.starts_with_sap", FT_BOOLEAN,
+ 32, NULL, 0x80000000, NULL, HFILL } },
+ { &hf_mp4_sidx_sap_type,
+ { "SAP Type", "mp4.sidx.sap_type", FT_UINT32,
+ BASE_DEC, NULL, 0x70000000, NULL, HFILL } },
+ { &hf_mp4_sidx_sap_delta_time,
+ { "SAP Delta Time", "mp4.sidx.sap_delta_time", FT_UINT32,
+ BASE_DEC, NULL, 0x0FFFFFFF, NULL, HFILL } },
};
static gint *ett[] = {
@@ -1181,12 +1337,13 @@ proto_register_mp4(void)
proto_register_subtree_array(ett, array_length(ett));
expert_mp4 = expert_register_protocol(proto_mp4);
expert_register_field_array(expert_mp4, ei, array_length(ei));
+
+ mp4_handle = register_dissector("mp4", dissect_mp4, proto_mp4);
}
void
proto_reg_handoff_mp4(void)
{
- dissector_handle_t mp4_handle = create_dissector_handle(dissect_mp4, proto_mp4);
dissector_add_string("media_type", "video/mp4", mp4_handle);
dissector_add_string("media_type", "audio/mp4", mp4_handle);
dissector_add_uint("wtap_encap", WTAP_ENCAP_MP4, mp4_handle);