All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gstreamer.Gst Maven / Gradle / Ivy

There is a newer version: 1.6
Show newest version
/* 
 * Copyright (c) 2007 Wayne Meissner
 * 
 * This file is part of gstreamer-java.
 *
 * This code is free software: you can redistribute it and/or modify it under 
 * the terms of the GNU Lesser General Public License version 3 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 
 * version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with this work.  If not, see .
 */

package org.gstreamer;


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.gstreamer.glib.MainContextExecutorService;
import org.gstreamer.lowlevel.GstAPI;
import org.gstreamer.lowlevel.GMainContext;
import org.gstreamer.lowlevel.GstNative;
import org.gstreamer.lowlevel.GstAPI.GErrorStruct;

import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;

/**
 * Media library supporting arbitrary formats and filter graphs.
 * 
 */
public final class Gst {
    static Logger logger = Logger.getLogger(Gst.class.getName());
    private static ScheduledExecutorService executorService;
    private static volatile CountDownLatch quit = new CountDownLatch(1);
    private static GMainContext mainContext;
    private static boolean useDefaultContext = false;
    private static final AtomicInteger initCount = new AtomicInteger(0);
    private static List shutdownTasks = Collections.synchronizedList(new ArrayList());
    private static final GstAPI gst = GstNative.load(GstAPI.class);    
    
    /** Creates a new instance of Gst */
    private Gst() {
    }
    
    /**
     * Gets the version of gstreamer currently in use.
     * 
     * @return the version of gstreamer
     */
    public static Version getVersion() {
        long[] major = { 0 }, minor = { 0 }, micro = { 0 }, nano = { 0 };
        gst.gst_version(major, minor, micro, nano);
        return new Version(major[0], minor[0], micro[0], nano[0]);
    }
    
    /**
     * Gets the the version of gstreamer currently in use, as a String.
     * 
     * @return a string representation of the version.
     */
    public static String getVersionString() {
        return gst.gst_version_string();
    }
    
    /**
     * Gets the common {@code Executor} used to execute background tasks.
     * 
     * @return an executor that can be used for background tasks.
     */
    public static Executor getExecutor() {
        return getScheduledExecutorService();
    }
    
    /**
     * Gets the common {@code ExecutorService} used to execute background tasks.
     * 
     * @return an executor that can be used for background tasks.
     */
    public static ExecutorService getExecutorService() {
        return getScheduledExecutorService();
    }
    
    /**
     * Gets the common {@code ScheduledExecutorService} used to execute 
     * background tasks and schedule timeouts.
     * 
     * @return an executor that can be used for background tasks.
     */
    public static ScheduledExecutorService getScheduledExecutorService() {
        return executorService;
    }
    
    /**
     * Signals the thread that called {@link #run} to return.
     */
    public static void quit() {
        quit.countDown();
    }
    
    /**
     * Waits for the gstreamer system to shutdown via a call to {@link #quit}.
     * 

For most gui programs, this is of little use. However, it can be * a convenient way of keeping the main thread alive whilst gstreamer * processing on other threads continues. */ public static void main() { try { CountDownLatch latch = quit; if (latch != null) { latch.await(); } } catch (InterruptedException ex) { } finally { quit = new CountDownLatch(1); } } /** * Schedules a task for execution on the gstreamer background * {@link java.util.concurrent.Executor}. * * @param task the task to execute. */ public static void invokeLater(final Runnable task) { getExecutor().execute(task); } /** * Executes a task on the gstreamer background * {@link java.util.concurrent.Executor}, waiting until the task completes * before returning. * * @param task the task to execute. */ public static void invokeAndWait(Runnable task) { try { getExecutorService().submit(task).get(); } catch (Exception ex) { throw new RuntimeException(ex.getCause()); } } /** * Gets the current main context used (if any). * * @return a main context. */ public static GMainContext getMainContext() { return mainContext; } /** * Initializes the GStreamer library. *

This is a shortcut if no arguments are to be passed to gstreamer. * * @throws org.gstreamer.GstException */ public static final void init() throws GstException { init("unknown", new String[] {}); } /** * Initializes the GStreamer library. *

This sets up internal path lists, registers built-in elements, and * loads standard plugins. * *

* This method should be called before calling any other GLib functions. If * this is not an option, your program must initialise the GLib thread system * using g_thread_init() before any other GLib functions are called. * *

* Note:

* This method will throw a GstException if it fails. * * @param progname the java program name. * @param args the java argument list. * @return the list of arguments with any gstreamer specific options stripped * out. * @throws org.gstreamer.GstException */ public static synchronized final String[] init(String progname, String[] args) throws GstException { // // Only do real init the first time through // if (initCount.getAndIncrement() > 0) { return args; } NativeArgs argv = new NativeArgs(progname, args); Logger.getLogger("org.gstreamer").setLevel(Level.WARNING); Pointer[] error = { null }; if (!gst.gst_init_check(argv.argcRef, argv.argvRef, error)) { initCount.decrementAndGet(); throw new GstException(new GError(new GErrorStruct(error[0]))); } logger.fine("after gst_init, argc=" + argv.argcRef.getValue()); if (useDefaultContext) { mainContext = GMainContext.getDefaultContext(); executorService = new MainContextExecutorService(mainContext); } else { mainContext = new GMainContext(); executorService = Executors.newSingleThreadScheduledExecutor(threadFactory); } quit = new CountDownLatch(1); return argv.toStringArray(); } /** * Undoes all the initialization done in {@link #init}. *

This will run any cleanup tasks, terminate any timers and other * asynchronous tasks, and de-initialize the gstreamer library. */ public static synchronized final void deinit() { // // Only perform real shutdown if called as many times as Gst.init() is // if (initCount.decrementAndGet() > 0) { return; } // Perform any cleanup tasks for (Object task : shutdownTasks.toArray()) { ((Runnable) task).run(); } // Stop any more tasks/timers from being scheduled executorService.shutdown(); // Wake up the run thread. quit(); // Wait for tasks to complete. try { if (!executorService.awaitTermination(100, TimeUnit.MILLISECONDS)) { // Force-kill everything executorService.shutdownNow(); } } catch (InterruptedException ex) { } mainContext = null; System.gc(); // Make sure any dangling objects are unreffed before calling deinit(). gst.gst_deinit(); } /** * Adds a task to be called when {@link Gst#deinit} is called. *

This is used internally, and is not recommended for other uses. * * @param task the task to execute. */ public static void addStaticShutdownTask(Runnable task) { shutdownTasks.add(task); } /** * Instructs gstreamer-java to use the default main context. *

* This may be useful if integration with the GTK main loop is desirable, * as all {@link Bus} signals and timers will be executed in the context * of the GTK main loop. *

* For the majority of programs though, it is better to wrap the individual * listeners in a proxy which executes the listener in the appropriate * context. * * @param useDefault if true, use the default glib main context. */ public static void setUseDefaultContext(boolean useDefault) { useDefaultContext = useDefault; } // Make the gstreamer executor threads daemon, so they don't stop the main // program from exiting private static final ThreadFactory threadFactory = new ThreadFactory() { private final AtomicInteger counter = new AtomicInteger(0); /** * Determines if Gst has been started from an applet and returns * it's parent group. * * This is to avoid a problem where the service thread is killed when * an applet is destroyed. If multiple applets are active simultaneously, * this could be a problem. * * @return Applet's parent ("main") thread group or null, if not * running inside an applet */ private ThreadGroup getThreadGroup() { ThreadGroup tg = Thread.currentThread().getThreadGroup(); try { Class atgClass = Class.forName("sun.applet.AppletThreadGroup"); return atgClass.isInstance(tg) ? tg.getParent() : null; } catch (ClassNotFoundException ex) { return null; } } public Thread newThread(Runnable task) { final String name = "gstreamer service thread " + counter.incrementAndGet(); Thread t = new Thread(getThreadGroup(), task, name); t.setDaemon(true); t.setPriority(Thread.NORM_PRIORITY); return t; } }; } class NativeArgs { IntByReference argcRef; PointerByReference argvRef; Memory[] argsCopy; Memory argvMemory; public NativeArgs(String progname, String[] args) { // // Allocate some native memory to pass the args down to the native layer // argsCopy = new Memory[args.length + 2]; argvMemory = new Memory(argsCopy.length * Pointer.SIZE); // // Insert the program name as argv[0] // Memory arg = new Memory(progname.length() + 4); arg.setString(0, progname, false); argsCopy[0] = arg; for (int i = 0; i < args.length; i++) { arg = new Memory(args[i].length() + 1); arg.setString(0, args[i], false); argsCopy[i + 1] = arg; } argvMemory.write(0, argsCopy, 0, argsCopy.length); argvRef = new PointerByReference(argvMemory); argcRef = new IntByReference(args.length + 1); } String[] toStringArray() { // // Unpack the native arguments back into a String array // List args = new ArrayList(); Pointer argv = argvRef.getValue(); for (int i = 1; i < argcRef.getValue(); i++) { Pointer arg = argv.getPointer(i * Pointer.SIZE); if (arg != null) { args.add(arg.getString(0, false)); } } return args.toArray(new String[args.size()]); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy