MP4: add support for segment boxes (styp, sidx)

sidx and styp boxes are implemented according to 3GPP TS 26.244
Both boxes are added as mp4 magic bytes due to mp4 segments start from them

pcap and mp4 samples: https://wiki.wireshark.org/SampleCaptures#mp4-init-segments-and-segments
This commit is contained in:
Sergey V. Lobanov 2023-01-13 10:58:12 +01:00 committed by John Thacker
parent 776aafc7de
commit 4d2d0b7f6d
2 changed files with 155 additions and 1 deletions

View File

@ -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 */
@ -97,6 +98,27 @@ 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 int hf_mp4_sidx_reference_id = -1;
static int hf_mp4_sidx_timescale = -1;
static int hf_mp4_sidx_earliest_presentation_time_v0 = -1;
static int hf_mp4_sidx_first_offset_v0 = -1;
static int hf_mp4_sidx_earliest_presentation_time = -1;
static int hf_mp4_sidx_first_offset = -1;
static int hf_mp4_sidx_reserved = -1;
static int hf_mp4_sidx_entry_cnt = -1;
static int hf_mp4_sidx_reference_type = -1;
static int hf_mp4_sidx_reference_size = -1;
static int hf_mp4_sidx_subsegment_duration = -1;
static int hf_mp4_sidx_starts_with_sap = -1;
static int hf_mp4_sidx_sap_type = -1;
static int hf_mp4_sidx_sap_delta_time = -1;
static const value_string mp4_sidx_reference_type_vals[] = {
{ 0, "Movie" },
{ 1, "Index" },
{ 0, NULL }
};
static expert_field ei_mp4_box_too_large = EI_INIT;
static expert_field ei_mp4_too_many_rec_lvls = EI_INIT;
@ -150,6 +172,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 +219,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 }
};
@ -817,6 +843,83 @@ 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
@ -888,7 +991,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 +1035,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 +1260,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[] = {

View File

@ -15,6 +15,8 @@
#include "wtap-int.h"
static const guint8 mp4_magic[] = { 'f', 't', 'y', 'p' };
static const guint8 mp4_magic_sidx[] = { 's', 'i', 'd', 'x' };
static const guint8 mp4_magic_styp[] = { 's', 't', 'y', 'p' };
static int mp4_file_type_subtype = -1;
@ -36,7 +38,9 @@ mp4_open(wtap *wth, int *err, gchar **err_info)
return WTAP_OPEN_NOT_MINE;
if (bytes_read == sizeof (magic_buf) &&
memcmp(magic_buf + 4, mp4_magic, sizeof (mp4_magic)))
memcmp(magic_buf + 4, mp4_magic, sizeof (mp4_magic)) &&
memcmp(magic_buf + 4, mp4_magic_sidx, sizeof (mp4_magic_sidx)) &&
memcmp(magic_buf + 4, mp4_magic_styp, sizeof (mp4_magic_styp)))
return WTAP_OPEN_NOT_MINE;
if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)