/* * Copyright (c) 2011 Michael Zucchi * * This file is part of jjmpeg, a java binding to ffmpeg's libraries. * * jjmpeg is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * jjmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with jjmpeg. If not, see <http://www.gnu.org/licenses/>. */ package au.notzed.jjmpeg; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.LongBuffer; /** * * @author notzed */ public class AVRational extends AVRationalAbstract { protected AVRational(ByteBuffer p) { setNative(new AVRationalNative(this, p)); } static AVRational create(ByteBuffer p) { return new AVRational(p); } static AVRational create(int num, int den) { // since it's so simple we can create this ourselves ByteBuffer b = ByteBuffer.allocateDirect(8).order(ByteOrder.nativeOrder()); b.asIntBuffer().put(num).put(den).rewind(); return create(b); } public static final AVRational AV_TIME_BASE_Q = create(1, 1000000); public double q2d() { return (double) getNum() / (double) getDen(); } static public long rescaleQ(long a, AVRational bq, AVRational cq) { return AVRationalNative.jjRescaleQ(a, bq.n.p, cq.n.p); } /** * Perform v * (num * s) / den * @param v * @param s * @return */ public long scale(long v, int s) { return starSlash(v, (long)getNum() * (long)s, getDen()); } /** * Performs A * B / C, where A * B is treated as 128 bit * @param a * @param b * @param c * @return */ static public long starSlash(long a, long b, long c) { // lazy today .. just use BigInteger, even if it's SAF byte[] longBytes = new byte[8]; LongBuffer lb = ByteBuffer.wrap(longBytes).asLongBuffer(); lb.put(0, a); BigInteger A = new BigInteger(longBytes); lb.put(0, b); BigInteger B = new BigInteger(longBytes); lb.put(0, c); BigInteger C = new BigInteger(longBytes); long res = A.multiply(B).divide(C).longValue(); //System.out.printf("%d * %d / %d = %d ? %d ? %d\n", a, b, c, res, a * b / c, a * b); //System.out.printf("%d * %d / %d = %d\n", A.longValue(), B.longValue(), C.longValue(), res); return res; } } class AVRationalNative extends AVRationalNativeAbstract { AVRationalNative(AVObject o, ByteBuffer p) { super(o, p); } // perhapd implement this locally instead? static native long jjRescaleQ(long a, ByteBuffer bq, ByteBuffer cq); // /usr/include/ffmpeg/libavutil/mathematics.h:int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; }