static gboolean dissect_mpeg_audio_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint32 h; struct mpa mpa; int data_size = 0; asn1_ctx_t asn1_ctx; int offset = 0; static const char *version_names[] = { "1", "2", "2.5" }; if (!tvb_bytes_exist(tvb, 0, 4)) return FALSE; /* not enough data for an MPEG audio frame */ h = tvb_get_ntohl(tvb, 0); MPA_UNMARSHAL(&mpa, h); if (!MPA_SYNC_VALID(&mpa)) return FALSE; if (!MPA_VERSION_VALID(&mpa)) return FALSE; if (!MPA_LAYER_VALID(&mpa)) return FALSE; col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "MPEG-%s", version_names[mpa_version(&mpa)]); col_add_fstr(pinfo->cinfo, COL_INFO, "Audio Layer %d", mpa_layer(&mpa) + 1); if (MPA_BITRATE_VALID(&mpa) && MPA_FREQUENCY_VALID(&mpa)) { data_size = (int)(MPA_DATA_BYTES(&mpa) - sizeof mpa); if (check_col(pinfo->cinfo, COL_DEF_SRC)) { SET_ADDRESS(&pinfo->src, AT_NONE, 0, NULL); col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "%d kb/s", mpa_bitrate(&mpa) / 1000); } if (check_col(pinfo->cinfo, COL_DEF_DST)) { SET_ADDRESS(&pinfo->dst, AT_NONE, 0, NULL); col_add_fstr(pinfo->cinfo, COL_DEF_DST, "%g kHz", mpa_frequency(&mpa) / (float)1000); } } if (tree == NULL) return TRUE; asn1_ctx_init(&asn1_ctx, ASN1_ENC_PER, TRUE, pinfo); offset = dissect_mpeg_audio_Audio(tvb, offset, &asn1_ctx, tree, proto_mpeg_audio); if (data_size > 0) { unsigned int padding; proto_tree_add_item(tree, hf_mpeg_audio_data, tvb, offset / 8, data_size, ENC_NA); offset += data_size * 8; padding = mpa_padding(&mpa); if (padding > 0) { proto_tree_add_item(tree, hf_mpeg_audio_padbytes, tvb, offset / 8, padding, ENC_NA); } } return TRUE; }
unsigned mpa_samples(const struct mpa *mpa) { return mpa_samples_data[mpa_versions[mpa->version]][mpa_layer(mpa)]; }