+ int i;
+ uint64_t size = aac_read_int32(buf);
+
+ memcpy(type, buf + 4, 4);
+ type[4] = '\0';
+
+ PARA_DEBUG_LOG("size: %llu, type: %s\n", (long long unsigned)size, type);
+ if (size != 1) {
+ *subsize = size;
+ return 8;
+ }
+ buf += 4;
+ size = 0;
+ for (i = 0; i < 8; i++)
+ size |= ((uint64_t)buf[i]) << ((7 - i) * 8);
+ *subsize = size;
+ return 16;
+}
+
+static char *get_tag(unsigned char *p, int size)
+{
+ char *buf;
+
+ assert(size > 0);
+ buf = para_malloc(size + 1);
+
+ memcpy(buf, p, size);
+ buf[size] = '\0';
+ PARA_DEBUG_LOG("size: %d: %s\n", size, buf);
+ return buf;
+}
+
+static void read_tags(unsigned char *buf, size_t buflen, struct afh_info *afhi)
+{
+ unsigned char *p = buf;
+
+ while (p + 32 < buf + buflen) {
+ unsigned char *q, type1[5], type2[5];
+ uint64_t size1, size2;
+ int ret, ret2;
+
+ ret = read_atom_header(p, &size1, type1);
+ ret2 = read_atom_header(p + ret, &size2, type2);
+
+ if (size2 <= 16 || atom_cmp(type2, "data")) {
+ p += size1;
+ continue;
+ }
+ size2 -= 16;
+ q = p + ret + ret2 + 8;
+ if (q + size2 > buf + buflen)
+ break;
+ if (!atom_cmp(type1, "\xa9" "ART"))
+ afhi->tags.artist = get_tag(q, size2);
+ else if (!atom_cmp(type1, "\xa9" "alb"))
+ afhi->tags.album = get_tag(q, size2);
+ else if (!atom_cmp(type1, "\xa9" "nam"))
+ afhi->tags.title = get_tag(q, size2);
+ else if (!atom_cmp(type1, "\xa9" "cmt"))
+ afhi->tags.comment = get_tag(q, size2);
+ else if (!atom_cmp(type1, "\xa9" "day"))
+ afhi->tags.year = get_tag(q, size2);
+ p += size1;
+ }
+}
+
+static void read_meta(unsigned char *buf, size_t buflen, struct afh_info *afhi)
+{
+ unsigned char *p = buf;
+
+ while (p + 4 < buf + buflen) {
+
+ if (p[0] != 'i' || p[1] != 'l' || p[2] != 's' || p[3] != 't') {
+ p++;
+ continue;
+ }
+ p += 4;
+ return read_tags(p, buflen - (p - buf), afhi);
+ }
+}