summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java24
-rw-r--r--src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java4
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java45
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java231
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java105
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java19
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java5
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java5
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java5
-rw-r--r--src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java81
-rw-r--r--src/jogl/native/libav/ffmpeg_dshow.c209
-rw-r--r--src/jogl/native/libav/ffmpeg_dshow.h47
-rw-r--r--src/jogl/native/libav/ffmpeg_impl_template.c416
-rw-r--r--src/jogl/native/libav/ffmpeg_lavc55_lavf55_lavu52_lavr01.c33
-rw-r--r--src/jogl/native/libav/ffmpeg_static.c32
-rw-r--r--src/jogl/native/libav/ffmpeg_tool.h37
16 files changed, 1004 insertions, 294 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
index 0feca9f45..7f57138a7 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java
@@ -197,13 +197,33 @@ public interface GLMediaPlayer extends TextureSequence {
* {@link URI#getScheme() URI scheme} name {@value} for camera input. E.g. <code>camera://0</code>
* for the 1st camera device.
* <p>
- * Note: the {@link URI#getHost() URI host} is being used to identify the camera:
+ * The {@link URI#getRawPath() URI path} is being used to identify the camera,
+ * where the root fwd-slash is being cut-off.
+ * </p>
+ * <p>
+ * The {@link URI#getRawQuery() URI query} is used to pass options to the camera.
+ * </p>
+ * <pre>
+ * camera:/<id>
+ * camera://somewhere/<id>
+ * camera://somewhere/<id>?width=640&height=480&rate=15
+ * </pre>
* <pre>
- * camera://<id>
+ * URI: [scheme:][//authority][path][?query][#fragment]
+ * w/ authority: [user-info@]host[:port]
+ * Note: 'path' starts w/ fwd slash
* </pre>
* </p>
*/
public static final String CameraInputScheme = "camera";
+ /** Camera property {@value}, size as string, e.g. <code>1280x720</code>, <code>hd720</code>. May not be supported on all platforms. See {@link #CameraInputScheme}. */
+ public static final String CameraPropSizeS = "size";
+ /** Camera property {@value}. See {@link #CameraInputScheme}. */
+ public static final String CameraPropWidth = "width";
+ /** Camera property {@value}. See {@link #CameraInputScheme}. */
+ public static final String CameraPropHeight = "height";
+ /** Camera property {@value}. See {@link #CameraInputScheme}. */
+ public static final String CameraPropRate = "rate";
/** Maximum video frame async of {@value} milliseconds. */
public static final int MAXIMUM_VIDEO_ASYNC = 22;
diff --git a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
index 056998c0c..38faf62a6 100644
--- a/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
+++ b/src/jogl/classes/jogamp/opengl/android/av/AndroidGLMediaPlayerAPI14.java
@@ -254,12 +254,12 @@ public class AndroidGLMediaPlayerAPI14 extends GLMediaPlayerImpl {
return;
}
if( null == mp && null == cam ) {
- if( null == cameraHostPart ) {
+ if( null == cameraPath ) {
mp = new MediaPlayer();
} else {
int cameraId = 0;
try {
- cameraId = Integer.valueOf(cameraHostPart);
+ cameraId = Integer.valueOf(cameraPath);
} catch (NumberFormatException nfe) {}
if( 0 <= cameraId && cameraId < Camera.getNumberOfCameras() ) {
cam = Camera.open(cameraId);
diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
index 5286c86b8..ab0e2eebd 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java
@@ -31,6 +31,7 @@ import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.Map;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.opengl.GL;
@@ -44,6 +45,7 @@ import javax.media.opengl.GLProfile;
import jogamp.opengl.Debug;
+import com.jogamp.common.net.URIQueryProps;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.LFRingbuffer;
import com.jogamp.common.util.Ringbuffer;
@@ -89,10 +91,13 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
protected URI streamLoc = null;
/**
* In case {@link #streamLoc} is a {@link GLMediaPlayer#CameraInputScheme},
- * {@link #cameraHostPart} holds the URI's path portion
+ * {@link #cameraPath} holds the URI's path portion
* as parsed in {@link #initStream(URI, int, int, int)}.
+ * @see #cameraProps
*/
- protected String cameraHostPart = null;
+ protected String cameraPath = null;
+ /** Optional camera properties, see {@link #cameraPath}. */
+ protected Map<String, String> cameraProps = null;
protected volatile float playSpeed = 1.0f;
protected float audioVolume = 1.0f;
@@ -472,11 +477,19 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
this.streamLoc = streamLoc;
// Pre-parse for camera-input scheme
+ cameraPath = null;
+ cameraProps = null;
final String streamLocScheme = streamLoc.getScheme();
if( null != streamLocScheme && streamLocScheme.equals(CameraInputScheme) ) {
- cameraHostPart = streamLoc.getHost();
- } else {
- cameraHostPart = null;
+ final String rawPath = streamLoc.getRawPath();
+ if( null != rawPath && rawPath.length() > 0 ) {
+ // cut-off root fwd-slash
+ cameraPath = rawPath.substring(1);
+ final URIQueryProps props = URIQueryProps.create(streamLoc);
+ cameraProps = props.getProperties();
+ } else {
+ throw new IllegalArgumentException("Camera path is empty: "+streamLoc.toString());
+ }
}
this.vid = vid;
@@ -526,6 +539,9 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
if( STREAM_ID_NONE != vid ) {
removeAllTextureFrames(gl);
initGLImpl(gl);
+ if(DEBUG) {
+ System.err.println("initGLImpl.X "+this);
+ }
videoFramesOrig = createTexFrames(gl, textureCount);
videoFramesFree = new LFRingbuffer<TextureFrame>(videoFramesOrig);
videoFramesDecoded = new LFRingbuffer<TextureFrame>(TextureFrame[].class, textureCount);
@@ -615,13 +631,13 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
final int err = gl.glGetError();
if( GL.GL_NO_ERROR != err ) {
throw new RuntimeException("Couldn't create TexImage2D RGBA "+tWidth+"x"+tHeight+", target "+toHexString(textureTarget)+
- ", ifmt "+toHexString(GL.GL_RGBA)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType)+
+ ", ifmt "+toHexString(textureInternalFormat)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType)+
", err "+toHexString(err));
}
}
if(DEBUG) {
System.err.println("Created TexImage2D RGBA "+tWidth+"x"+tHeight+", target "+toHexString(textureTarget)+
- ", ifmt "+toHexString(GL.GL_RGBA)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType));
+ ", ifmt "+toHexString(textureInternalFormat)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType));
}
}
gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, texMinMagFilter[0]);
@@ -1322,10 +1338,10 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
final int freeVideoFrames = null != videoFramesFree ? videoFramesFree.size() : 0;
final int decVideoFrames = null != videoFramesDecoded ? videoFramesDecoded.size() : 0;
final int video_scr = video_scr_pts + (int) ( ( Platform.currentTimeMillis() - video_scr_t0 ) * playSpeed );
- final String camPath = null != cameraHostPart ? ", camera: "+cameraHostPart : "";
+ final String camPath = null != cameraPath ? ", camera: "+cameraPath : "";
return "GLMediaPlayer["+state+", vSCR "+video_scr+", frames[p "+presentedFrameCount+", d "+decodedFrameCount+", t "+videoFrames+" ("+tt+" s)], "+
"speed "+playSpeed+", "+bps_stream+" bps, "+
- "Texture[count "+textureCount+", free "+freeVideoFrames+", dec "+decVideoFrames+", target "+toHexString(textureTarget)+", format "+toHexString(textureFormat)+", type "+toHexString(textureType)+"], "+
+ "Texture[count "+textureCount+", free "+freeVideoFrames+", dec "+decVideoFrames+", tagt "+toHexString(textureTarget)+", ifmt "+toHexString(textureInternalFormat)+", fmt "+toHexString(textureFormat)+", type "+toHexString(textureType)+"], "+
"Video[id "+vid+", <"+vcodec+">, "+width+"x"+height+", "+fps+" fps, "+frame_duration+" fdur, "+bps_video+" bps], "+
"Audio[id "+aid+", <"+acodec+">, "+bps_audio+" bps, "+audioFrames+" frames], uri "+loc+camPath+"]";
}
@@ -1394,4 +1410,15 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer {
protected static final String toHexString(int v) {
return "0x"+Integer.toHexString(v);
}
+ protected static final int getPropIntVal(Map<String, String> props, String key) {
+ final String val = props.get(key);
+ try {
+ return Integer.valueOf(val).intValue();
+ } catch (NumberFormatException nfe) {
+ if(DEBUG) {
+ System.err.println("Not a valid integer for <"+key+">: <"+val+">");
+ }
+ }
+ return 0;
+ }
} \ No newline at end of file
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
index f327cddd4..400788a24 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java
@@ -32,10 +32,8 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import javax.media.opengl.GLProfile;
@@ -53,12 +51,13 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
private static final List<String> glueLibNames = new ArrayList<String>(); // none
- private static final int symbolCount = 54;
+ private static final int symbolCount = 65;
private static final String[] symbolNames = {
- "avcodec_version",
- "avformat_version",
"avutil_version",
-/* 4 */ "avresample_version",
+ "avformat_version",
+ "avcodec_version",
+ "avresample_version",
+/* 5 */ "swresample_version",
// libavcodec
"avcodec_register_all",
@@ -69,15 +68,20 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"avcodec_alloc_frame",
"avcodec_get_frame_defaults",
"avcodec_free_frame", // 54.28.0 (opt)
- "avcodec_default_get_buffer",
- "avcodec_default_release_buffer",
+ "avcodec_default_get_buffer", // <= 54 (opt), else sp_avcodec_default_get_buffer2
+ "avcodec_default_release_buffer", // <= 54 (opt), else sp_av_frame_unref
+ "avcodec_default_get_buffer2", // 55 (opt)
+ "avcodec_get_edge_width",
+ "av_image_fill_linesizes",
+ "avcodec_align_dimensions",
+ "avcodec_align_dimensions2",
"avcodec_flush_buffers",
"av_init_packet",
"av_new_packet",
"av_destruct_packet",
"av_free_packet",
"avcodec_decode_audio4", // 53.25.0 (opt)
-/* 21 */ "avcodec_decode_video2", // 52.23.0
+/* 27 */ "avcodec_decode_video2", // 52.23.0
// libavutil
"av_pix_fmt_descriptors",
@@ -91,7 +95,7 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"av_dict_get",
"av_dict_count", // 54.* (opt)
"av_dict_set",
-/* 33 */ "av_dict_free",
+/* 28 */ "av_dict_free",
// libavformat
"avformat_alloc_context",
@@ -108,22 +112,25 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"av_read_pause",
"avformat_network_init", // 53.13.0 (opt)
"avformat_network_deinit", // 53.13.0 (opt)
-/* 48 */ "avformat_find_stream_info", // 53.3.0 (opt)
+/* 54 */ "avformat_find_stream_info", // 53.3.0 (opt)
// libavdevice
-/* 49 */ "avdevice_register_all", // ???
+/* 55 */ "avdevice_register_all", // ???
// libavresample
"avresample_alloc_context", // 1.0.1
"avresample_open",
"avresample_close",
"avresample_free",
-/* 54 */ "avresample_convert"
- };
-
- // alternate symbol names
- private static final String[][] altSymbolNames = {
- // { "av_find_stream_info", "avformat_find_stream_info" }, // old, 53.3.0
+/* 60 */ "avresample_convert",
+
+ // libavresample
+ "av_opt_set_sample_fmt", // actually lavu .. but exist only w/ swresample!
+ "swr_alloc",
+ "swr_init",
+ "swr_free",
+/* 65 */ "swr_convert",
+
};
// optional symbol names
@@ -132,8 +139,13 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"avcodec_free_frame", // 54.28.0 (opt)
"av_frame_unref", // 55.0.0 (opt)
"av_dict_count", // 54.* (opt)
+ "avcodec_default_get_buffer", // <= 54 (opt), else sp_avcodec_default_get_buffer2
+ "avcodec_default_release_buffer", // <= 54 (opt), else sp_av_frame_unref
+ "avcodec_default_get_buffer2", // 55 (opt)
+
// libavdevice
"avdevice_register_all", // 53.0.0 (opt)
+
// libavresample
"avresample_version", // 1.0.1
"avresample_alloc_context", // 1.0.1
@@ -141,41 +153,60 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
"avresample_close",
"avresample_free",
"avresample_convert",
+
+ // libavresample
+ "av_opt_set_sample_fmt", // actually lavu .. but exist only w/ swresample!
+ "swresample_version", // 0
+ "swr_alloc",
+ "swr_init",
+ "swr_free",
+ "swr_convert",
};
private static final long[] symbolAddr = new long[symbolCount];
private static final boolean ready;
- private static final boolean libsLoaded;
+ private static final boolean libsUFCLoaded;
private static final boolean avresampleLoaded; // optional
+ private static final boolean swresampleLoaded; // optional
private static final boolean avdeviceLoaded; // optional
static final VersionNumber avCodecVersion;
static final VersionNumber avFormatVersion;
static final VersionNumber avUtilVersion;
static final VersionNumber avResampleVersion;
+ static final VersionNumber swResampleVersion;
private static final FFMPEGNatives natives;
+ private static final int LIB_IDX_UTI = 0;
+ private static final int LIB_IDX_FMT = 1;
+ private static final int LIB_IDX_COD = 2;
+ private static final int LIB_IDX_DEV = 3;
+ private static final int LIB_IDX_AVR = 4;
+ private static final int LIB_IDX_SWR = 5;
+
static {
// native ffmpeg media player implementation is included in jogl_desktop and jogl_mobile
GLProfile.initSingleton();
boolean _ready = false;
- boolean[] _libsLoaded= { false };
- boolean[] _avdeviceLoaded= { false };
- boolean[] _avresampleLoaded= { false };
- VersionNumber[] _versions = new VersionNumber[4];
+ /** util, format, codec, device, avresample, swresample */
+ boolean[] _loaded= new boolean[6];
+ /** util, format, codec, avresample, swresample */
+ VersionNumber[] _versions = new VersionNumber[5];
try {
- _ready = initSymbols(_libsLoaded, _avdeviceLoaded, _avresampleLoaded, _versions);
+ _ready = initSymbols(_loaded, _versions);
} catch (Throwable t) {
t.printStackTrace();
}
- libsLoaded = _libsLoaded[0];
- avdeviceLoaded = _avdeviceLoaded[0];
- avresampleLoaded = _avresampleLoaded[0];
- avCodecVersion = _versions[0];
+ libsUFCLoaded = _loaded[LIB_IDX_UTI] && _loaded[LIB_IDX_FMT] && _loaded[LIB_IDX_COD];
+ avdeviceLoaded = _loaded[LIB_IDX_DEV];
+ avresampleLoaded = _loaded[LIB_IDX_AVR];
+ swresampleLoaded = _loaded[LIB_IDX_SWR];
+ avUtilVersion = _versions[0];
avFormatVersion = _versions[1];
- avUtilVersion = _versions[2];
+ avCodecVersion = _versions[2];
avResampleVersion = _versions[3];
- if(!libsLoaded) {
- System.err.println("LIB_AV Not Available");
+ swResampleVersion = _versions[4];
+ if(!libsUFCLoaded) {
+ System.err.println("LIB_AV Not Available: lavu, lavc, lavu");
natives = null;
ready = false;
} else if(!_ready) {
@@ -183,12 +214,15 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
natives = null;
ready = false;
} else {
- if( avCodecVersion.getMajor() <= 53 && avFormatVersion.getMajor() <= 53 && avUtilVersion.getMajor() <= 51 ) {
+ if( avCodecVersion.getMajor() == 53 && avFormatVersion.getMajor() == 53 && avUtilVersion.getMajor() == 51 ) {
// lavc53.lavf53.lavu51
natives = new FFMPEGv08Natives();
- } else if( avCodecVersion.getMajor() == 54 && avFormatVersion.getMajor() <= 54 && avUtilVersion.getMajor() <= 52 ) {
+ } else if( avCodecVersion.getMajor() == 54 && avFormatVersion.getMajor() == 54 && avUtilVersion.getMajor() == 52 ) {
// lavc54.lavf54.lavu52.lavr01
natives = new FFMPEGv09Natives();
+ } else if( avCodecVersion.getMajor() == 55 && avFormatVersion.getMajor() == 55 && avUtilVersion.getMajor() == 52 ) {
+ // lavc55.lavf55.lavu52.lavr01
+ natives = new FFMPEGv10Natives();
} else {
System.err.println("LIB_AV No Version/Native-Impl Match");
natives = null;
@@ -201,29 +235,33 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
}
}
- static boolean libsLoaded() { return libsLoaded; }
+ static boolean libsLoaded() { return libsUFCLoaded; }
static boolean avDeviceLoaded() { return avdeviceLoaded; }
static boolean avResampleLoaded() { return avresampleLoaded; }
+ static boolean swResampleLoaded() { return swresampleLoaded; }
static FFMPEGNatives getNatives() { return natives; }
static boolean initSingleton() { return ready; }
-
- private static final boolean initSymbols(boolean[] libsLoaded, boolean[] avdeviceLoaded, boolean[] avresampleLoaded,
- VersionNumber[] versions) {
- libsLoaded[0] = false;
+
+ /**
+ * @param loaded 6: util, format, codec, device, avresample, swresample
+ * @param versions 5: util, format, codec, avresample, swresample
+ * @return
+ */
+ private static final boolean initSymbols(boolean[] loaded, VersionNumber[] versions) {
+ for(int i=0; i<6; i++) {
+ loaded[i] = false;
+ }
final DynamicLibraryBundle dl = AccessController.doPrivileged(new PrivilegedAction<DynamicLibraryBundle>() {
public DynamicLibraryBundle run() {
return new DynamicLibraryBundle(new FFMPEGDynamicLibraryBundleInfo());
} } );
- final boolean avutilLoaded = dl.isToolLibLoaded(0);
- final boolean avformatLoaded = dl.isToolLibLoaded(1);
- final boolean avcodecLoaded = dl.isToolLibLoaded(2);
- if(!avutilLoaded || !avformatLoaded || !avcodecLoaded) {
- throw new RuntimeException("FFMPEG Tool library incomplete: [ avutil "+avutilLoaded+", avformat "+avformatLoaded+", avcodec "+avcodecLoaded+"]");
+ dl.toString();
+ for(int i=0; i<6; i++) {
+ loaded[i] = dl.isToolLibLoaded(i);
+ }
+ if( !loaded[LIB_IDX_UTI] || !loaded[LIB_IDX_FMT] || !loaded[LIB_IDX_COD] ) {
+ throw new RuntimeException("FFMPEG Tool library incomplete: [ avutil "+loaded[LIB_IDX_UTI]+", avformat "+loaded[LIB_IDX_FMT]+", avcodec "+loaded[LIB_IDX_COD]+"]");
}
- avdeviceLoaded[0] = dl.isToolLibLoaded(3);
- avresampleLoaded[0] = dl.isToolLibLoaded(4);
- libsLoaded[0] = true;
-
if(symbolNames.length != symbolCount) {
throw new InternalError("XXX0 "+symbolNames.length+" != "+symbolCount);
}
@@ -232,20 +270,6 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
final Set<String> optionalSymbolNameSet = new HashSet<String>();
optionalSymbolNameSet.addAll(Arrays.asList(optionalSymbolNames));
- // alternate symbol name mapping to indexed array
- final Map<String, Integer> mAltSymbolNames = new HashMap<String, Integer>();
- final int[][] iAltSymbolNames = new int[altSymbolNames.length][];
- {
- final List<String> symbolNameList = Arrays.asList(symbolNames);
- for(int i=0; i<altSymbolNames.length; i++) {
- iAltSymbolNames[i] = new int[altSymbolNames[i].length];
- for(int j=0; j<altSymbolNames[i].length; j++) {
- mAltSymbolNames.put(altSymbolNames[i][j], new Integer(i));
- iAltSymbolNames[i][j] = symbolNameList.indexOf(altSymbolNames[i][j]);
- }
- }
- }
-
// lookup
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
@@ -262,33 +286,18 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
// no symbol, check optional and alternative symbols
final String symbol = symbolNames[i];
if ( !optionalSymbolNameSet.contains(symbol) ) {
- // check for API changed symbols
- boolean ok = false;
- final Integer cI = mAltSymbolNames.get(symbol);
- if ( null != cI ) {
- // check whether alternative symbol is available
- final int ci = cI.intValue();
- for(int j=0; !ok && j<iAltSymbolNames[ci].length; j++) {
- final int si = iAltSymbolNames[ci][j];
- ok = 0 != symbolAddr[si];
- if(ok && DEBUG) {
- System.err.println("OK: Unresolved symbol <"+symbol+">, but has alternative <"+symbolNames[si]+">");
- }
- }
- }
- if(!ok) {
- System.err.println("Fail: Could not resolve symbol <"+symbolNames[i]+">: not optional, no alternatives.");
- res = false;
- }
+ System.err.println("Fail: Could not resolve symbol <"+symbolNames[i]+">: not optional, no alternatives.");
+ res = false;
} else if(DEBUG) {
System.err.println("OK: Unresolved optional symbol <"+symbolNames[i]+">");
}
}
}
- versions[0] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvCodecVersion0(symbolAddr[0]));
- versions[1] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvFormatVersion0(symbolAddr[1]));
- versions[2] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvUtilVersion0(symbolAddr[2]));
- versions[3] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvResampleVersion0(symbolAddr[3]));
+ versions[0] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[0]));
+ versions[1] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[1]));
+ versions[2] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[2]));
+ versions[3] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[3]));
+ versions[4] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[4]));
return res;
}
@@ -319,16 +328,18 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
public final List<List<String>> getToolLibNames() {
List<List<String>> libsList = new ArrayList<List<String>>();
+ // 6: util, format, codec, device, avresample, swresample
+
final List<String> avutil = new ArrayList<String>();
avutil.add("avutil"); // default
avutil.add("libavutil.so.53"); // dummy future proof
- avutil.add("libavutil.so.52"); // 9
+ avutil.add("libavutil.so.52"); // ffmpeg 1.2 + 2 / libav 9 + 10
avutil.add("libavutil.so.51"); // 0.8
avutil.add("libavutil.so.50"); // 0.7
avutil.add("avutil-53"); // dummy future proof
- avutil.add("avutil-52"); // 9
+ avutil.add("avutil-52"); // ffmpeg 1.2 + 2 / libav 9 + 10
avutil.add("avutil-51"); // 0.8
avutil.add("avutil-50"); // 0.7
libsList.add(avutil);
@@ -336,51 +347,69 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo {
final List<String> avformat = new ArrayList<String>();
avformat.add("avformat"); // default
- avformat.add("libavformat.so.55"); // dummy future proof
- avformat.add("libavformat.so.54"); // 9
+ avformat.add("libavformat.so.56"); // dummy future proof
+ avformat.add("libavformat.so.55"); // ffmpeg 2 / libav 10
+ avformat.add("libavformat.so.54"); // ffmpeg 1.2 / libav 9
avformat.add("libavformat.so.53"); // 0.8
avformat.add("libavformat.so.52"); // 0.7
- avformat.add("avformat-55"); // dummy future proof
- avformat.add("avformat-54"); // 9
+ avformat.add("avformat-56"); // dummy future proof
+ avformat.add("avformat-55"); // ffmpeg 2 / libav 10
+ avformat.add("avformat-54"); // ffmpeg 1.2 / libav 9
avformat.add("avformat-53"); // 0.8
- avformat.add("avformat-52"); // 0.7
+ avformat.add("avformat-52"); // 0.7
libsList.add(avformat);
final List<String> avcodec = new ArrayList<String>();
avcodec.add("avcodec"); // default
- avcodec.add("libavcodec.so.55"); // dummy future proof
- avcodec.add("libavcodec.so.54"); // 9
+ avcodec.add("libavcodec.so.56"); // dummy future proof
+ avcodec.add("libavcodec.so.55"); // ffmpeg 2/ libav 10
+ avcodec.add("libavcodec.so.54"); // ffmpeg 1.2 / libav 9
avcodec.add("libavcodec.so.53"); // 0.8
avcodec.add("libavcodec.so.52"); // 0.7
- avcodec.add("avcodec-55"); // dummy future proof
- avcodec.add("avcodec-54"); // 9
+ avcodec.add("avcodec-56"); // dummy future proof
+ avcodec.add("avcodec-55"); // ffmpeg 2/ libav 10
+ avcodec.add("avcodec-54"); // ffmpeg 1.2 / libav 9
avcodec.add("avcodec-53"); // 0.8
- avcodec.add("avcodec-52"); // 0.7
+ avcodec.add("avcodec-52"); // 0.7
libsList.add(avcodec);
final List<String> avdevice = new ArrayList<String>();
avdevice.add("avdevice"); // default
- avdevice.add("libavdevice.so.54"); // dummy future proof
- avdevice.add("libavdevice.so.53"); // 0.8 && 9
+ avdevice.add("libavdevice.so.56"); // dummy future proof
+ avdevice.add("libavdevice.so.55"); // ffmpeg 2
+ avdevice.add("libavdevice.so.54"); // ffmpeg 1.2 / libav 10
+ avdevice.add("libavdevice.so.53"); // 0.8 && libav 9
- avdevice.add("avdevice-54"); // dummy future proof
- avdevice.add("avdevice-53"); // 0.8 && 9
+ avdevice.add("avdevice-56"); // dummy future proof
+ avdevice.add("avdevice-55"); // ffmpeg 2
+ avdevice.add("avdevice-54"); // ffmpeg 1.2 / libav 10
+ avdevice.add("avdevice-53"); // 0.8 && libav 9
libsList.add(avdevice);
final List<String> avresample = new ArrayList<String>();
avresample.add("avresample"); // default
avresample.add("libavresample.so.2"); // dummy future proof
- avresample.add("libavresample.so.1"); // 9
+ avresample.add("libavresample.so.1"); // libav 9 + 10
avresample.add("avresample-2"); // dummy future proof
- avresample.add("avresample-1"); // 9
+ avresample.add("avresample-1"); // libav 9 + 10
libsList.add(avresample);
+ final List<String> swresample = new ArrayList<String>();
+ swresample.add("swresample"); // default
+
+ swresample.add("libswresample.so.1"); // dummy future proof
+ swresample.add("libswresample.so.0"); // ffmpeg 1.2 + 2.x
+
+ swresample.add("swresample-1"); // dummy future proof
+ swresample.add("swresample-0"); // ffmpeg 1.2 + 2.x
+ libsList.add(swresample);
+
return libsList;
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
index 2dd60074c..269500399 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java
@@ -55,7 +55,7 @@ import jogamp.opengl.util.av.impl.FFMPEGNatives.SampleFormat;
/***
* Implementation utilizes <a href="http://libav.org/">Libav</a>
- * or <a href="http://ffmpeg.org/">FFmpeg</a> which is ubiquitous
+ * or <a href="http://ffmpeg.org/">FFmpeg</a> which are ubiquitous
* available and usually pre-installed on Unix platforms.
* <p>
* Due to legal reasons we cannot deploy binaries of it, which contains patented codecs.
@@ -83,6 +83,7 @@ import jogamp.opengl.util.av.impl.FFMPEGNatives.SampleFormat;
* <li>{@link PixelFormat#YUV422P}</li>
* <li>{@link PixelFormat#YUVJ422P}</li>
* <li>{@link PixelFormat#YUYV422}</li>
+ * <li>{@link PixelFormat#BGR24}</li>
* </ul>
* </p>
* <p>
@@ -104,9 +105,10 @@ import jogamp.opengl.util.av.impl.FFMPEGNatives.SampleFormat;
* <p>
* Currently we are binary compatible w/:
* <table border="1">
- * <tr><th>release</th><th>lavc</th><th>lavf</th><th>lavu</th><th>lavr</th> <th>FFMPEG* class</th></tr>
- * <tr><td>0.8</td> <td>53</td><td>53</td><td>51</td><td></td> <td>FFMPEGv08</td></tr>
- * <tr><td>9.0</td> <td>54</td><td>54</td><td>52</td><td>01</td> <td>FFMPEGv09</td></tr>
+ * <tr><th>libav / ffmpeg</th><th>lavc</th><th>lavf</th><th>lavu</th><th>lavr</th> <th>FFMPEG* class</th></tr>
+ * <tr><td>0.8</td> <td>53</td> <td>53</td> <td>51</td> <td></td> <td>FFMPEGv08</td></tr>
+ * <tr><td>9.0 / 1.2</td> <td>54</td> <td>54</td> <td>52</td> <td>01/00</td> <td>FFMPEGv09</td></tr>
+ * <tr><td>10 / 2</td> <td>55</td> <td>55</td> <td>52</td> <td>01/00</td> <td>FFMPEGv10</td></tr>
* </table>
* </p>
* <p>
@@ -122,14 +124,19 @@ import jogamp.opengl.util.av.impl.FFMPEGNatives.SampleFormat;
* <a name="todo"><h5>TODO:</h5></a>
* <p>
* <ul>
- * <li>better pts sync handling</li>
+ * <li>better audio synchronization handling? (video is synchronized)</li>
* </ul>
* </p>
*
- * <a name="libavavail"><h5>LibAV Availability</h5></a>
+ * <a name="libavavail"><h5>FFMPEG / LibAV Availability</h5></a>
* <p>
* <ul>
- * <li>Windows: http://win32.libav.org/releases/</li>
+ * <li>GNU/Linux: ffmpeg or libav are deployed in most distributions.</li>
+ * <li>Windows:
+ * <ul>
+ * <li>http://ffmpeg.zeranoe.com/builds/ (ffmpeg)</li>
+ * <li>http://win32.libav.org/releases/ (libav)</li>
+ * </ul></li>
* <li>MacOSX: http://ffmpegmac.net/</li>
* <li>OpenIndiana/Solaris:<pre>
* pkg set-publisher -p http://pkg.openindiana.org/sfe-encumbered.
@@ -148,7 +155,8 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
private static final int avUtilMajorVersionCC;
private static final int avFormatMajorVersionCC;
private static final int avCodecMajorVersionCC;
- private static final int avResampleMajorVersionCC;
+ private static final int avResampleMajorVersionCC;
+ private static final int swResampleMajorVersionCC;
private static final boolean available;
static {
@@ -156,24 +164,38 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
final boolean libAVVersionGood;
if( FFMPEGDynamicLibraryBundleInfo.libsLoaded() ) {
natives = FFMPEGDynamicLibraryBundleInfo.getNatives();
- avCodecMajorVersionCC = natives.getAvCodecMajorVersionCC0();
- avFormatMajorVersionCC = natives.getAvFormatMajorVersionCC0();
- avUtilMajorVersionCC = natives.getAvUtilMajorVersionCC0();
- avResampleMajorVersionCC = natives.getAvResampleMajorVersionCC0();
+ if( null != natives ) {
+ avCodecMajorVersionCC = natives.getAvCodecMajorVersionCC0();
+ avFormatMajorVersionCC = natives.getAvFormatMajorVersionCC0();
+ avUtilMajorVersionCC = natives.getAvUtilMajorVersionCC0();
+ avResampleMajorVersionCC = natives.getAvResampleMajorVersionCC0();
+ swResampleMajorVersionCC = natives.getSwResampleMajorVersionCC0();
+ } else {
+ avUtilMajorVersionCC = 0;
+ avFormatMajorVersionCC = 0;
+ avCodecMajorVersionCC = 0;
+ avResampleMajorVersionCC = 0;
+ swResampleMajorVersionCC = 0;
+ }
final VersionNumber avCodecVersion = FFMPEGDynamicLibraryBundleInfo.avCodecVersion;
final VersionNumber avFormatVersion = FFMPEGDynamicLibraryBundleInfo.avFormatVersion;
final VersionNumber avUtilVersion = FFMPEGDynamicLibraryBundleInfo.avUtilVersion;
- final VersionNumber avResampleVersion = FFMPEGDynamicLibraryBundleInfo.avResampleVersion;
+ final VersionNumber avResampleVersion = FFMPEGDynamicLibraryBundleInfo.avResampleVersion;
+ final boolean avResampleLoaded = FFMPEGDynamicLibraryBundleInfo.avResampleLoaded();
+ final VersionNumber swResampleVersion = FFMPEGDynamicLibraryBundleInfo.swResampleVersion;
+ final boolean swResampleLoaded = FFMPEGDynamicLibraryBundleInfo.swResampleLoaded();
System.err.println("LIB_AV Codec : "+avCodecVersion+" [cc "+avCodecMajorVersionCC+"]");
System.err.println("LIB_AV Format : "+avFormatVersion+" [cc "+avFormatMajorVersionCC+"]");
System.err.println("LIB_AV Util : "+avUtilVersion+" [cc "+avUtilMajorVersionCC+"]");
- System.err.println("LIB_AV Resample: "+FFMPEGDynamicLibraryBundleInfo.avResampleVersion+" [cc "+avResampleMajorVersionCC+", loaded "+FFMPEGDynamicLibraryBundleInfo.avResampleLoaded()+"]");
+ System.err.println("LIB_AV Resample: "+avResampleVersion+" [cc "+avResampleMajorVersionCC+", loaded "+avResampleLoaded+"]");
+ System.err.println("LIB_SW Resample: "+swResampleVersion+" [cc "+swResampleMajorVersionCC+", loaded "+swResampleLoaded+"]");
System.err.println("LIB_AV Device : [loaded "+FFMPEGDynamicLibraryBundleInfo.avDeviceLoaded()+"]");
- System.err.println("LIB_AV Class : "+natives.getClass().getSimpleName());
+ System.err.println("LIB_AV Class : "+(null!= natives ? natives.getClass().getSimpleName() : "n/a"));
libAVVersionGood = avCodecMajorVersionCC == avCodecVersion.getMajor() &&
avFormatMajorVersionCC == avFormatVersion.getMajor() &&
avUtilMajorVersionCC == avUtilVersion.getMajor() &&
- avResampleMajorVersionCC == avResampleVersion.getMajor();
+ ( !avResampleLoaded || avResampleMajorVersionCC == avResampleVersion.getMajor() ) &&
+ ( !swResampleLoaded || swResampleMajorVersionCC == swResampleVersion.getMajor() ) ;
if( !libAVVersionGood ) {
System.err.println("LIB_AV Not Matching Compile-Time / Runtime Major-Version");
}
@@ -183,6 +205,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
avFormatMajorVersionCC = 0;
avCodecMajorVersionCC = 0;
avResampleMajorVersionCC = 0;
+ swResampleMajorVersionCC = 0;
libAVVersionGood = false;
}
available = libAVGood && libAVVersionGood && null != natives ? natives.initIDs0() : false;
@@ -268,8 +291,10 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
System.err.println("initStream: p2 preferred "+preferredAudioFormat+", "+this);
}
- final boolean isCameraInput = null != cameraHostPart;
+ final boolean isCameraInput = null != cameraPath;
final String resStreamLocS;
+ int rw=640, rh=480, rr=15;
+ String sizes = null;
if( isCameraInput ) {
switch(Platform.OS_TYPE) {
case ANDROID:
@@ -278,10 +303,10 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
case HPUX:
case LINUX:
case SUNOS:
- resStreamLocS = dev_video_linux + cameraHostPart;
+ resStreamLocS = dev_video_linux + cameraPath;
break;
case WINDOWS:
- resStreamLocS = cameraHostPart;
+ resStreamLocS = cameraPath;
break;
case MACOS:
case OPENKODE:
@@ -289,13 +314,22 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
resStreamLocS = streamLocS; // FIXME: ??
break;
}
+ if( null != cameraProps ) {
+ sizes = cameraProps.get(CameraPropSizeS);
+ int v = getPropIntVal(cameraProps, CameraPropWidth);
+ if( v > 0 ) { rw = v; }
+ v = getPropIntVal(cameraProps, CameraPropHeight);
+ if( v > 0 ) { rh = v; }
+ v = getPropIntVal(cameraProps, CameraPropRate);
+ if( v > 0 ) { rr = v; }
+ }
} else {
resStreamLocS = streamLocS;
}
final int aMaxChannelCount = audioSink.getMaxSupportedChannels();
final int aPrefSampleRate = preferredAudioFormat.sampleRate;
// setStream(..) issues updateAttributes*(..), and defines avChosenAudioFormat, vid, aid, .. etc
- natives.setStream0(moviePtr, resStreamLocS, isCameraInput, vid, aid, aMaxChannelCount, aPrefSampleRate);
+ natives.setStream0(moviePtr, resStreamLocS, isCameraInput, vid, sizes, rw, rh, rr, aid, aMaxChannelCount, aPrefSampleRate);
}
@Override
@@ -373,11 +407,19 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
tf = GL2ES2.GL_RG; tif=GL2ES2.GL_RG; break;
}
case 3: tf = GL2ES2.GL_RGB; tif=GL.GL_RGB; break;
- case 4: tf = GL2ES2.GL_RGBA; tif=GL.GL_RGBA; break;
+ case 4: if( vPixelFmt == PixelFormat.BGRA ) {
+ tf = GL2ES2.GL_BGRA; tif=GL.GL_RGBA; break;
+ } else {
+ tf = GL2ES2.GL_RGBA; tif=GL.GL_RGBA; break;
+ }
default: throw new RuntimeException("Unsupported bytes-per-pixel / plane "+vBytesPerPixelPerPlane);
}
setTextureFormat(tif, tf);
setTextureType(tt);
+ if(DEBUG) {
+ System.err.println("initGL: p5: video "+vPixelFmt+", planes "+vPlanes+", bpp "+vBitsPerPixel+"/"+vBytesPerPixelPerPlane+
+ ", tex "+texWidth+"x"+texHeight+", usesTexLookupShader "+usesTexLookupShader);
+ }
}
}
@Override
@@ -470,9 +512,6 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
* @param planes
* @param bitsPerPixel
* @param bytesPerPixelPerPlane
- * @param lSz0
- * @param lSz1
- * @param lSz2
* @param tWd0
* @param tWd1
* @param tWd2
@@ -483,7 +522,6 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
* @param audioSamplesPerFrameAndChannel in audio samples per frame and channel
*/
void updateAttributes2(int vid, int pixFmt, int planes, int bitsPerPixel, int bytesPerPixelPerPlane,
- int lSz0, int lSz1, int lSz2,
int tWd0, int tWd1, int tWd2, int vW, int vH,
int aid, int audioSampleFmt, int audioSampleRate,
int audioChannels, int audioSamplesPerFrameAndChannel) {
@@ -495,7 +533,6 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
usesTexLookupShader = false;
texWidth = 0; texHeight = 0;
- final int[] vLinesize = { 0, 0, 0 }; // per plane
final int[] vTexWidth = { 0, 0, 0 }; // per plane
if( STREAM_ID_NONE != vid ) {
@@ -503,7 +540,6 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
vPlanes = planes;
vBitsPerPixel = bitsPerPixel;
vBytesPerPixelPerPlane = bytesPerPixelPerPlane;
- vLinesize[0] = lSz0; vLinesize[1] = lSz1; vLinesize[2] = lSz2;
vTexWidth[0] = tWd0; vTexWidth[1] = tWd1; vTexWidth[2] = tWd2;
switch(vPixelFmt) {
@@ -533,11 +569,12 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
texWidth = vTexWidth[0] + vTexWidth[1] + vTexWidth[2]; texHeight = vH;
break;
case YUYV422: // < packed YUV 4:2:2, 2x 16bpp, Y0 Cb Y1 Cr - stuffed into RGBA half width texture
+ case BGR24:
usesTexLookupShader = true;
texWidth = vTexWidth[0]; texHeight = vH;
break;
+
case RGB24:
- case BGR24:
case ARGB:
case RGBA:
case ABGR:
@@ -567,9 +604,10 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
System.err.println("audio: id "+aid+", fmt "+aSampleFmt+", "+avChosenAudioFormat+", aFrameSize/fc "+audioSamplesPerFrameAndChannel);
System.err.println("video: id "+vid+", fmt "+vW+"x"+vH+", "+vPixelFmt+", planes "+vPlanes+", bpp "+vBitsPerPixel+"/"+vBytesPerPixelPerPlane+", usesTexLookupShader "+usesTexLookupShader);
for(int i=0; i<3; i++) {
- System.err.println("video: "+i+": "+vTexWidth[i]+"/"+vLinesize[i]);
+ System.err.println("video: p["+i+"]: "+vTexWidth[i]);
}
System.err.println("video: total tex "+texWidth+"x"+texHeight);
+ System.err.println(this.toString());
}
}
@@ -674,6 +712,15 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl {
" return vec4(r, g, b, 1);\n"+
"}\n"
;
+ case BGR24:
+ return
+ "vec4 "+texLookupFuncName+"(in "+getTextureSampler2DType()+" image, in vec2 texCoord) {\n"+
+ " "+
+ " vec3 bgr = texture2D(image, texCoord).rgb;\n"+
+ " return vec4(bgr.b, bgr.g, bgr.r, 1);\n"+ /* just swizzle */
+ "}\n"
+ ;
+
default: // FIXME: Add more formats !
throw new InternalError("Add proper mapping of: vPixelFmt "+vPixelFmt+", usesTexLookupShader "+usesTexLookupShader);
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
index 3ee87b5da..b919f22c7 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java
@@ -27,7 +27,6 @@
*/
package jogamp.opengl.util.av.impl;
-import com.jogamp.opengl.util.av.AudioSink;
import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame;
interface FFMPEGNatives {
@@ -37,6 +36,7 @@ interface FFMPEGNatives {
int getAvFormatMajorVersionCC0();
int getAvCodecMajorVersionCC0();
int getAvResampleMajorVersionCC0();
+ int getSwResampleMajorVersionCC0();
boolean initIDs0();
long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
@@ -45,21 +45,22 @@ interface FFMPEGNatives {
/**
* Issues {@link #updateAttributes(int, int, int, int, int, int, int, float, int, int, String, String)}
* and {@link #updateAttributes2(int, int, int, int, int, int, int, int, int, int)}.
- * <p>
- * Always uses {@link AudioSink.AudioFormat}:
- * <pre>
- * [type PCM, sampleRate [10000(?)..44100..48000], sampleSize 16, channelCount 1-2, signed, littleEndian]
- * </pre>
- * </p>
*
* @param moviePtr
* @param url
* @param vid
+ * @param sizes requested video size as string, i.e. 'hd720'. May be null to favor vWidth and vHeight.
+ * @param vWidth requested video width (for camera mode)
+ * @param vHeight requested video width (for camera mode)
+ * @param vRate requested video framerate (for camera mode)
* @param aid
- * @param aPrefChannelCount
* @param aPrefSampleRate
+ * @param aPrefChannelCount
*/
- void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, int aid, int aMaxChannelCount, int aPrefSampleRate);
+ void setStream0(long moviePtr, String url, boolean isCameraInput,
+ int vid, String sizes, int vWidth, int vHeight,
+ int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+
void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
int getVideoPTS0(long moviePtr);
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java
index 9ee0198f4..16ee2dd4b 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGStaticNatives.java
@@ -35,8 +35,5 @@ class FFMPEGStaticNatives {
( vers >> 8 ) & 0xFF,
( vers >> 0 ) & 0xFF );
}
- static native int getAvUtilVersion0(long func);
- static native int getAvFormatVersion0(long func);
- static native int getAvCodecVersion0(long func);
- static native int getAvResampleVersion0(long func);
+ static native int getAvVersion0(long func);
}
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java
index 3b2567655..2a0c9dc3d 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java
@@ -44,6 +44,9 @@ class FFMPEGv08Natives implements FFMPEGNatives {
public native int getAvResampleMajorVersionCC0();
@Override
+ public native int getSwResampleMajorVersionCC0();
+
+ @Override
public native boolean initIDs0();
@Override
@@ -53,7 +56,7 @@ class FFMPEGv08Natives implements FFMPEGNatives {
public native void destroyInstance0(long moviePtr);
@Override
- public native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, int aid, int aMaxChannelCount, int aPrefSampleRate);
+ public native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
@Override
public native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java
index 6c56d3ccb..422f1ceb0 100644
--- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java
@@ -44,6 +44,9 @@ class FFMPEGv09Natives implements FFMPEGNatives {
public native int getAvResampleMajorVersionCC0();
@Override
+ public native int getSwResampleMajorVersionCC0();
+
+ @Override
public native boolean initIDs0();
@Override
@@ -53,7 +56,7 @@ class FFMPEGv09Natives implements FFMPEGNatives {
public native void destroyInstance0(long moviePtr);
@Override
- public native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, int aid, int aMaxChannelCount, int aPrefSampleRate);
+ public native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
@Override
public native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java
new file mode 100644
index 000000000..e3007ab69
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl.util.av.impl;
+
+class FFMPEGv10Natives implements FFMPEGNatives {
+ @Override
+ public native boolean initSymbols0(long[] symbols, int count);
+
+ @Override
+ public native int getAvUtilMajorVersionCC0();
+
+ @Override
+ public native int getAvFormatMajorVersionCC0();
+
+ @Override
+ public native int getAvCodecMajorVersionCC0();
+
+ @Override
+ public native int getAvResampleMajorVersionCC0();
+
+ @Override
+ public native int getSwResampleMajorVersionCC0();
+
+ @Override
+ public native boolean initIDs0();
+
+ @Override
+ public native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose);
+
+ @Override
+ public native void destroyInstance0(long moviePtr);
+
+ @Override
+ public native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate);
+
+ @Override
+ public native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish);
+
+ @Override
+ public native int getVideoPTS0(long moviePtr);
+
+ @Override
+ public native int getAudioPTS0(long moviePtr);
+
+ @Override
+ public native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType);
+
+ @Override
+ public native int play0(long moviePtr);
+
+ @Override
+ public native int pause0(long moviePtr);
+
+ @Override
+ public native int seek0(long moviePtr, int position);
+}
diff --git a/src/jogl/native/libav/ffmpeg_dshow.c b/src/jogl/native/libav/ffmpeg_dshow.c
new file mode 100644
index 000000000..4f8fedb9f
--- /dev/null
+++ b/src/jogl/native/libav/ffmpeg_dshow.c
@@ -0,0 +1,209 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "ffmpeg_dshow.h"
+
+#ifdef _WIN32
+
+#include <stdio.h>
+#include <string.h>
+#include <dshow.h>
+#include <tchar.h>
+
+static HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
+{
+ // Create the System Device Enumerator.
+ ICreateDevEnum *pDevEnum;
+ void *pv = NULL;
+
+ HRESULT hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, &IID_ICreateDevEnum, (void**)&pDevEnum);
+
+ if (SUCCEEDED(hr)) {
+ // Create an enumerator for the category.
+ hr = pDevEnum->lpVtbl->CreateClassEnumerator(pDevEnum, category, ppEnum,0);
+ if (hr == S_FALSE)
+ {
+ hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error.
+ }
+ pDevEnum->lpVtbl->Release(pDevEnum);
+ }
+ return hr;
+}
+
+static void getBSTRChars(BSTR bstr, char *pDest, int destLen) {
+
+ #ifdef UNICODE
+ _sntprintf(pDest, destLen, _T("%s"), bstr);
+ #else
+ _sntprintf(pDest, destLen, _T("%S"), bstr);
+ #endif
+}
+
+
+static int GetDeviceInformation(IEnumMoniker *pEnum, int verbose, int devIdx,
+ char *pDescr, int descrSize,
+ char *pName, int nameSize,
+ char *pPath, int pathSize, int *pWaveID) {
+ IMoniker *pMoniker = NULL;
+ int i=0;
+ int res = devIdx >= 0 ? -1 : 0;
+
+ if( NULL != pDescr ) {
+ *pDescr=0;
+ }
+ if( NULL != pName ) {
+ *pName=0;
+ }
+ if( NULL != pPath ) {
+ *pPath=0;
+ }
+ if( NULL != pWaveID ) {
+ *pWaveID=0;
+ }
+
+ while (pEnum->lpVtbl->Next(pEnum, 1, &pMoniker, NULL) == S_OK) {
+ IPropertyBag *pPropBag;
+ HRESULT hr;
+
+ hr = pMoniker->lpVtbl->BindToStorage(pMoniker, 0, 0, &IID_IPropertyBag, (void**)&pPropBag);
+ if (FAILED(hr)) {
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: bind failed ...\n", i);
+ }
+ pMoniker->lpVtbl->Release(pMoniker);
+ continue;
+ }
+ VARIANT var;
+ VariantInit(&var);
+
+ // Get description or friendly name.
+ hr = pPropBag->lpVtbl->Read(pPropBag, L"Description", &var, 0);
+ if (SUCCEEDED(hr)) {
+ if( i == devIdx && NULL != pDescr ) {
+ res = 0;
+ getBSTRChars(var.bstrVal, pDescr, descrSize);
+ }
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: Descr %S\n", i, var.bstrVal);
+ }
+ VariantClear(&var);
+ } else if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: cannot read Descr..\n", i);
+ }
+
+ hr = pPropBag->lpVtbl->Read(pPropBag, L"FriendlyName", &var, 0);
+ if (SUCCEEDED(hr)) {
+ if( i == devIdx && NULL != pName ) {
+ res = 0;
+ getBSTRChars(var.bstrVal, pName, nameSize);
+ }
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: FName %S\n", i, var.bstrVal);
+ }
+ VariantClear(&var);
+ } else if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: cannot read FName..\n", i);
+ }
+
+ hr = pPropBag->lpVtbl->Write(pPropBag, L"FriendlyName", &var);
+
+ // WaveInID applies only to audio capture devices.
+ hr = pPropBag->lpVtbl->Read(pPropBag, L"WaveInID", &var, 0);
+ if (SUCCEEDED(hr)) {
+ if( i == devIdx && NULL != pWaveID ) {
+ res = 0;
+ *pWaveID=(int)var.lVal;
+ }
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: WaveInID %d\n", i, var.lVal);
+ }
+ VariantClear(&var);
+ }
+
+ hr = pPropBag->lpVtbl->Read(pPropBag, L"DevicePath", &var, 0);
+ if (SUCCEEDED(hr)) {
+ if( i == devIdx && NULL != pPath ) {
+ res = 0;
+ getBSTRChars(var.bstrVal, pPath, pathSize);
+ }
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Dev[%d]: Path %S\n", i, var.bstrVal);
+ }
+ VariantClear(&var);
+ }
+
+ pPropBag->lpVtbl->Release(pPropBag);
+ pMoniker->lpVtbl->Release(pMoniker);
+
+ if( devIdx >= 0 && i == devIdx ) {
+ break; // done!
+ }
+ i++;
+ }
+ return res;
+}
+
+int findDShowVideoDevice(char * dest, int destSize, int devIdx, int verbose) {
+ int res = -1;
+
+ HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ if (SUCCEEDED(hr)) {
+ IEnumMoniker *pEnum;
+
+ hr = EnumerateDevices(&CLSID_VideoInputDeviceCategory, &pEnum);
+ if (SUCCEEDED(hr)) {
+ res = GetDeviceInformation(pEnum, verbose, devIdx, NULL /* pDescr */, 0, dest, destSize, NULL /* pPath */, 0, NULL /* pWaveID */);
+ pEnum->lpVtbl->Release(pEnum);
+ if( verbose ) {
+ fprintf(stderr, "DShowParser: Get VideoInputDevice: res %d, '%s'\n", res, dest);
+ }
+ } else if( verbose ) {
+ fprintf(stderr, "DShowParser: Get VideoInputDevice failed\n");
+ }
+ /**
+ hr = EnumerateDevices(&CLSID_AudioInputDeviceCategory, &pEnum);
+ if (SUCCEEDED(hr)) {
+ res = GetDeviceInformation(pEnum, verbose, devIdx, NULL, 0, NULL, 0, NULL, 0, NULL);
+ pEnum->lpVtbl->Release(pEnum);
+ } else if( verbose ) {
+ fprintf(stderr, "DShowParser: Get AudioInputDevice failed\n");
+ } */
+ CoUninitialize();
+ } else if( verbose ) {
+ fprintf(stderr, "DShowParser: CoInit failed\n");
+ }
+ return res;
+}
+
+#else
+
+int findDShowVideoDevice(char * dest, int destSize, int devIdx, int verbose) {
+ return -1;
+}
+
+#endif
diff --git a/src/jogl/native/libav/ffmpeg_dshow.h b/src/jogl/native/libav/ffmpeg_dshow.h
new file mode 100644
index 000000000..e4ef7096b
--- /dev/null
+++ b/src/jogl/native/libav/ffmpeg_dshow.h
@@ -0,0 +1,47 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#ifndef _FFMPEG_TOOL_H
+#define _FFMPEG_TOOL_H
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+#endif // _WIN32
+
+#include <gluegen_stdint.h>
+#include <gluegen_inttypes.h>
+#include <gluegen_stddef.h>
+#include <gluegen_stdint.h>
+
+extern int findDShowVideoDevice(char * dest, int destSize, int devIdx, int verbose);
+
+
+#endif // _FFMPEG_TOOL_H
+
diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c
index 822007136..9f371a720 100644
--- a/src/jogl/native/libav/ffmpeg_impl_template.c
+++ b/src/jogl/native/libav/ffmpeg_impl_template.c
@@ -30,6 +30,7 @@
#include "JoglCommon.h"
#include "ffmpeg_tool.h"
+#include "ffmpeg_dshow.h"
#include "libavutil/pixdesc.h"
#include "libavutil/samplefmt.h"
@@ -50,28 +51,35 @@ static jmethodID jni_mid_isAudioFormatSupported = NULL;
#define HAS_FUNC(f) (NULL!=(f))
-typedef unsigned (APIENTRYP AVCODEC_VERSION)(void);
typedef unsigned (APIENTRYP AVUTIL_VERSION)(void);
typedef unsigned (APIENTRYP AVFORMAT_VERSION)(void);
+typedef unsigned (APIENTRYP AVCODEC_VERSION)(void);
typedef unsigned (APIENTRYP AVRESAMPLE_VERSION)(void);
+typedef unsigned (APIENTRYP SWRESAMPLE_VERSION)(void);
-static AVCODEC_VERSION sp_avcodec_version;
-static AVFORMAT_VERSION sp_avformat_version;
static AVUTIL_VERSION sp_avutil_version;
+static AVFORMAT_VERSION sp_avformat_version;
+static AVCODEC_VERSION sp_avcodec_version;
static AVRESAMPLE_VERSION sp_avresample_version;
-// count: 4
+static SWRESAMPLE_VERSION sp_swresample_version;
+// count: 5
// libavcodec
typedef int (APIENTRYP AVCODEC_REGISTER_ALL)(void);
typedef int (APIENTRYP AVCODEC_CLOSE)(AVCodecContext *avctx);
typedef void (APIENTRYP AVCODEC_STRING)(char *buf, int buf_size, AVCodecContext *enc, int encode);
-typedef AVCodec *(APIENTRYP AVCODEC_FIND_DECODER)(enum CodecID id);
+typedef AVCodec *(APIENTRYP AVCODEC_FIND_DECODER)(int avCodecID); // lavc 53: 'enum CodecID id', lavc 54: 'enum AVCodecID id'
typedef int (APIENTRYP AVCODEC_OPEN2)(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options); // 53.6.0
typedef AVFrame *(APIENTRYP AVCODEC_ALLOC_FRAME)(void);
typedef void (APIENTRYP AVCODEC_GET_FRAME_DEFAULTS)(AVFrame *frame);
typedef void (APIENTRYP AVCODEC_FREE_FRAME)(AVFrame **frame);
-typedef int (APIENTRYP AVCODEC_DEFAULT_GET_BUFFER)(AVCodecContext *s, AVFrame *pic);
-typedef void (APIENTRYP AVCODEC_DEFAULT_RELEASE_BUFFER)(AVCodecContext *s, AVFrame *pic);
+typedef int (APIENTRYP AVCODEC_DEFAULT_GET_BUFFER)(AVCodecContext *s, AVFrame *pic); // <= 54 (opt), else AVCODEC_DEFAULT_GET_BUFFER2
+typedef void (APIENTRYP AVCODEC_DEFAULT_RELEASE_BUFFER)(AVCodecContext *s, AVFrame *pic); // <= 54 (opt), else AV_FRAME_UNREF
+typedef int (APIENTRYP AVCODEC_DEFAULT_GET_BUFFER2)(AVCodecContext *s, AVFrame *frame, int flags); // 55. (opt)
+typedef int (APIENTRYP AVCODEC_GET_EDGE_WIDTH)();
+typedef int (APIENTRYP AV_IMAGE_FILL_LINESIZES)(int linesizes[4], int pix_fmt, int width); // lavu 51: 'enum PixelFormat pix_fmt', lavu 53: 'enum AVPixelFormat pix_fmt'
+typedef void (APIENTRYP AVCODEC_ALIGN_DIMENSIONS)(AVCodecContext *s, int *width, int *height);
+typedef void (APIENTRYP AVCODEC_ALIGN_DIMENSIONS2)(AVCodecContext *s, int *width, int *height, int linesize_align[AV_NUM_DATA_POINTERS]);
typedef void (APIENTRYP AVCODEC_FLUSH_BUFFERS)(AVCodecContext *avctx);
typedef void (APIENTRYP AV_INIT_PACKET)(AVPacket *pkt);
typedef int (APIENTRYP AV_NEW_PACKET)(AVPacket *pkt, int size);
@@ -88,8 +96,13 @@ static AVCODEC_OPEN2 sp_avcodec_open2; // 53.6.0
static AVCODEC_ALLOC_FRAME sp_avcodec_alloc_frame;
static AVCODEC_GET_FRAME_DEFAULTS sp_avcodec_get_frame_defaults;
static AVCODEC_FREE_FRAME sp_avcodec_free_frame;
-static AVCODEC_DEFAULT_GET_BUFFER sp_avcodec_default_get_buffer;
-static AVCODEC_DEFAULT_RELEASE_BUFFER sp_avcodec_default_release_buffer;
+static AVCODEC_DEFAULT_GET_BUFFER sp_avcodec_default_get_buffer; // <= 54 (opt), else sp_avcodec_default_get_buffer2
+static AVCODEC_DEFAULT_RELEASE_BUFFER sp_avcodec_default_release_buffer; // <= 54 (opt), else sp_av_frame_unref
+static AVCODEC_DEFAULT_GET_BUFFER2 sp_avcodec_default_get_buffer2; // 55. (opt)
+static AVCODEC_GET_EDGE_WIDTH sp_avcodec_get_edge_width;
+static AV_IMAGE_FILL_LINESIZES sp_av_image_fill_linesizes;
+static AVCODEC_ALIGN_DIMENSIONS sp_avcodec_align_dimensions;
+static AVCODEC_ALIGN_DIMENSIONS2 sp_avcodec_align_dimensions2;
static AVCODEC_FLUSH_BUFFERS sp_avcodec_flush_buffers;
static AV_INIT_PACKET sp_av_init_packet;
static AV_NEW_PACKET sp_av_new_packet;
@@ -97,7 +110,7 @@ static AV_DESTRUCT_PACKET sp_av_destruct_packet;
static AV_FREE_PACKET sp_av_free_packet;
static AVCODEC_DECODE_AUDIO4 sp_avcodec_decode_audio4; // 53.25.0
static AVCODEC_DECODE_VIDEO2 sp_avcodec_decode_video2; // 52.23.0
-// count: 21
+// count: 27
// libavutil
typedef void (APIENTRYP AV_FRAME_UNREF)(AVFrame *frame);
@@ -108,7 +121,7 @@ typedef int (APIENTRYP AV_SAMPLES_GET_BUFFER_SIZE)(int *linesize, int nb_channel
typedef int (APIENTRYP AV_GET_BYTES_PER_SAMPLE)(enum AVSampleFormat sample_fmt);
typedef int (APIENTRYP AV_OPT_SET_INT)(void *obj, const char *name, int64_t val, int search_flags);
typedef AVDictionaryEntry* (APIENTRYP AV_DICT_GET)(AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags);
-typedef int (APIENTRYP AV_DICT_COUNT)(AVDictionary **m);
+typedef int (APIENTRYP AV_DICT_COUNT)(AVDictionary *m);
typedef int (APIENTRYP AV_DICT_SET)(AVDictionary **pm, const char *key, const char *value, int flags);
typedef void (APIENTRYP AV_DICT_FREE)(AVDictionary **m);
@@ -124,7 +137,7 @@ static AV_DICT_GET sp_av_dict_get;
static AV_DICT_COUNT sp_av_dict_count;
static AV_DICT_SET sp_av_dict_set;
static AV_DICT_FREE sp_av_dict_free;
-// count: 33
+// count: 39
// libavformat
typedef AVFormatContext *(APIENTRYP AVFORMAT_ALLOC_CONTEXT)(void);
@@ -158,12 +171,12 @@ static AV_READ_PAUSE sp_av_read_pause;
static AVFORMAT_NETWORK_INIT sp_avformat_network_init; // 53.13.0
static AVFORMAT_NETWORK_DEINIT sp_avformat_network_deinit; // 53.13.0
static AVFORMAT_FIND_STREAM_INFO sp_avformat_find_stream_info; // 53.3.0
-// count: 48
+// count: 54
// libavdevice [53.0.0]
typedef int (APIENTRYP AVDEVICE_REGISTER_ALL)(void);
static AVDEVICE_REGISTER_ALL sp_avdevice_register_all;
-// count: 49
+// count: 55
// libavresample [1.0.1]
typedef AVAudioResampleContext* (APIENTRYP AVRESAMPLE_ALLOC_CONTEXT)(void); // 1.0.1
@@ -178,9 +191,23 @@ static AVRESAMPLE_OPEN sp_avresample_open;
static AVRESAMPLE_CLOSE sp_avresample_close;
static AVRESAMPLE_FREE sp_avresample_free;
static AVRESAMPLE_CONVERT sp_avresample_convert;
-// count: 54
+// count: 60
+
+// libswresample [1...]
+typedef int (APIENTRYP AV_OPT_SET_SAMPLE_FMT)(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); // actually lavu .. but exist only w/ swresample!
+typedef struct SwrContext *(APIENTRYP SWR_ALLOC)(void);
+typedef int (APIENTRYP SWR_INIT)(struct SwrContext *s);
+typedef void (APIENTRYP SWR_FREE)(struct SwrContext **s);
+typedef int (APIENTRYP SWR_CONVERT)(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in , int in_count);
-#define SYMBOL_COUNT 54
+static AV_OPT_SET_SAMPLE_FMT sp_av_opt_set_sample_fmt;
+static SWR_ALLOC sp_swr_alloc;
+static SWR_INIT sp_swr_init;
+static SWR_FREE sp_swr_free;
+static SWR_CONVERT sp_swr_convert;
+// count: 65
+
+#define SYMBOL_COUNT 65
JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0)
(JNIEnv *env, jobject instance, jobject jSymbols, jint count)
@@ -198,10 +225,11 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0)
i = 0;
symbols = (int64_t *) (*env)->GetPrimitiveArrayCritical(env, jSymbols, NULL);
- sp_avcodec_version = (AVCODEC_VERSION) (intptr_t) symbols[i++];
- sp_avformat_version = (AVFORMAT_VERSION) (intptr_t) symbols[i++];
sp_avutil_version = (AVUTIL_VERSION) (intptr_t) symbols[i++];
+ sp_avformat_version = (AVFORMAT_VERSION) (intptr_t) symbols[i++];
+ sp_avcodec_version = (AVCODEC_VERSION) (intptr_t) symbols[i++];
sp_avresample_version = (AVRESAMPLE_VERSION) (intptr_t) symbols[i++];
+ sp_swresample_version = (SWRESAMPLE_VERSION) (intptr_t) symbols[i++];
sp_avcodec_register_all = (AVCODEC_REGISTER_ALL) (intptr_t) symbols[i++];
sp_avcodec_close = (AVCODEC_CLOSE) (intptr_t) symbols[i++];
@@ -213,6 +241,11 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0)
sp_avcodec_free_frame = (AVCODEC_FREE_FRAME) (intptr_t) symbols[i++];
sp_avcodec_default_get_buffer = (AVCODEC_DEFAULT_GET_BUFFER) (intptr_t) symbols[i++];
sp_avcodec_default_release_buffer = (AVCODEC_DEFAULT_RELEASE_BUFFER) (intptr_t) symbols[i++];
+ sp_avcodec_default_get_buffer2 = (AVCODEC_DEFAULT_GET_BUFFER2) (intptr_t) symbols[i++];
+ sp_avcodec_get_edge_width = (AVCODEC_GET_EDGE_WIDTH) (intptr_t) symbols[i++];
+ sp_av_image_fill_linesizes = (AV_IMAGE_FILL_LINESIZES) (intptr_t) symbols[i++];
+ sp_avcodec_align_dimensions = (AVCODEC_ALIGN_DIMENSIONS) (intptr_t) symbols[i++];
+ sp_avcodec_align_dimensions2 = (AVCODEC_ALIGN_DIMENSIONS2) (intptr_t) symbols[i++];
sp_avcodec_flush_buffers = (AVCODEC_FLUSH_BUFFERS) (intptr_t) symbols[i++];
sp_av_init_packet = (AV_INIT_PACKET) (intptr_t) symbols[i++];
sp_av_new_packet = (AV_NEW_PACKET) (intptr_t) symbols[i++];
@@ -258,6 +291,12 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0)
sp_avresample_free = (AVRESAMPLE_FREE) (intptr_t) symbols[i++];
sp_avresample_convert = (AVRESAMPLE_CONVERT) (intptr_t) symbols[i++];
+ sp_av_opt_set_sample_fmt = (AV_OPT_SET_SAMPLE_FMT) (intptr_t) symbols[i++];
+ sp_swr_alloc = (SWR_ALLOC) (intptr_t) symbols[i++];
+ sp_swr_init = (SWR_INIT) (intptr_t) symbols[i++];
+ sp_swr_free = (SWR_FREE) (intptr_t) symbols[i++];
+ sp_swr_convert = (SWR_CONVERT) (intptr_t) symbols[i++];
+
(*env)->ReleasePrimitiveArrayCritical(env, jSymbols, symbols, 0);
if(SYMBOL_COUNT != i) {
@@ -282,7 +321,6 @@ static void _updateJavaAttributes(JNIEnv *env, jobject instance, FFMPEGToolBasic
(*env)->CallVoidMethod(env, pAV->ffmpegMediaPlayer, jni_mid_updateAttributes2,
pAV->vid, pAV->vPixFmt, pAV->vBufferPlanes,
pAV->vBitsPerPixel, pAV->vBytesPerPixelPerPlane,
- pAV->vLinesize[0], pAV->vLinesize[1], pAV->vLinesize[2],
pAV->vTexWidth[0], pAV->vTexWidth[1], pAV->vTexWidth[2],
pAV->vWidth, pAV->vHeight,
pAV->aid, pAV->aSampleFmtOut, pAV->aSampleRateOut, pAV->aChannelsOut, pAV->aFrameSize);
@@ -300,9 +338,13 @@ static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) {
int i;
if(NULL != pAV) {
// Close the A resampler
- if( NULL != pAV->aResampleCtx ) {
- sp_avresample_free(&pAV->aResampleCtx);
- pAV->aResampleCtx = NULL;
+ if( NULL != pAV->avResampleCtx ) {
+ sp_avresample_free(&pAV->avResampleCtx);
+ pAV->avResampleCtx = NULL;
+ }
+ if( NULL != pAV->swResampleCtx ) {
+ sp_swr_free(&pAV->swResampleCtx);
+ pAV->swResampleCtx = NULL;
}
if( NULL != pAV->aResampleBuffer ) {
sp_av_free(pAV->aResampleBuffer);
@@ -430,9 +472,15 @@ JNIEXPORT jint JNICALL FF_FUNC(getAvResampleMajorVersionCC0)
return (jint) LIBAVRESAMPLE_VERSION_MAJOR;
}
+JNIEXPORT jint JNICALL FF_FUNC(getSwResampleMajorVersionCC0)
+ (JNIEnv *env, jobject instance) {
+ return (jint) LIBSWRESAMPLE_VERSION_MAJOR;
+}
+
JNIEXPORT jboolean JNICALL FF_FUNC(initIDs0)
(JNIEnv *env, jobject instance)
{
+ jboolean res = JNI_TRUE;
JoglCommon_init(env);
jclass c;
@@ -452,7 +500,7 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initIDs0)
jni_mid_pushSound = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "pushSound", "(Ljava/nio/ByteBuffer;II)V");
jni_mid_updateAttributes1 = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "updateAttributes", "(IIIIIIIFIIILjava/lang/String;Ljava/lang/String;)V");
- jni_mid_updateAttributes2 = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "updateAttributes2", "(IIIIIIIIIIIIIIIIII)V");
+ jni_mid_updateAttributes2 = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "updateAttributes2", "(IIIIIIIIIIIIIII)V");
jni_mid_isAudioFormatSupported = (*env)->GetMethodID(env, ffmpegMediaPlayerClazz, "isAudioFormatSupported", "(III)Z");
if(jni_mid_pushSound == NULL ||
@@ -461,7 +509,22 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initIDs0)
jni_mid_isAudioFormatSupported == NULL) {
return JNI_FALSE;
}
- return JNI_TRUE;
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ if(!HAS_FUNC(sp_avcodec_default_get_buffer2) ||
+ !HAS_FUNC(sp_av_frame_unref) ) {
+ fprintf(stderr, "avcodec >= 55: avcodec_default_get_buffer2 %p, av_frame_unref %p\n",
+ sp_avcodec_default_get_buffer2, sp_av_frame_unref);
+ res = JNI_FALSE;
+ }
+ #else
+ if(!HAS_FUNC(sp_avcodec_default_get_buffer) ||
+ !HAS_FUNC(sp_avcodec_default_release_buffer)) {
+ fprintf(stderr, "avcodec < 55: avcodec_default_get_buffer %p, sp_avcodec_default_release_buffer %p\n",
+ sp_avcodec_default_get_buffer2, sp_avcodec_default_release_buffer);
+ res = JNI_FALSE;
+ }
+ #endif
+ return res;
}
JNIEXPORT jlong JNICALL FF_FUNC(createInstance0)
@@ -480,6 +543,11 @@ JNIEXPORT jlong JNICALL FF_FUNC(createInstance0)
} else {
pAV->avresampleVersion = 0;
}
+ if(HAS_FUNC(sp_swresample_version)) {
+ pAV->swresampleVersion = sp_swresample_version();
+ } else {
+ pAV->swresampleVersion = 0;
+ }
#if LIBAVCODEC_VERSION_MAJOR >= 55
// TODO: We keep code on using 1 a/v frame per decoding cycle now.
@@ -496,6 +564,10 @@ JNIEXPORT jlong JNICALL FF_FUNC(createInstance0)
pAV->vid=AV_STREAM_ID_AUTO;
pAV->aid=AV_STREAM_ID_AUTO;
+ if(pAV->verbose) {
+ fprintf(stderr, "Info: Use avresample %d, swresample %d, device %d, refCount %d\n",
+ AV_HAS_API_AVRESAMPLE(pAV), AV_HAS_API_SWRESAMPLE(pAV), HAS_FUNC(sp_avdevice_register_all), pAV->useRefCountedFrames);
+ }
return (jlong) (intptr_t) pAV;
}
@@ -529,7 +601,7 @@ static int64_t evalPTS(PTSStats *ptsStats, int64_t inPTS, int64_t inDTS);
static AVInputFormat* tryAVInputFormat(const char * name, int verbose) {
AVInputFormat* inFmt = sp_av_find_input_format(name);
if( verbose) {
- if ( inFmt == NULL ) {
+ if ( NULL == inFmt ) {
fprintf(stderr, "Warning: Could not find input format '%s'\n", name);
} else {
fprintf(stderr, "Info: Found input format '%s'\n", name);
@@ -565,10 +637,41 @@ static AVInputFormat* findAVInputFormat(int verbose) {
return inFmt;
}
+#if 0
+static void getAlignedLinesizes(AVCodecContext *avctx, int linesize[/*4*/]) {
+ int stride_align[AV_NUM_DATA_POINTERS];
+ int w = avctx->width;
+ int h = avctx->height;
+ int unaligned;
+ int i;
+
+ sp_avcodec_align_dimensions2(avctx, &w, &h, stride_align);
+
+ if (!(avctx->flags & CODEC_FLAG_EMU_EDGE)) {
+ int edge_width = sp_avcodec_get_edge_width();
+ w += edge_width * 2;
+ h += edge_width * 2;
+ }
+
+ do {
+ // Get alignment for all planes (-> YUVP .. etc)
+ sp_av_image_fill_linesizes(linesize, avctx->pix_fmt, w);
+ // increase alignment of w for next try (rhs gives the lowest bit set in w)
+ w += w & ~(w - 1);
+
+ unaligned = 0;
+ for (i = 0; i < 4; i++)
+ unaligned |= linesize[i] % stride_align[i];
+ } while (unaligned);
+}
+#endif
+
JNIEXPORT void JNICALL FF_FUNC(setStream0)
- (JNIEnv *env, jobject instance, jlong ptr, jstring jURL, jboolean jIsCameraInput, jint vid, jint aid,
- jint aMaxChannelCount, jint aPrefSampleRate)
+ (JNIEnv *env, jobject instance, jlong ptr, jstring jURL, jboolean jIsCameraInput,
+ jint vid, jstring jSizeS, jint vWidth, jint vHeight, jint vRate,
+ jint aid, jint aMaxChannelCount, jint aPrefSampleRate)
{
+ char cameraName[256];
int res, i;
jboolean iscopy;
FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)(intptr_t)ptr;
@@ -592,31 +695,59 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
pAV->pFormatCtx = sp_avformat_alloc_context();
const char *urlPath = (*env)->GetStringUTFChars(env, jURL, &iscopy);
+ const char *filename = urlPath; // allow changing path for camera ..
// Open video file
AVDictionary *inOpts = NULL;
AVInputFormat* inFmt = NULL;
if( jIsCameraInput ) {
+ char buffer[256];
inFmt = findAVInputFormat(pAV->verbose);
if( NULL == inFmt ) {
JoglCommon_throwNewRuntimeException(env, "Couldn't find input format for camera: %s", urlPath);
(*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
return;
}
- // set maximum values, driver shall 'degrade' ..
- // sp_av_dict_set(&inOpts, "video_size", "640x480", 0);
- // sp_av_dict_set(&inOpts, "video_size", "1280x720", 0);
- sp_av_dict_set(&inOpts, "video_size", "hd720", 0); // video4linux, vfwcap, ..
- // sp_av_dict_set(&inOpts, "video_size", "1280x1024", 0);
- // sp_av_dict_set(&inOpts, "video_size", "320x240", 0);
- sp_av_dict_set(&inOpts, "framerate", "60", 0); // not setting a framerate causes some drivers to crash!
+ if(pAV->verbose) {
+ fprintf(stderr, "Camera: Format: %s (%s)\n", inFmt->long_name, inFmt->name);
+ }
+ if( 0 == strncmp(inFmt->name, "dshow", 255) ) {
+ int devIdx = atoi(urlPath);
+ strncpy(cameraName, "video=", sizeof(cameraName));
+ res = findDShowVideoDevice(cameraName+6, sizeof(cameraName)-6, devIdx, pAV->verbose);
+ if( 0 == res ) {
+ if(pAV->verbose) {
+ fprintf(stderr, "Camera %d found: %s\n", devIdx, cameraName);
+ }
+ filename = cameraName;
+ } else if(pAV->verbose) {
+ fprintf(stderr, "Camera %d not found\n", devIdx);
+ }
+ }
+
+ const char *sizeS = NULL != jSizeS ? (*env)->GetStringUTFChars(env, jSizeS, &iscopy) : NULL;
+ if( NULL != sizeS ) {
+ snprintf(buffer, sizeof(buffer), "%s", sizeS);
+ (*env)->ReleaseStringChars(env, jSizeS, (const jchar *)sizeS);
+ } else {
+ snprintf(buffer, sizeof(buffer), "%dx%d", vWidth, vHeight);
+ }
+ if(pAV->verbose) {
+ fprintf(stderr, "Camera: Size: %s\n", buffer);
+ }
+ sp_av_dict_set(&inOpts, "video_size", buffer, 0);
+ snprintf(buffer, sizeof(buffer), "%d", vRate);
+ if(pAV->verbose) {
+ fprintf(stderr, "Camera: FPS: %s\n", buffer);
+ }
+ sp_av_dict_set(&inOpts, "framerate", buffer, 0); // not setting a framerate causes some drivers to crash!
}
- res = sp_avformat_open_input(&pAV->pFormatCtx, urlPath, inFmt, NULL != inOpts ? &inOpts : NULL);
+ res = sp_avformat_open_input(&pAV->pFormatCtx, filename, inFmt, NULL != inOpts ? &inOpts : NULL);
if( NULL != inOpts ) {
sp_av_dict_free(&inOpts);
}
if(res != 0) {
- JoglCommon_throwNewRuntimeException(env, "Couldn't open URI: %s, err %d", urlPath, res);
+ JoglCommon_throwNewRuntimeException(env, "Couldn't open URI: %s [%dx%d @ %d hz], err %d", filename, vWidth, vHeight, vRate, res);
(*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
return;
}
@@ -630,9 +761,11 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
if(pAV->verbose) {
// Dump information about file onto standard error
- sp_av_dump_format(pAV->pFormatCtx, 0, urlPath, JNI_FALSE);
+ sp_av_dump_format(pAV->pFormatCtx, 0, filename, JNI_FALSE);
}
(*env)->ReleaseStringChars(env, jURL, (const jchar *)urlPath);
+
+
// FIXME: Libav Binary compatibility! JAU01
if (pAV->pFormatCtx->duration != AV_NOPTS_VALUE) {
pAV->duration = pAV->pFormatCtx->duration / AV_TIME_BASE_MSEC;
@@ -707,9 +840,10 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
pAV->pACodecCtx->request_sample_fmt=AV_SAMPLE_FMT_S16;
if( 1 <= aMaxChannelCount && aMaxChannelCount <= 2 ) {
pAV->pACodecCtx->request_channel_layout=getDefaultAudioChannelLayout(aMaxChannelCount);
- if( AV_HAS_API_REQUEST_CHANNELS(pAV) ) {
+ #if LIBAVCODEC_VERSION_MAJOR < 54
+ /** Until 55.0.0, but stopped working w/ 54 already :( */
pAV->pACodecCtx->request_channels=aMaxChannelCount;
- }
+ #endif
}
pAV->pACodecCtx->skip_frame=AVDISCARD_DEFAULT;
@@ -745,12 +879,23 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
pAV->frames_audio = pAV->pAStream->nb_frames;
pAV->aSinkSupport = _isAudioFormatSupported(env, pAV->ffmpegMediaPlayer, pAV->aSampleFmt, pAV->aSampleRate, pAV->aChannels);
if( pAV->verbose ) {
- fprintf(stderr, "A channels %d [l %d], sample_rate %d, frame_size %d, frame_number %d, r_frame_rate %f, avg_frame_rate %f, nb_frames %d, [maxChan %d, prefRate %d, req_chan_layout %d, req_chan %d], sink-support %d \n",
+ fprintf(stderr, "A channels %d [l %d], sample_rate %d, frame_size %d, frame_number %d, [afps %f, rfps %f, cfps %f, sfps %f], nb_frames %d, [maxChan %d, prefRate %d, req_chan_layout %d, req_chan %d], sink-support %d \n",
pAV->aChannels, pAV->pACodecCtx->channel_layout, pAV->aSampleRate, pAV->aFrameSize, pAV->pACodecCtx->frame_number,
- my_av_q2f(pAV->pAStream->r_frame_rate),
my_av_q2f(pAV->pAStream->avg_frame_rate),
+ #if LIBAVCODEC_VERSION_MAJOR < 55
+ my_av_q2f(pAV->pVStream->r_frame_rate),
+ #else
+ 0.0f,
+ #endif
+ my_av_q2f_r(pAV->pAStream->codec->time_base),
+ my_av_q2f_r(pAV->pAStream->time_base),
pAV->pAStream->nb_frames,
- aMaxChannelCount, aPrefSampleRate, pAV->pACodecCtx->request_channel_layout, pAV->pACodecCtx->request_channels,
+ aMaxChannelCount, aPrefSampleRate, pAV->pACodecCtx->request_channel_layout,
+ #if LIBAVCODEC_VERSION_MAJOR < 54
+ pAV->pACodecCtx->request_channels,
+ #else
+ 0,
+ #endif
pAV->aSinkSupport);
}
@@ -759,11 +904,11 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
pAV->aChannelsOut = pAV->aChannels;
pAV->aSampleRateOut = pAV->aSampleRate;
- if( AV_HAS_API_AVRESAMPLE(pAV) &&
+ if( ( AV_HAS_API_AVRESAMPLE(pAV) || AV_HAS_API_SWRESAMPLE(pAV) ) &&
( pAV->aSampleFmt != AV_SAMPLE_FMT_S16 ||
- ( 0 != aPrefSampleRate && pAV->aSampleRate != aPrefSampleRate ) ||
- !pAV->aSinkSupport )
- ) {
+ ( 0 != aPrefSampleRate && pAV->aSampleRate != aPrefSampleRate ) ||
+ !pAV->aSinkSupport ) ) {
+
if( 0 == aPrefSampleRate ) {
aPrefSampleRate = pAV->aSampleRate;
}
@@ -782,25 +927,48 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
aSampleRateOut = aPrefSampleRate;
aSinkSupport = 1;
}
+
if( aSinkSupport ) {
- pAV->aResampleCtx = sp_avresample_alloc_context();
- sp_av_opt_set_int(pAV->aResampleCtx, "in_channel_layout", pAV->pACodecCtx->channel_layout, 0);
- sp_av_opt_set_int(pAV->aResampleCtx, "out_channel_layout", getDefaultAudioChannelLayout(aChannelsOut), 0);
- sp_av_opt_set_int(pAV->aResampleCtx, "in_sample_rate", pAV->aSampleRate, 0);
- sp_av_opt_set_int(pAV->aResampleCtx, "out_sample_rate", aSampleRateOut, 0);
- sp_av_opt_set_int(pAV->aResampleCtx, "in_sample_fmt", pAV->aSampleFmt, 0);
- sp_av_opt_set_int(pAV->aResampleCtx, "out_sample_fmt", aSampleFmtOut, 0);
-
- if ( sp_avresample_open(pAV->aResampleCtx) < 0 ) {
- sp_avresample_free(&pAV->aResampleCtx);
- pAV->aResampleCtx = NULL;
- fprintf(stderr, "error initializing libavresample\n");
- } else {
- // OK
- pAV->aSampleFmtOut = aSampleFmtOut;
- pAV->aChannelsOut = aChannelsOut;
- pAV->aSampleRateOut = aSampleRateOut;
- pAV->aSinkSupport = 1;
+ if( AV_HAS_API_AVRESAMPLE(pAV) ) {
+ pAV->avResampleCtx = sp_avresample_alloc_context();
+ sp_av_opt_set_int(pAV->avResampleCtx, "in_channel_layout", pAV->pACodecCtx->channel_layout, 0);
+ sp_av_opt_set_int(pAV->avResampleCtx, "out_channel_layout", getDefaultAudioChannelLayout(aChannelsOut), 0);
+ sp_av_opt_set_int(pAV->avResampleCtx, "in_sample_rate", pAV->aSampleRate, 0);
+ sp_av_opt_set_int(pAV->avResampleCtx, "out_sample_rate", aSampleRateOut, 0);
+ sp_av_opt_set_int(pAV->avResampleCtx, "in_sample_fmt", pAV->aSampleFmt, 0);
+ sp_av_opt_set_int(pAV->avResampleCtx, "out_sample_fmt", aSampleFmtOut, 0);
+
+ if ( sp_avresample_open(pAV->avResampleCtx) < 0 ) {
+ sp_avresample_free(&pAV->avResampleCtx);
+ pAV->avResampleCtx = NULL;
+ fprintf(stderr, "error initializing avresample ctx\n");
+ } else {
+ // OK
+ pAV->aSampleFmtOut = aSampleFmtOut;
+ pAV->aChannelsOut = aChannelsOut;
+ pAV->aSampleRateOut = aSampleRateOut;
+ pAV->aSinkSupport = 1;
+ }
+ } else if( AV_HAS_API_SWRESAMPLE(pAV) ) {
+ pAV->swResampleCtx = sp_swr_alloc();
+ sp_av_opt_set_int(pAV->swResampleCtx, "in_channel_layout", pAV->pACodecCtx->channel_layout, 0);
+ sp_av_opt_set_int(pAV->swResampleCtx, "out_channel_layout", getDefaultAudioChannelLayout(aChannelsOut), 0);
+ sp_av_opt_set_int(pAV->swResampleCtx, "in_sample_rate", pAV->aSampleRate, 0);
+ sp_av_opt_set_int(pAV->swResampleCtx, "out_sample_rate", aSampleRateOut, 0);
+ sp_av_opt_set_sample_fmt(pAV->swResampleCtx, "in_sample_fmt", pAV->aSampleFmt, 0);
+ sp_av_opt_set_sample_fmt(pAV->swResampleCtx, "out_sample_fmt", aSampleFmtOut, 0);
+
+ if ( sp_swr_init(pAV->swResampleCtx) < 0 ) {
+ sp_swr_free(&pAV->swResampleCtx);
+ pAV->swResampleCtx = NULL;
+ fprintf(stderr, "error initializing swresample ctx\n");
+ } else {
+ // OK
+ pAV->aSampleFmtOut = aSampleFmtOut;
+ pAV->aChannelsOut = aChannelsOut;
+ pAV->aSampleRateOut = aSampleRateOut;
+ pAV->aSinkSupport = 1;
+ }
}
}
}
@@ -867,10 +1035,18 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
pAV->pVCodecCtx->time_base.den=1000;
}
// FIXME: Libav Binary compatibility! JAU01
- if( 0 < pAV->pVStream->avg_frame_rate.den ) {
+ if( pAV->pVStream->avg_frame_rate.den && pAV->pVStream->avg_frame_rate.num ) {
pAV->fps = my_av_q2f(pAV->pVStream->avg_frame_rate);
- } else {
+ #if LIBAVCODEC_VERSION_MAJOR < 55
+ } else if( pAV->pVStream->r_frame_rate.den && pAV->pVStream->r_frame_rate.num ) {
pAV->fps = my_av_q2f(pAV->pVStream->r_frame_rate);
+ #endif
+ } else if( pAV->pVStream->codec->time_base.den && pAV->pVStream->codec->time_base.num ) {
+ pAV->fps = my_av_q2f_r(pAV->pVStream->codec->time_base);
+ } else if( pAV->pVStream->time_base.den && pAV->pVStream->time_base.num ) {
+ pAV->fps = my_av_q2f_r(pAV->pVStream->time_base);
+ } else {
+ pAV->fps = 0.0f; // duh!
}
pAV->frames_video = pAV->pVStream->nb_frames;
@@ -886,35 +1062,78 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
}
if( pAV->verbose ) {
- fprintf(stderr, "V frame_size %d, frame_number %d, r_frame_rate %f %d/%d, avg_frame_rate %f %d/%d, nb_frames %d, size %dx%d, fmt 0x%X, bpp %d, planes %d\n",
+ fprintf(stderr, "V frame_size %d, frame_number %d, [afps %f, rfps %f, cfps %f, sfps %f] -> %f fps, nb_frames %d, size %dx%d, fmt 0x%X, bpp %d, planes %d, codecCaps 0x%X\n",
pAV->pVCodecCtx->frame_size, pAV->pVCodecCtx->frame_number,
- my_av_q2f(pAV->pVStream->r_frame_rate), pAV->pVStream->r_frame_rate.num, pAV->pVStream->r_frame_rate.den,
- my_av_q2f(pAV->pVStream->avg_frame_rate), pAV->pVStream->avg_frame_rate.num, pAV->pVStream->avg_frame_rate.den,
+ my_av_q2f(pAV->pVStream->avg_frame_rate),
+ #if LIBAVCODEC_VERSION_MAJOR < 55
+ my_av_q2f(pAV->pVStream->r_frame_rate),
+ #else
+ 0.0f,
+ #endif
+ my_av_q2f_r(pAV->pVStream->codec->time_base),
+ my_av_q2f_r(pAV->pVStream->time_base),
+ pAV->fps,
pAV->pVStream->nb_frames,
- pAV->vWidth, pAV->vHeight, pAV->vPixFmt, pAV->vBitsPerPixel, pAV->vBufferPlanes);
+ pAV->vWidth, pAV->vHeight, pAV->vPixFmt, pAV->vBitsPerPixel, pAV->vBufferPlanes, pAV->pVCodecCtx->codec->capabilities);
+ }
+ #if 0
+ // Check CODEC_CAP_DR1, i.e. codec must handle get_buffer(), i.e. allocs 'em.
+ {
+ int codecHandlesBuffers = 0 != ( pAV->pVCodecCtx->codec->capabilities & CODEC_CAP_DR1 );
+ if( !codecHandlesBuffers ) {
+ JoglCommon_throwNewRuntimeException(env, "Codec does not handle buffers (!CODEC_CAP_DR1)");
+ return;
+ }
}
+ #endif
pAV->pVFrame=sp_avcodec_alloc_frame();
if( pAV->pVFrame == NULL ) {
JoglCommon_throwNewRuntimeException(env, "Couldn't alloc video frame");
return;
}
- res = sp_avcodec_default_get_buffer(pAV->pVCodecCtx, pAV->pVFrame);
- if(0==res) {
+ {
const int32_t bytesPerPixel = ( pAV->vBitsPerPixel + 7 ) / 8 ;
if(1 == pAV->vBufferPlanes) {
pAV->vBytesPerPixelPerPlane = bytesPerPixel;
} else {
pAV->vBytesPerPixelPerPlane = 1;
}
+ int32_t vLinesize[4];
if( pAV->vBufferPlanes > 1 ) {
- for(i=0; i<3; i++) {
- // FIXME: Libav Binary compatibility! JAU01
- pAV->vLinesize[i] = pAV->pVFrame->linesize[i];
- pAV->vTexWidth[i] = pAV->vLinesize[i] / pAV->vBytesPerPixelPerPlane ;
- }
+ #if 0
+ getAlignedLinesizes(pAV->pVCodecCtx, vLinesize);
+ for(i=0; i<pAV->vBufferPlanes; i++) {
+ // FIXME: Libav Binary compatibility! JAU01
+ pAV->vTexWidth[i] = vLinesize[i] / pAV->vBytesPerPixelPerPlane ;
+ }
+ #else
+ // Min. requirement for 'get_buffer2' !
+ pAV->pVFrame->width = pAV->pVCodecCtx->width;
+ pAV->pVFrame->height = pAV->pVCodecCtx->height;
+ pAV->pVFrame->format = pAV->pVCodecCtx->pix_fmt;
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ res = sp_avcodec_default_get_buffer2(pAV->pVCodecCtx, pAV->pVFrame, 0);
+ #else
+ res = sp_avcodec_default_get_buffer(pAV->pVCodecCtx, pAV->pVFrame);
+ #endif
+ if(0!=res) {
+ JoglCommon_throwNewRuntimeException(env, "Couldn't peek video buffer dimension");
+ return;
+ }
+ for(i=0; i<pAV->vBufferPlanes; i++) {
+ // FIXME: Libav Binary compatibility! JAU01
+ vLinesize[i] = pAV->pVFrame->linesize[i];
+ pAV->vTexWidth[i] = vLinesize[i] / pAV->vBytesPerPixelPerPlane ;
+ }
+ #if LIBAVCODEC_VERSION_MAJOR >= 55
+ sp_av_frame_unref(pAV->pVFrame);
+ #else
+ sp_avcodec_default_release_buffer(pAV->pVCodecCtx, pAV->pVFrame);
+ #endif
+ #endif
} else {
- pAV->vLinesize[0] = pAV->pVCodecCtx->width * pAV->vBytesPerPixelPerPlane;
+ vLinesize[0] = pAV->pVCodecCtx->width * pAV->vBytesPerPixelPerPlane;
if( pAV->vPixFmt == PIX_FMT_YUYV422 ) {
// Stuff 2x 16bpp (YUYV) into one RGBA pixel!
pAV->vTexWidth[0] = pAV->pVCodecCtx->width / 2;
@@ -922,10 +1141,11 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0)
pAV->vTexWidth[0] = pAV->pVCodecCtx->width;
}
}
- sp_avcodec_default_release_buffer(pAV->pVCodecCtx, pAV->pVFrame);
- } else {
- JoglCommon_throwNewRuntimeException(env, "Couldn't peek video buffer dimension");
- return;
+ if( pAV->verbose ) {
+ for(i=0; i<pAV->vBufferPlanes; i++) {
+ fprintf(stderr, "P[%d]: %d texw * %d bytesPP -> %d line\n", i, pAV->vTexWidth[i], pAV->vBytesPerPixelPerPlane, vLinesize[i]);
+ }
+ }
}
}
pAV->vPTS=0;
@@ -945,7 +1165,7 @@ JNIEXPORT void JNICALL FF_FUNC(setGLFuncs0)
pAV->procAddrGLFinish = (PFNGLFINISH) (intptr_t)jProcAddrGLFinish;
}
-#if 0
+#if 1
#define DBG_TEXSUBIMG2D_a(c,p,w1,w2,h,i) fprintf(stderr, "TexSubImage2D.%c offset %d / %d, size %d x %d, ", c, (w1*p->pVCodecCtx->width)/w2, p->pVCodecCtx->height/h, p->vTexWidth[i], p->pVCodecCtx->height/h)
#define DBG_TEXSUBIMG2D_b(p) fprintf(stderr, "err 0x%X\n", pAV->procAddrGLGetError())
#else
@@ -1046,7 +1266,7 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0)
if( NULL != env ) {
void* data_ptr = pAFrameCurrent->data[0]; // default
- if( NULL != pAV->aResampleCtx ) {
+ if( NULL != pAV->avResampleCtx || NULL != pAV->swResampleCtx ) {
enum AVSampleFormat aSampleFmtOut; // out fmt
int32_t aChannelsOut;
int32_t aSampleRateOut;
@@ -1068,12 +1288,18 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0)
}
pAV->aResampleBuffer = tmp_out;
- out_samples = sp_avresample_convert(pAV->aResampleCtx,
- &pAV->aResampleBuffer,
- out_linesize, nb_samples,
- pAFrameCurrent->data,
- pAFrameCurrent->linesize[0],
- pAFrameCurrent->nb_samples);
+ if( NULL != pAV->avResampleCtx ) {
+ out_samples = sp_avresample_convert(pAV->avResampleCtx,
+ &pAV->aResampleBuffer,
+ out_linesize, nb_samples,
+ pAFrameCurrent->data,
+ pAFrameCurrent->linesize[0],
+ pAFrameCurrent->nb_samples);
+ } else if( NULL != pAV->swResampleCtx ) {
+ out_samples = sp_swr_convert(pAV->swResampleCtx,
+ &pAV->aResampleBuffer, nb_samples,
+ (const uint8_t **)pAFrameCurrent->data, pAFrameCurrent->nb_samples);
+ }
if (out_samples < 0) {
JoglCommon_throwNewRuntimeException(env, "avresample_convert() failed");
return;
@@ -1154,11 +1380,17 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0)
const int32_t frame_repeat_i = pAV->pVFrame->repeat_pict * (frame_delay_i / 2);
const char * warn = frame_repeat_i > 0 ? "REPEAT" : "NORMAL" ;
+ const char * oopsLsz = pAV->pVFrame->linesize[0] <= 0 ? "Ooops LSZ" : "OK" ;
- fprintf(stderr, "V fix_pts %d, pts %d [pkt_pts %ld], dts %d [pkt_dts %ld], time d(%lf s + r %lf = %lf s), i(%d ms + r %d = %d ms) - %s - f# %d\n",
+ fprintf(stderr, "V fix_pts %d, pts %d [pkt_pts %ld], dts %d [pkt_dts %ld], time d(%lf s + r %lf = %lf s), i(%d ms + r %d = %d ms) - %s - f# %d, data %p, lsz %d (%s)\n",
pAV->vPTS, vPTS, pkt_pts, vDTS, pkt_dts,
frame_delay_d, frame_repeat_d, (frame_delay_d + frame_repeat_d),
- frame_delay_i, frame_repeat_i, (frame_delay_i + frame_repeat_i), warn, frameCount);
+ frame_delay_i, frame_repeat_i, (frame_delay_i + frame_repeat_i), warn, frameCount,
+ pAV->pVFrame->data[0], pAV->pVFrame->linesize[0], oopsLsz);
+ }
+ if( pAV->pVFrame->linesize[0] <= 0 ) {
+ // Ooops !
+ continue;
}
resPTS = pAV->vPTS; // Video Frame!
diff --git a/src/jogl/native/libav/ffmpeg_lavc55_lavf55_lavu52_lavr01.c b/src/jogl/native/libav/ffmpeg_lavc55_lavf55_lavu52_lavr01.c
new file mode 100644
index 000000000..277100398
--- /dev/null
+++ b/src/jogl/native/libav/ffmpeg_lavc55_lavf55_lavu52_lavr01.c
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+#include "jogamp_opengl_util_av_impl_FFMPEGv10Natives.h"
+
+#define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv10Natives_ ## METHOD
+
+#include "ffmpeg_impl_template.c"
diff --git a/src/jogl/native/libav/ffmpeg_static.c b/src/jogl/native/libav/ffmpeg_static.c
index 171dda6a7..f079ee841 100644
--- a/src/jogl/native/libav/ffmpeg_static.c
+++ b/src/jogl/native/libav/ffmpeg_static.c
@@ -28,9 +28,6 @@
#ifdef _WIN32
#include <windows.h>
- // __declspec(dllimport) void __stdcall Sleep(unsigned long dwMilliseconds);
-
- #define usleep(t) Sleep((t) / 1000)
#endif
#include <gluegen_stdint.h>
@@ -46,34 +43,7 @@
typedef unsigned (APIENTRYP AV_GET_VERSION)(void);
-JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGStaticNatives_getAvUtilVersion0
- (JNIEnv *env, jclass clazz, jlong func) {
- if( 0 != func ) {
- return (jint) ((AV_GET_VERSION)func)();
- } else {
- return 0;
- }
-}
-
-JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGStaticNatives_getAvFormatVersion0
- (JNIEnv *env, jclass clazz, jlong func) {
- if( 0 != func ) {
- return (jint) ((AV_GET_VERSION)func)();
- } else {
- return 0;
- }
-}
-
-JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGStaticNatives_getAvCodecVersion0
- (JNIEnv *env, jclass clazz, jlong func) {
- if( 0 != func ) {
- return (jint) ((AV_GET_VERSION)func)();
- } else {
- return 0;
- }
-}
-
-JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGStaticNatives_getAvResampleVersion0
+JNIEXPORT jint JNICALL Java_jogamp_opengl_util_av_impl_FFMPEGStaticNatives_getAvVersion0
(JNIEnv *env, jclass clazz, jlong func) {
if( 0 != func ) {
return (jint) ((AV_GET_VERSION)func)();
diff --git a/src/jogl/native/libav/ffmpeg_tool.h b/src/jogl/native/libav/ffmpeg_tool.h
index ea9625da6..e4b10f95f 100644
--- a/src/jogl/native/libav/ffmpeg_tool.h
+++ b/src/jogl/native/libav/ffmpeg_tool.h
@@ -45,13 +45,20 @@
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#if LIBAVCODEC_VERSION_MAJOR >= 54
-#include "libavresample/avresample.h"
+ #include "libavresample/avresample.h"
+ #include "libswresample/swresample.h"
#endif
#ifndef LIBAVRESAMPLE_VERSION_MAJOR
-#define LIBAVRESAMPLE_VERSION_MAJOR 0
+#define LIBAVRESAMPLE_VERSION_MAJOR -1
+// Opaque
typedef void* AVAudioResampleContext;
#endif
+#ifndef LIBSWRESAMPLE_VERSION_MAJOR
+#define LIBSWRESAMPLE_VERSION_MAJOR -1
+// Opaque
+typedef struct SwrContext SwrContext;
+#endif
#include <stdarg.h>
#include <stdio.h>
@@ -88,24 +95,27 @@ typedef void (APIENTRYP PFNGLFINISH) (void);
/** Constant PTS marking the end of the stream, i.e. Integer.MIN_VALUE - 1 == 0x7FFFFFFF == {@value}. Sync w/ TimeFrameI.END_OF_STREAM_PTS */
#define END_OF_STREAM_PTS 0x7FFFFFFF
-/** Until 55.0.0, but stopped working w/ 54 already :( */
-#define AV_HAS_API_REQUEST_CHANNELS(pAV) (AV_VERSION_MAJOR(pAV->avcodecVersion) < 54)
-
-/** Since 55.0.0 */
-#define AV_HAS_API_REFCOUNTED_FRAMES(pAV) (AV_VERSION_MAJOR(pAV->avcodecVersion) >= 55)
-
/** Since 54.0.0.1 */
-#define AV_HAS_API_AVRESAMPLE(pAV) (AV_VERSION_MAJOR(pAV->avresampleVersion) >= 1)
+#define AV_HAS_API_AVRESAMPLE(pAV) ( pAV->avresampleVersion != 0 )
+
+/** Since 55.0.0.1 */
+#define AV_HAS_API_SWRESAMPLE(pAV) ( pAV->swresampleVersion != 0 )
#define MAX_INT(a,b) ( (a >= b) ? a : b )
#define MIN_INT(a,b) ( (a <= b) ? a : b )
static inline float my_av_q2f(AVRational a){
- return a.num / (float) a.den;
+ return (float)a.num / (float)a.den;
+}
+static inline float my_av_q2f_r(AVRational a){
+ return (float)a.den / (float)a.num;
}
static inline int32_t my_av_q2i32(int64_t snum, AVRational a){
return (int32_t) ( ( snum * (int64_t) a.num ) / (int64_t)a.den );
}
+static inline int my_align(int v, int a){
+ return ( v + a - 1 ) & ~( a - 1 );
+}
typedef struct {
void *origPtr;
@@ -129,6 +139,7 @@ typedef struct {
uint32_t avformatVersion;
uint32_t avutilVersion;
uint32_t avresampleVersion;
+ uint32_t swresampleVersion;
int32_t useRefCountedFrames;
@@ -149,8 +160,7 @@ typedef struct {
enum PixelFormat vPixFmt; // native decoder fmt
int32_t vPTS; // msec - overall last video PTS
PTSStats vPTSStats;
- int32_t vLinesize[3]; // decoded video linesize in bytes for each plane
- int32_t vTexWidth[3]; // decoded video tex width in bytes for each plane
+ int32_t vTexWidth[AV_NUM_DATA_POINTERS]; // decoded video tex width in bytes for each plane
int32_t vWidth;
int32_t vHeight;
@@ -167,7 +177,8 @@ typedef struct {
int32_t aSampleRate;
int32_t aChannels;
int32_t aSinkSupport; // supported by AudioSink
- AVAudioResampleContext *aResampleCtx;
+ AVAudioResampleContext* avResampleCtx;
+ struct SwrContext* swResampleCtx;
uint8_t* aResampleBuffer;
enum AVSampleFormat aSampleFmtOut; // out fmt
int32_t aChannelsOut;