public HashMap parse_vorbis_comment(RandomAccessFile fh, PageInfo.PageParser pp, long offset, long payload_len) throws IOException {
		HashMap tags = new HashMap();
		long last_byte = offset + payload_len;

		// skip vendor string in format: [LEN][VENDOR_STRING] -> 4 = LEN = 32bit int
		offset += 4 + raf2le32(fh, offset);

		// we can now read the number of comments in this file, we will also
		// adjust offset to point to the value after this 32bit int
		int comments = raf2le32(fh, offset);
		offset += 4;

		for ( ; comments > 0; comments--) {
			int comment_len = raf2le32(fh, offset);
			offset += 4;
			long can_read = last_byte - offset; // indicates the last byte of this page
			int do_read  = (int)(can_read > comment_len ? comment_len : can_read); // how much data is readable in this page

			if (do_read >= 3) {
				int bsize = (do_read > MAX_COMMENT_SIZE ? MAX_COMMENT_SIZE : do_read);
				byte[] data = new byte[bsize];
				fh.seek(offset);
				fh.read(data);
				String   tag_raw = new String(data);
				String[] tag_vec = tag_raw.split("=", 2);
				String   tag_key = tag_vec[0].toUpperCase();
				addTagEntry(tags, tag_key, tag_vec[1]);
			}

			// set offset to begin of next tag (OR the end of this page!)
			offset += do_read;

			// We hit the end of a stream
			// this is most likely due to the fact that we cropped do_read to not cross
			// the page boundary -> we must now calculate the position of the next tag
			if (offset == last_byte) {
				int partial_cruft = comment_len - do_read; // how many bytes we did not read
				while(partial_cruft > 0) {
					PageInfo pi = pp.parse_stream_page(fh, last_byte);
					if (pi.header_len <1 || pi.payload_len < 1)
						xdie("Data from callback doesnt make much sense");

					offset += pi.header_len;             // move position behind page header
					last_byte = offset + pi.payload_len; // and adjust the last byte to pos + payload_size

					if (offset+partial_cruft < last_byte) {
						offset += partial_cruft; // partial data ends in this block: just adjust the ofset
						break;
					} else {
						// this page just contains data from the partial tag -> skip to next one
						offset = last_byte;
						partial_cruft -= pi.payload_len;
					}
				}
			}
		}
		return tags;
	}