/* * Copyright (c) 2001 Fabrice Bellard * 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 au.notzed.jjmpeg.exception.AVIOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; /** * Wrapper for AVIOContext - allows custom streams to * be implemented from java. * * @author notzed */ public abstract class AVIOContext extends AVIOContextAbstract { public static final int AVSEEK_SIZE = 0x10000; // public static final int SEEK_SET = 0; public static final int SEEK_CUR = 1; public static final int SEEK_END = 2; // public static final int ALLOC_WRITE = 1; public static final int ALLOC_STREAMED = 2; // flags for open public static final int URL_RDONLY; public static final int URL_WRONLY; public static final int URL_RDWR; static { // These flags changed at version 53 // TODO: should be done at build time as part of genjjmpeg.pl int[] vers = AVNative.getVersions(); if (vers[AVNative.LIBAVFORMAT_VERSION] >= 53) { URL_RDONLY = 1; URL_WRONLY = 2; URL_RDWR = 3; } else { URL_RDONLY = 0; URL_WRONLY = 1; URL_RDWR = 2; } } protected AVIOContext(ByteBuffer p) { setNative(new AVIOContextNative(this, p, 0)); } static AVIOContext create(ByteBuffer p) { // These could call back to the C versions return new AVIOContext(p) { @Override public int readPacket(ByteBuffer dst) { throw new UnsupportedOperationException("Not supported yet."); } @Override public int writePacket(ByteBuffer src) { throw new UnsupportedOperationException("Not supported yet."); } @Override public long seek(long offset, int whence) { throw new UnsupportedOperationException("Not supported yet."); } }; } public static AVIOContext open(String url, int flags) throws AVIOException { ByteBuffer res = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()); ByteBuffer context; System.out.println("open url " + url + " flags " + flags); context = AVIOContextNative.open(url, flags, res); if (context == null) { throw new AVIOException(res.asIntBuffer().get(0), "Failed to open " + url); } return create(context); } /** * Initialise the aviocontext. * @param size * @param flags Taken from ALLOC_* flags */ protected AVIOContext(int size, int flags) { this(AVIOContextNative.allocContext(size, flags)); AVIOContextNative.bind(this, n.p); } /** * Call av_probe_input_buffer() on this stream * @param filename * @param offset * @param max_probe_size * @return */ public AVInputFormat probeInput(String filename, int offset, int max_probe_size) { ByteBuffer b = AVIOContextNative.probeInput(n.p, filename, offset, max_probe_size); if (b != null) { return AVInputFormat.create(b); } return null; } /** * Release resources. This must be called otherwise the object * will not be garbage collected. * * TODO: still thinking of how to implement the lifecycle. */ public abstract int readPacket(ByteBuffer dst); public abstract int writePacket(ByteBuffer src); public abstract long seek(long offset, int whence); } class AVIOContextNative extends AVIOContextNativeAbstract { private final int type; AVIOContextNative(AVObject o, ByteBuffer p, int type) { super(o, p); this.type = type; } @Override public void dispose() { if (p != null) { if (type == 1) { AVIOContextNative.unbind((AVIOContext) this.get(), p); } super.dispose(); } } static native ByteBuffer allocContext(int size, int flags); static native ByteBuffer probeInput(ByteBuffer p, String filename, int offset, int max_probe_size); static native ByteBuffer open(String url, int flags, ByteBuffer error_ptr); /** * Bind AVIOContext to java instance */ static native void bind(AVIOContext self, ByteBuffer p); /** * Unbind AVIOContext from java instance, and free memory too. */ static native void unbind(AVIOContext self, ByteBuffer p); }