+ return ret;
+
+ ret = -E_MP4_BAD_SAMPLERATE;
+ rv = mp4_get_sample_rate(c->mp4, c->track);
+ if (rv <= 0)
+ goto close;
+ afhi->frequency = rv;
+
+ ret = -E_MP4_BAD_CHANNEL_COUNT;
+ rv = mp4_get_channel_count(c->mp4, c->track);
+ if (rv <= 0)
+ goto close;
+ afhi->channels = rv;
+
+ ret = -E_MP4_BAD_SAMPLE_COUNT;
+ rv = mp4_num_samples(c->mp4, c->track);
+ if (rv <= 0)
+ goto close;
+ afhi->chunks_total = rv;
+ afhi->max_chunk_size = 0;
+ for (n = 0; n < afhi->chunks_total; n++) {
+ if (aac_afh_get_chunk(n, c, &buf, &len) < 0)
+ break;
+ afhi->max_chunk_size = PARA_MAX(afhi->max_chunk_size, len);
+ }
+ milliseconds = mp4_get_duration(c->mp4, c->track);
+ afhi->seconds_total = milliseconds / 1000;
+ ms2tv(milliseconds / afhi->chunks_total, &afhi->chunk_tv);
+ if (aac_afh_get_chunk(0, c, &buf, &len) >= 0)
+ numbytes -= buf - map;
+ afhi->bitrate = 8 * numbytes / afhi->seconds_total / 1000;
+ _aac_afh_get_taginfo(c->mp4, &afhi->tags);
+ ret = 1;
+close:
+ aac_afh_close(c);
+ return ret;
+}
+
+static uint32_t aac_afh_meta_read_cb(void *user_data, void *dest, uint32_t want)
+{
+ int fd = *(int *)user_data;
+ return read(fd, dest, want);
+}
+
+static uint32_t aac_afh_meta_seek_cb(void *user_data, uint64_t pos)
+{
+ int fd = *(int *)user_data;
+ return lseek(fd, pos, SEEK_SET);
+}
+
+static uint32_t aac_afh_meta_write_cb(void *user_data, void *dest, uint32_t want)
+{
+ int fd = *(int *)user_data;
+ return write(fd, dest, want);
+}
+
+static uint32_t aac_afh_meta_truncate_cb(void *user_data)
+{
+ int fd = *(int *)user_data;
+ off_t offset = lseek(fd, 0, SEEK_CUR);
+ return ftruncate(fd, offset);
+}
+
+static void replace_tag(struct mp4_tag *tag, const char *new_val, bool *found)
+{
+ free(tag->value);
+ tag->value = para_strdup(new_val);
+ *found = true;
+}
+
+static void add_tag(struct mp4_metadata *md, const char *item, const char *value)
+{
+ md->tags[md->count].item = para_strdup(item);
+ md->tags[md->count].value = para_strdup(value);
+ md->count++;
+}
+
+static int aac_afh_rewrite_tags(const char *map, size_t mapsize,
+ struct taginfo *tags, int fd, __a_unused const char *filename)
+{
+ int ret, i;
+ int32_t rv;
+ struct mp4_metadata metadata;
+ struct mp4 *mp4;
+ struct mp4_callback cb = {
+ .read = aac_afh_meta_read_cb,
+ .seek = aac_afh_meta_seek_cb,
+ .write = aac_afh_meta_write_cb,
+ .truncate = aac_afh_meta_truncate_cb,
+ .user_data = &fd
+ };
+ bool found_artist = false, found_title = false, found_album = false,
+ found_year = false, found_comment = false;
+
+ ret = write_all(fd, map, mapsize);