public int bitrate(int i) {
        if (i >= links) {
            return (-1);
        }
        if (!seekable && i != 0) {
            return (bitrate(0));
        }
        if (i < 0) {
            long bits = 0;
            for (int j = 0; j < links; j++) {
                bits += (offsets[j + 1] - dataoffsets[j]) * 8;
            }
            return ((int) Math.rint(bits / time_total(-1)));
        } else {
            if (seekable) {
                // return the actual bitrate
                return ((int) Math.rint((offsets[i + 1] - dataoffsets[i]) * 8 / time_total(i)));
            } else {
                // return nominal if set
                if (vi[i].bitrate_nominal > 0) {
                    return vi[i].bitrate_nominal;
                } else {
                    if (vi[i].bitrate_upper > 0) {
                        if (vi[i].bitrate_lower > 0) {
                            return (vi[i].bitrate_upper + vi[i].bitrate_lower) / 2;
                        } else {
                            return vi[i].bitrate_upper;
                        }
                    }
                    return (-1);
                }
            }
        }
    }