├── NativeOSXCanvas ├── .gitignore ├── QTKitCanvas.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcuserdata │ │ │ ├── jesse.xcuserdatad │ │ │ │ ├── UserInterfaceState.xcuserstate │ │ │ │ └── WorkspaceSettings.xcsettings │ │ │ └── datavyu.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ ├── datavyu.xcuserdatad │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ │ └── jesse.xcuserdatad │ │ ├── xcschemes │ │ ├── xcschememanagement.plist │ │ ├── JAWTExample.xcscheme │ │ ├── Compile Java.xcscheme │ │ ├── Compile Native.xcscheme │ │ └── Assemble Application.xcscheme │ │ └── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist ├── src │ ├── java │ │ └── com │ │ │ └── apple │ │ │ └── dts │ │ │ └── samplecode │ │ │ └── jawtexample │ │ │ ├── LayerBackedCanvas.java │ │ │ ├── NativeDrawnCanvas.java │ │ │ └── JAWTExample.java │ └── native │ │ └── DrawingCanvas.m └── make │ ├── find-classrefs.sh │ └── build.xml ├── src ├── main │ ├── cpp │ │ ├── MediaPLayerTest.xcodeproj │ │ │ └── project.xcworkspace │ │ │ │ └── contents.xcworkspacedata │ │ ├── FfmpegJavaMediaPlayer.xcodeproj │ │ │ ├── project.xcworkspace │ │ │ │ └── contents.xcworkspacedata │ │ │ └── xcuserdata │ │ │ │ ├── datavyu.xcuserdatad │ │ │ │ └── xcschemes │ │ │ │ │ └── xcschememanagement.plist │ │ │ │ └── RedaNezzar.xcuserdatad │ │ │ │ └── xcschemes │ │ │ │ ├── xcschememanagement.plist │ │ │ │ └── FfmpegJavaMediaPlayer.xcscheme │ │ ├── FfmpegErrorUtils.h │ │ ├── FfmpegJavaAVPipline.h │ │ ├── packages.config │ │ ├── MediaPlayer.xcodeproj │ │ │ ├── project.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ ├── xcuserdata │ │ │ │ │ └── datavyu.xcuserdatad │ │ │ │ │ │ └── UserInterfaceState.xcuserstate │ │ │ │ └── xcshareddata │ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ └── xcuserdata │ │ │ │ ├── RedaNezzar.xcuserdatad │ │ │ │ └── xcschemes │ │ │ │ │ ├── xcschememanagement.plist │ │ │ │ │ └── MediaPlayer.xcscheme │ │ │ │ └── datavyu.xcuserdatad │ │ │ │ └── xcschemes │ │ │ │ └── xcschememanagement.plist │ │ ├── PipelineData.cpp │ │ ├── MediaPlayer.xcworkspace │ │ │ ├── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ └── contents.xcworkspacedata │ │ ├── PlayerState.h │ │ ├── org_datavyu_plugins_ffmpeg_NativeMediaPlayer_MediaErrorEvent.h │ │ ├── TestDecoder.cpp │ │ ├── FfmpegPipelineFactory.h │ │ ├── FfmpegPipelineFactory.cpp │ │ ├── Logger.cpp │ │ ├── FfmpegJniUtils.h │ │ ├── Info.plist │ │ ├── AudioVideoFormats.cpp │ │ ├── AudioVideoFormats.h │ │ ├── org_datavyu_plugins_ffmpeg_NativeMediaPlayer_EventQueueThread.h │ │ ├── player.cpp │ │ ├── Clock.cpp │ │ ├── FFplay.vcxproj.filters │ │ ├── TestClock.cpp │ │ ├── Clock.h │ │ ├── FfmpegJavaAvPlayback.h │ │ ├── Decoder.h │ │ ├── FfmpegSdlMediaPlayer.vcxproj.filters │ │ ├── Media.h │ │ ├── org_datavyu_plugins_ffmpeg_NativeMediaPlayer.h │ │ ├── Singleton.h │ │ ├── PipelineData.h │ │ ├── FfmpegJavaAvPlaybackPipline.h │ │ ├── FfmpegSdlAvPlaybackPipeline.h │ │ ├── FfmpegJavaMediaPlayer.vcxproj.filters │ │ ├── PacketQueue.h │ │ ├── PipelineOptions.h │ │ ├── FfmpegAvPlayback.cpp │ │ ├── JniUtils.h │ │ ├── Media.cpp │ │ ├── TestPacketQueue.cpp │ │ ├── VideoState.vcxitems │ │ ├── JavaPlayerEventDispatcher.h │ │ ├── FrameQueue.cpp │ │ ├── JniUtils.cpp │ │ ├── PacketQueue.cpp │ │ ├── FrameQueue.h │ │ ├── Pipeline.h │ │ ├── MediaPlayer.sln │ │ ├── Decoder.cpp │ │ ├── FfmpegErrorUtils.cpp │ │ ├── FfmpegSdlMediaPlayer.xcodeproj │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── MediaPlayerWorkspace.xcscheme │ │ └── MediaPlayerErrors.h │ ├── java │ │ └── org │ │ │ └── datavyu │ │ │ ├── plugins │ │ │ ├── PlayerEvent.java │ │ │ ├── MediaErrorListener.java │ │ │ ├── SdlKeyEventListener.java │ │ │ ├── PlayerStateListener.java │ │ │ ├── MediaException.java │ │ │ ├── MediaPlayerData.java │ │ │ ├── MediaPlayerWindow.java │ │ │ ├── nativeosx │ │ │ │ ├── NativeOSXPlayer.java │ │ │ │ └── AVFoundationMediaPlayer.java │ │ │ ├── PlayerStateEvent.java │ │ │ ├── ffmpeg │ │ │ │ ├── FfmpegMediaPlayer.java │ │ │ │ └── AudioPlayerThread.java │ │ │ ├── PlaybackRateController.java │ │ │ └── DatavyuMediaPlayer.java │ │ │ └── util │ │ │ ├── Utils.java │ │ │ └── MediaErrorToHeaderFile.java │ └── resources │ │ └── log4j2.xml └── test │ └── java │ ├── winTestngSuite.xml │ ├── macTestngSuite.xml │ └── org │ └── datavyu │ └── plugins │ └── ffmpeg │ ├── MediaInformation.java │ ├── FfmpegJavaMediaPlayerTest.java │ └── FfmpegSdlMediaPlayerTest.java ├── demo ├── SimpleJavaFXMediaPlayer.java ├── SimpleAVFoundationMediaPlayer.java ├── SimpleSdlMediaPlayer.java └── JavaFXMediaPlayer.java ├── .travis.yml ├── .appveyor.yml ├── .gitignore └── .gitattributes /NativeOSXCanvas/.gitignore: -------------------------------------------------------------------------------- 1 | .build/ 2 | 3 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPLayerTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegJavaMediaPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegErrorUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef _FFMPEG_ERROR_UTILS_H_ 2 | #define _FFMPEG_ERROR_UTILS_H_ 3 | 4 | int FfmpegToJavaErrNo(int ffmpegErrNo); 5 | 6 | #endif // _FFMPEG_ERROR_UTILS_H_ 7 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegJavaAVPipline.h: -------------------------------------------------------------------------------- 1 | #ifndef FFMPEGJAVAAVPIPELINE_H_ 2 | #define FFMPEGJAVAAVPIPELINE_H_ 3 | 4 | class FfmpegJavaAVPipline {}; 5 | 6 | #endif // !FFMPEGAVJAVAPIPELINE_H_ 7 | -------------------------------------------------------------------------------- /src/main/cpp/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/cpp/PipelineData.cpp: -------------------------------------------------------------------------------- 1 | #include "PipelineData.h" 2 | 3 | CPipelineData::CPipelineData(CPipelineOptions *pOptions) 4 | : CPipeline(pOptions) {} 5 | 6 | CPipelineData::~CPipelineData() {} 7 | 8 | void CPipelineData::Dispose() {} 9 | -------------------------------------------------------------------------------- /demo/SimpleJavaFXMediaPlayer.java: -------------------------------------------------------------------------------- 1 | import javafx.application.Application; 2 | 3 | public class SimpleJavaFXMediaPlayer { 4 | public static void main(String[] args) { 5 | Application.launch(JavaFXMediaPlayer.class, args); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPlayer.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/PlayerEvent.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins; 2 | 3 | /** 4 | * Generic player event 5 | * 6 | *

This is the super-class to other player event classes 7 | */ 8 | public class PlayerEvent { 9 | public PlayerEvent() {} 10 | } 11 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPlayer.xcodeproj/project.xcworkspace/xcuserdata/datavyu.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/databrary/datavyu-ffmpegplugin/HEAD/src/main/cpp/MediaPlayer.xcodeproj/project.xcworkspace/xcuserdata/datavyu.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/project.xcworkspace/xcuserdata/jesse.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/databrary/datavyu-ffmpegplugin/HEAD/NativeOSXCanvas/QTKitCanvas.xcodeproj/project.xcworkspace/xcuserdata/jesse.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/project.xcworkspace/xcuserdata/datavyu.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/databrary/datavyu-ffmpegplugin/HEAD/NativeOSXCanvas/QTKitCanvas.xcodeproj/project.xcworkspace/xcuserdata/datavyu.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /src/test/java/winTestngSuite.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/cpp/PlayerState.h: -------------------------------------------------------------------------------- 1 | #ifndef PLAYERSTATE_H_ 2 | #define PLAYERSTATE_H_ 3 | 4 | namespace PlayerState { 5 | enum State { 6 | Unknown = 0, 7 | Ready = 1, 8 | Playing = 2, 9 | Paused = 3, 10 | Stopped = 4, 11 | Stalled = 5, 12 | Finished = 6, 13 | Error = 7 14 | }; 15 | } 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPlayer.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/test/java/macTestngSuite.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegJavaMediaPlayer.xcodeproj/xcuserdata/datavyu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | FfmpegJavaMediaPlayer.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/cpp/org_datavyu_plugins_ffmpeg_NativeMediaPlayer_MediaErrorEvent.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class org_datavyu_plugins_ffmpeg_NativeMediaPlayer_MediaErrorEvent */ 4 | 5 | #ifndef _Included_org_datavyu_plugins_ffmpeg_NativeMediaPlayer_MediaErrorEvent 6 | #define _Included_org_datavyu_plugins_ffmpeg_NativeMediaPlayer_MediaErrorEvent 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | #endif 14 | -------------------------------------------------------------------------------- /src/main/cpp/TestDecoder.cpp: -------------------------------------------------------------------------------- 1 | // Note, the tests here are limited to memory allo/free 2 | // TODO(fraudies): Add more tests with e.g. a single video frame/file to decode. 3 | 4 | #include "gtest/gtest.h" 5 | 6 | #include "Decoder.h" 7 | 8 | #include 9 | 10 | TEST(DecoderTest, CreateDeleteTest) { 11 | std::condition_variable empty_queue_cond; 12 | PacketQueue packetQueue; 13 | AVCodecContext *pAvctx = avcodec_alloc_context3(NULL); 14 | Decoder decoder(pAvctx, &packetQueue, &empty_queue_cond); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPlayer.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 15 | 16 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegPipelineFactory.h: -------------------------------------------------------------------------------- 1 | #ifndef FFMPEGPIPELINEFACTORY_H_ 2 | #define FFMPEGPIPELINEFACTORY_H_ 3 | 4 | #include "PipelineFactory.h" 5 | #include "PipelineOptions.h" 6 | #include "FfmpegSdlAvPlaybackPipeline.h" 7 | #include "FfmpegJavaAvPlaybackPipline.h" 8 | #include "FfmpegMediaErrors.h" 9 | 10 | class FfmpegPipelineFactory : public PipelineFactory { 11 | public: 12 | FfmpegPipelineFactory(); 13 | virtual ~FfmpegPipelineFactory(); 14 | 15 | uint32_t CreatePlayerPipeline(CPipelineOptions *pOptions, CPipeline** ppPipeline); 16 | 17 | private: 18 | }; 19 | #endif // FFMPEGPIPELINEFACTORY_H_ 20 | 21 | 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: osx 2 | 3 | osx_image: xcode9.3 4 | 5 | git: 6 | depth: 1 7 | 8 | branches: 9 | only: 10 | - dev 11 | - master 12 | 13 | language: java 14 | 15 | cache: 16 | directories: 17 | - $HOME/.m2 18 | - $HOME/resources 19 | 20 | install: 21 | - curl -L https://github.com/databrary/FFplay64/raw/master/dependencies.zip -o $TRAVIS_BUILD_DIR/src/main/cpp/dependencies.zip 22 | - unzip -qq $TRAVIS_BUILD_DIR/src/main/cpp/dependencies.zip -d $TRAVIS_BUILD_DIR/src/main/cpp/ 23 | - java -version 24 | - mvn -version 25 | 26 | script: 27 | - mvn -T 4 -Prelease,mac -Dmaven.test.skip=true clean package -------------------------------------------------------------------------------- /src/main/cpp/FfmpegPipelineFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "FfmpegPipelineFactory.h" 2 | 3 | FfmpegPipelineFactory::FfmpegPipelineFactory() 4 | {} 5 | 6 | FfmpegPipelineFactory::~FfmpegPipelineFactory() 7 | {} 8 | 9 | uint32_t FfmpegPipelineFactory::CreatePlayerPipeline(CPipelineOptions *pOptions, CPipeline **ppPipeline) { 10 | 11 | *ppPipeline = NULL; 12 | if (pOptions->GetStreamData()) 13 | *ppPipeline = new (nothrow) FfmpegJavaAvPlaybackPipline(pOptions); 14 | else 15 | *ppPipeline = new (nothrow) FfmpegSdlAvPlaybackPipeline(pOptions); 16 | 17 | if (NULL == ppPipeline) 18 | return ERROR_PIPELINE_NULL; 19 | 20 | return ERROR_NONE; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPlayer.xcodeproj/xcuserdata/RedaNezzar.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MediaPlayer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | E95D243021966BBF007A6758 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPlayer.xcodeproj/xcuserdata/datavyu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MediaPlayer.xcscheme 8 | 9 | orderHint 10 | 2 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | E95D243021966BBF007A6758 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegJavaMediaPlayer.xcodeproj/xcuserdata/RedaNezzar.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | FfmpegJavaMediaPlayer.xcscheme 8 | 9 | orderHint 10 | 3 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | E95564D421963D3800A2AD8D 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/MediaErrorListener.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins; 2 | 3 | /** 4 | * An interface used to receive notifications of errors, encountered 5 | * while processing media. 6 | */ 7 | public interface MediaErrorListener { 8 | /** 9 | * Reports the occurrence of a error in media processing. An error may 10 | * or may not cause a stop in processing. 11 | * 12 | * @param source the source of the warning, likely the object calling this method. 13 | * @param errorCode an error code from the internal playback processor 14 | * @param message a String containing the warning. 15 | */ 16 | void onError(Object source, int errorCode, String message); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/util/Utils.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.util; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | 6 | public class Utils { 7 | private static final Logger logger = LogManager.getFormatterLogger(Utils.class); 8 | public static final char SEPARATOR; 9 | public static final boolean isMac; 10 | public static final boolean isWindows; 11 | 12 | static { 13 | // Look for Platform 14 | String OS = System.getProperty("os.name").toLowerCase(); 15 | isMac = OS.contains("mac"); 16 | isWindows = OS.contains("win"); 17 | logger.info("Platform detected : " + (isMac ? "Mac OS" : "Windows")); 18 | 19 | SEPARATOR = isMac ? '.' : '-'; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/SdlKeyEventListener.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins; 2 | 3 | /** 4 | * An interface used to receive notifications of key events, encountered 5 | * while using the SDL media player. 6 | */ 7 | public interface SdlKeyEventListener { 8 | 9 | /** 10 | * Reports the occurrence of a key event in SDL Media player window. 11 | * The SDL key Code is mapped to a Java Key Code ID in the Native. 12 | * 13 | * @param source the source of the event, likely the object calling this method. 14 | * @param nativeMediaRef the native reference of the SDL media Player. 15 | * @param javaKeyCode a KeyEvent value. 16 | */ 17 | void onKeyEvent(Object source, long nativeMediaRef,int javaKeyCode); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/cpp/Logger.cpp: -------------------------------------------------------------------------------- 1 | #include "Logger.h" 2 | // compile cl Logger.cpp 3 | // Run Logger.exe 4 | 5 | int main(int argc, char** argv) { 6 | Logger* pLogger = new StreamLogger(&std::cerr); 7 | //Logger* pLogger = new FileLogger("logger.txt"); 8 | pLogger->setLevel(Logger::ALL); 9 | pLogger->info("This is the first logging message"); 10 | pLogger->warn("You better get smaller than %d.", 5); 11 | pLogger->debug("Hehe, a floating point %2.2f", 3.14); 12 | pLogger->error("This is an error with code %d.", 7); 13 | pLogger->warn("This is a warning with decimal %f.", 1.5); 14 | pLogger->debug("A debug message with another string %s.", "another one"); 15 | pLogger->info("Just so you know!"); 16 | delete pLogger; 17 | pLogger = nullptr; 18 | return 0; 19 | } -------------------------------------------------------------------------------- /src/main/cpp/FfmpegJniUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef _FFMPEG_JNI_UTILS_H_ 2 | #define _FFMPEG_JNI_UTILS_H_ 3 | 4 | #include "AudioVideoFormats.h" 5 | #include 6 | 7 | // This mapping is taken from java.awt.color.ColorSpace.java 8 | #define TYPE_RGB 5 9 | 10 | uint32_t SetJAudioFormat(JNIEnv *env, jobject j_audio_format, 11 | const AudioFormat &audio_format); 12 | 13 | uint32_t SetJPixelFormat(JNIEnv *env, jobject j_pixel_format, 14 | const PixelFormat &pixel_format); 15 | 16 | uint32_t GetAudioFormat(JNIEnv *env, jobject j_audio_format, 17 | AudioFormat *p_audio_format); 18 | 19 | uint32_t GetPixelFormat(JNIEnv *env, jobject j_pixel_format, 20 | PixelFormat *p_pixel_format); 21 | 22 | #endif //_FFMPEG_JNI_UTILS_H_ 23 | -------------------------------------------------------------------------------- /src/main/cpp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/xcuserdata/datavyu.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Assemble Application.xcscheme 8 | 9 | orderHint 10 | 3 11 | 12 | Compile Java.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | Compile Native.xcscheme 18 | 19 | orderHint 20 | 2 21 | 22 | QTKitCanvas.xcscheme 23 | 24 | orderHint 25 | 0 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/project.xcworkspace/xcuserdata/jesse.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | SnapshotAutomaticallyBeforeSignificantChanges 18 | 19 | SnapshotLocationStyle 20 | Default 21 | 22 | 23 | -------------------------------------------------------------------------------- /demo/SimpleAVFoundationMediaPlayer.java: -------------------------------------------------------------------------------- 1 | import org.datavyu.plugins.nativeosx.AVFoundationMediaPlayer; 2 | import org.datavyu.plugins.MediaPlayer; 3 | 4 | import javax.swing.*; 5 | import java.io.File; 6 | import java.net.URI; 7 | 8 | public class SimpleAVFoundationMediaPlayer { 9 | public static void main(String[] args) { 10 | // Define the media file 11 | URI mediaPath = new File("Nature_30fps_1080p.mp4").toURI(); 12 | 13 | // Create the media player using the constructor with File 14 | MediaPlayer mediaPlayer = new AVFoundationMediaPlayer(mediaPath, new JDialog()); 15 | 16 | mediaPlayer.addMediaErrorListener( 17 | (source, errorCode, message) -> 18 | System.err.println(source.getClass() + " - " + errorCode + ": " + message)); 19 | 20 | // Initialize the player 21 | mediaPlayer.init(); 22 | 23 | // Open a JFrame to control the media player through key commands 24 | new JMediaPlayerControlFrame(mediaPlayer); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/cpp/AudioVideoFormats.cpp: -------------------------------------------------------------------------------- 1 | #include "AudioVideoFormats.h" 2 | #include "AudioVideoFormats.h" 3 | 4 | extern "C" { 5 | #include // codecs 6 | } 7 | 8 | AudioFormat::AudioFormat() {} 9 | 10 | void AudioFormat::ToAudioParams(AudioParams *pAudioParams) const { 11 | pAudioParams->num_channels_ = num_channels_; 12 | pAudioParams->frame_size_ = frame_size_; 13 | pAudioParams->frequency_ = sample_rate_; 14 | pAudioParams->bytes_per_sec_ = frame_rate_; 15 | pAudioParams->channel_layout_ = av_get_default_channel_layout(num_channels_); 16 | // TODO(fraudies): Support more formats (currently not necessary because of 17 | // the javax SoundLine does not support more formats 18 | if (strcmp("PCM_UNSIGNED", encoding_name_.c_str()) == 0) { 19 | pAudioParams->sample_format_ = AV_SAMPLE_FMT_U8; 20 | } else if (strcmp("PCM_SIGNED", encoding_name_.c_str()) == 0) { 21 | pAudioParams->sample_format_ = AV_SAMPLE_FMT_S16; 22 | } 23 | } 24 | 25 | PixelFormat::PixelFormat() {} 26 | -------------------------------------------------------------------------------- /src/main/cpp/AudioVideoFormats.h: -------------------------------------------------------------------------------- 1 | #ifndef _AUDIO_VIDEO_FORMATS_H_ 2 | #define _AUDIO_VIDEO_FORMATS_H_ 3 | #include 4 | 5 | extern "C" { 6 | #include "libavutil/pixfmt.h" 7 | #include "libavutil/samplefmt.h" 8 | } 9 | 10 | // TODO(fraudies): Consolidate AudioParams and AudioFormat 11 | typedef struct AudioParams { 12 | int frequency_; 13 | int num_channels_; 14 | int64_t channel_layout_; 15 | enum AVSampleFormat sample_format_; 16 | int frame_size_; 17 | int bytes_per_sec_; 18 | } AudioParams; 19 | 20 | class AudioFormat { 21 | public: 22 | std::string encoding_name_; 23 | float sample_rate_; 24 | int sample_size_in_bits_; 25 | int num_channels_; 26 | int frame_size_; 27 | float frame_rate_; 28 | bool is_big_endian_; 29 | AudioFormat(); 30 | void ToAudioParams(AudioParams *pAudioParams) const; 31 | }; 32 | 33 | class PixelFormat { 34 | public: 35 | AVPixelFormat pixel_format_; 36 | int num_components_; 37 | PixelFormat(); 38 | }; 39 | 40 | #endif // _AUDIO_VIDEO_FORMATS_H_ 41 | -------------------------------------------------------------------------------- /src/main/cpp/org_datavyu_plugins_ffmpeg_NativeMediaPlayer_EventQueueThread.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class org_datavyu_plugins_ffmpeg_NativeMediaPlayer_EventQueueThread */ 4 | 5 | #ifndef _Included_org_datavyu_plugins_ffmpeg_NativeMediaPlayer_EventQueueThread 6 | #define _Included_org_datavyu_plugins_ffmpeg_NativeMediaPlayer_EventQueueThread 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_EventQueueThread_MIN_PRIORITY 11 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_EventQueueThread_MIN_PRIORITY 1L 12 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_EventQueueThread_NORM_PRIORITY 13 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_EventQueueThread_NORM_PRIORITY 5L 14 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_EventQueueThread_MAX_PRIORITY 15 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_EventQueueThread_MAX_PRIORITY 10L 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | #endif 20 | -------------------------------------------------------------------------------- /src/main/cpp/player.cpp: -------------------------------------------------------------------------------- 1 | #include "FfmpegSdlAvPlayback.h" 2 | 3 | int runFFmpegPlayer(const char *input_filename, AVInputFormat *file_iformat) { 4 | 5 | av_log_set_flags(AV_LOG_SKIP_REPEATED); 6 | av_log(NULL, AV_LOG_WARNING, "Init Network\n"); 7 | FfmpegSdlAvPlayback *p_player = new FfmpegSdlAvPlayback(); 8 | int err = p_player->OpenVideo(input_filename, file_iformat); 9 | if (err) { 10 | fprintf(stderr, "Error %d when opening input file %s", err, input_filename); 11 | return err; 12 | } 13 | FfmpegSdlAvPlayback::InitializeAndListenForEvents(p_player); 14 | 15 | return 0; 16 | } 17 | 18 | int main(int argc, char **argv) { 19 | static const char *input_filename = 20 | //"Nature_30fps_1080p.mp4"; 21 | "DatavyuSampleVideo.mp4"; 22 | //"counter.mp4"; 23 | //"http://www.html5videoplayer.net/videos/toystory.mp4"; 24 | AVInputFormat *file_iformat = nullptr; 25 | 26 | /****************************************************** 27 | * Uncomment this part to test the ffmpeg player 28 | ******************************************************/ 29 | runFFmpegPlayer(input_filename, file_iformat); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | 3 | image: Visual Studio 2017 4 | 5 | clone_depth: 1 6 | 7 | branches: 8 | only: 9 | - master 10 | - dev 11 | 12 | environment: 13 | JAVA_HOME: C:\Program Files\Java\jdk1.8.0 14 | 15 | install: 16 | - ps: | 17 | if (!(Test-path -Path "C:\FFplay64")) { 18 | Write-Output "Download FFmpeg Dependencies" 19 | Invoke-WebRequest "https://github.com/databrary/FFplay64/raw/master/FFplay64.zip" -OutFile "C:\FFplay64.zip" 20 | Write-Output "Extract FFmpeg dependencies" 21 | Expand-Archive -LiteralPath C:\FFplay64.zip -DestinationPath C:\ 22 | } 23 | $msbuild = (Get-Command msbuild).path 24 | Write-Output $msbuild 25 | 26 | - cmd: SET PATH=%JAVA_HOME%\bin;%PATH% 27 | - cmd: mvn --version 28 | - cmd: java -version 29 | 30 | cache: 31 | - C:\apache-maven-3.5.4\ 32 | - C:\Users\appveyor\.m2 33 | - C:\FFplay64\ 34 | - C:\resources\ 35 | 36 | before_build: 37 | - cd %APPVEYOR_BUILD_FOLDER%\src\main\cpp 38 | - nuget restore MediaPlayer.sln 39 | - cd %APPVEYOR_BUILD_FOLDER% 40 | 41 | build_script: 42 | - mvn -T 4 -Prelease,win64 clean compile 43 | 44 | #test_script: 45 | # - mvn -T 4 -Prelease,win64 test -------------------------------------------------------------------------------- /src/main/cpp/Clock.cpp: -------------------------------------------------------------------------------- 1 | #include "Clock.h" 2 | 3 | extern "C" { 4 | #include "libavutil/log.h" 5 | } 6 | 7 | Clock::Clock(const int *queue_serial) 8 | : time(0.0), serial(-1), p_serial_(queue_serial) { 9 | SetTime(NAN, -1); 10 | } 11 | 12 | Clock::~Clock() { 13 | if (p_serial_) { 14 | p_serial_ == nullptr; 15 | } 16 | } 17 | 18 | Clock::Clock() : time(0.0), serial(-1), p_serial_(&serial) { SetTime(NAN, -1); } 19 | 20 | double Clock::GetTime() const { 21 | if (SerialNoMatch()) { 22 | return NAN; 23 | } 24 | return time; 25 | } 26 | 27 | void Clock::SetTime(double newTime, int newSerial) { 28 | if (!isnan(newTime)) { 29 | time = newTime; 30 | } 31 | serial = newSerial; 32 | } 33 | 34 | void Clock::SyncMasterToSlave(Clock *master, Clock *slave, 35 | double noSyncThreshold) { 36 | double master_time = master->GetTime(); 37 | double slave_time = slave->GetTime(); 38 | if (!isnan(slave_time) && 39 | (isnan(master_time) || 40 | fabs(master_time - slave_time) > noSyncThreshold)) { 41 | av_log(NULL, AV_LOG_TRACE, "Sync %7.2f to %7.2f\n", slave_time, 42 | master_time); 43 | master->SetTime(slave_time, slave->serial); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/cpp/FFplay.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/cpp/TestClock.cpp: -------------------------------------------------------------------------------- 1 | #include "Clock.h" 2 | #include "gtest/gtest.h" 3 | 4 | #ifdef __APPLE__ 5 | #include 6 | #endif 7 | #include 8 | #include 9 | #include 10 | 11 | // TODO(fraudies): Add test for sync method 12 | 13 | TEST(ClockTest, CreateAndDeleteClockTest) { 14 | int serial = 0; 15 | Clock clock(&serial); 16 | ASSERT_EQ(clock.GetSerial(), -1.0); 17 | } 18 | 19 | TEST(ClockTest, SetGetTimeTest) { 20 | // Create a clock 21 | int serial = 0; 22 | Clock clock(&serial); 23 | 24 | // Set different serial should return NAN 25 | clock.SetTime(1.0, 2); 26 | ASSERT_TRUE(isnan(clock.GetTime())); 27 | 28 | // Set clock with same serial and get time 29 | double time = av_gettime_relative() / MICRO; 30 | clock.SetTime(time, serial); 31 | // ASSERT LESS THAN 32 | ASSERT_LT(fabs(clock.GetTime() - time), 33 | std::numeric_limits::epsilon()); 34 | 35 | // Wait for 100 msec 36 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 37 | double speed = 1.0; 38 | double newTime = av_gettime_relative() / MICRO; 39 | 40 | // ASSERT LESS THAN, the expired time does not matter, only the setTime 41 | // changes the clock's time 42 | ASSERT_LT(fabs(clock.GetTime() - time), 43 | std::numeric_limits::epsilon()); 44 | } 45 | -------------------------------------------------------------------------------- /NativeOSXCanvas/src/java/com/apple/dts/samplecode/jawtexample/LayerBackedCanvas.java: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | */ 5 | 6 | package com.apple.dts.samplecode.jawtexample; 7 | 8 | import java.awt.Canvas; 9 | 10 | public class LayerBackedCanvas extends Canvas { 11 | static { 12 | // Standard JNI: load the native library 13 | System.loadLibrary("JAWTExample"); 14 | } 15 | 16 | public void addNotify() { 17 | super.addNotify(); 18 | addNativeCoreAnimationLayer("file:///Users/jesse/Desktop/minecraft.mp4"); 19 | } 20 | 21 | // This method is implemented in native code. See NativeCanvas.m 22 | public native void addNativeCoreAnimationLayer(String path); 23 | 24 | public native void stop(); 25 | 26 | public native void play(); 27 | 28 | public native void setTime(long time); 29 | 30 | public native void setVolume(float time); 31 | 32 | public native void release(); 33 | 34 | public native double getMovieHeight(); 35 | 36 | public native double getMovieWidth(); 37 | 38 | public native long getCurrentTime(); 39 | 40 | public native long getDuration(); 41 | 42 | public native float getRate(); 43 | 44 | public native boolean isPlaying(); 45 | 46 | public native void setRate(float rate); 47 | 48 | public native float getFPS(); 49 | 50 | } -------------------------------------------------------------------------------- /NativeOSXCanvas/make/find-classrefs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Prints all class references made by all classes in a Jar file 4 | # Depends on the output formatting of javap 5 | 6 | # create a temporary working directory 7 | dir=`mktemp -d $TMPDIR/classrefs.XXXXXX` 8 | 9 | asm_dump="$dir/asm_dump" 10 | all_classes="$dir/all_classes" 11 | 12 | # for each class in a Jar file, dump the full assembly 13 | javap -c -classpath "$1" `/usr/bin/jar tf "$1" | grep "\.class" | sort | xargs | sed -e 's/\.class//g'` > $asm_dump 14 | 15 | # dump the initial list of all classes in the Jar file 16 | /usr/bin/jar tf $1 | grep "\.class" | sed -e 's/\.class//g' >> $all_classes 17 | 18 | # dump all static class references 19 | cat $asm_dump | grep //class | awk -F"//class " '{print $2}' | sort | uniq >> $all_classes 20 | 21 | # dump all references to classes made in methods 22 | cat $asm_dump | grep //Method | awk -F"//Method " '{print $2}' | sort | uniq | grep "\." | awk -F"." '{print $1}' | sort | uniq >> $all_classes 23 | 24 | # dump all references to classes by direct field access 25 | cat $asm_dump | grep //Field | awk -F"//Field " '{print $2}' | sort | uniq | grep "\:L" | awk -F"\:L" '{print $2}' | sort | uniq | awk -F"\;" '{print $1}' >> $all_classes 26 | 27 | # sort and reformat 28 | sort $all_classes | uniq | grep -v "\"" | sed -e 's/\//\./g' 29 | 30 | # cleanup 31 | rm -rf $dir 32 | -------------------------------------------------------------------------------- /demo/SimpleSdlMediaPlayer.java: -------------------------------------------------------------------------------- 1 | import org.apache.logging.log4j.LogManager; 2 | import org.apache.logging.log4j.Logger; 3 | import org.datavyu.plugins.MediaPlayerWindow; 4 | import org.datavyu.plugins.ffmpeg.FfmpegSdlMediaPlayer; 5 | 6 | import java.io.File; 7 | import java.net.URI; 8 | 9 | public class SimpleSdlMediaPlayer { 10 | private static Logger logger = LogManager.getLogger(SimpleSdlMediaPlayer.class); 11 | 12 | public static void main(String[] args) { 13 | // Define the media file 14 | URI mediaPath = new File("Nature_30fps_1080p.mp4").toURI(); 15 | 16 | // Create the media player using the constructor with File 17 | MediaPlayerWindow mediaPlayer = new FfmpegSdlMediaPlayer(mediaPath); 18 | 19 | // Handle Media Player errors 20 | mediaPlayer.addMediaErrorListener( 21 | (source, errorCode, message) -> logger.error(errorCode + ": " + message)); 22 | 23 | // Initialize the player 24 | mediaPlayer.init(); 25 | 26 | // Open a simple JFrame to control the media player through key commands 27 | // Be creative and create your own controller 28 | JMediaPlayerControlFrame controller = new JMediaPlayerControlFrame(mediaPlayer); 29 | 30 | // Handle Window Key events 31 | mediaPlayer.addSdlKeyEventListener( 32 | (source, nativeMediaRef, javaKeyCode) -> controller.handleKeyEvents(javaKeyCode)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.dll 2 | *.dylib 3 | *.jnilib 4 | *.lib 5 | *.obj 6 | *.exp 7 | *.log 8 | *.exe 9 | *.pdb 10 | *.txt 11 | bin/ 12 | *.iml 13 | .idea/* 14 | .vscode/* 15 | target/* 16 | out/* 17 | src/main/cpp/*.txt 18 | .classpath 19 | .factorypath 20 | .project 21 | .settings 22 | 23 | # User-specific files 24 | *.suo 25 | *.user 26 | *.userosscache 27 | *.sln.docstates 28 | 29 | # User-specific files (MonoDevelop/Xamarin Studio) 30 | *.userprefs 31 | 32 | # Build results 33 | [Dd]ebug/ 34 | [Dd]ebugPublic/ 35 | [Rr]elease/ 36 | [Rr]eleases/ 37 | x64/ 38 | x86/ 39 | bld/ 40 | [Bb]in/ 41 | [Oo]bj/ 42 | [Ll]og/ 43 | 44 | # Debug files/resources 45 | *.aps 46 | *.TMP 47 | *.rc 48 | resource.h 49 | 50 | # Visual Studio 2015/2017 cache/options directory 51 | .vs/ 52 | 53 | # Uncomment if you have tasks that create the project's static files in wwwroot 54 | #wwwroot/ 55 | 56 | # Video Files 57 | *.mp4 58 | *.avi 59 | 60 | # Google Test Package 61 | packages/ 62 | 63 | .DS_Store 64 | 65 | **/dependencies/* 66 | SDL2.framework/* 67 | 68 | # Xcode files 69 | ## Build generated 70 | build/ 71 | DerivedData/ 72 | 73 | ## Various settings 74 | *.pbxuser 75 | !default.pbxuser 76 | *.mode1v3 77 | !default.mode1v3 78 | *.mode2v3 79 | !default.mode2v3 80 | *.perspectivev3 81 | !default.perspectivev3 82 | **/xcuserdata/* 83 | 84 | ## Other 85 | *.moved-aside 86 | *.xccheckout 87 | *.xcscmblueprint 88 | -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/xcuserdata/jesse.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Assemble Application.xcscheme 8 | 9 | orderHint 10 | 3 11 | 12 | Compile Java.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | Compile Native.xcscheme 18 | 19 | orderHint 20 | 2 21 | 22 | JAWTExample.xcscheme 23 | 24 | orderHint 25 | 0 26 | 27 | 28 | SuppressBuildableAutocreation 29 | 30 | 89D0F0480F393A6F007831A7 31 | 32 | primary 33 | 34 | 35 | 89D0F04F0F393AD9007831A7 36 | 37 | primary 38 | 39 | 40 | 89D0F1C90F3B704E007831A7 41 | 42 | primary 43 | 44 | 45 | 8D1107260486CEB800E47090 46 | 47 | primary 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/PlayerStateListener.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins; 2 | 3 | /** */ 4 | public interface PlayerStateListener { 5 | /** 6 | * The ready state indicates the media is loaded. For 7 | * best results, developers should wait on 8 | * OnReady() before playing a media. 9 | * 10 | * @param evt 11 | */ 12 | void onReady(PlayerStateEvent evt); 13 | 14 | /** 15 | * The play state indicates the media is beginning to play. 16 | * 17 | * @param evt 18 | */ 19 | void onPlaying(PlayerStateEvent evt); 20 | 21 | /** 22 | * The pause state indicates playback has paused. 23 | * 24 | * @param evt 25 | */ 26 | void onPause(PlayerStateEvent evt); 27 | 28 | /** 29 | * The stop state indicates playback has paused and presentation 30 | * time has been reset back to 0. If the player is asked to 31 | * play() again, playback begins from the beginning. 32 | * 33 | * @param evt 34 | */ 35 | void onStop(PlayerStateEvent evt); 36 | 37 | void onStall(PlayerStateEvent evt); 38 | 39 | /** 40 | * The finish state indicates playback has completed playback 41 | * to the end. 42 | * 43 | * @param evt 44 | */ 45 | void onFinish(PlayerStateEvent evt); 46 | 47 | /** 48 | * The error notification provides information on any error 49 | * during playback. 50 | * 51 | * @param evt 52 | */ 53 | void onHalt(PlayerStateEvent evt); 54 | } 55 | -------------------------------------------------------------------------------- /src/main/cpp/Clock.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern "C" { 4 | #include // timer 5 | } 6 | 7 | #ifndef CLOCK_H_ 8 | #define CLOCK_H_ 9 | 10 | #define MICRO 1000000.0 11 | 12 | // Clock to keep decoding in sync 13 | // 14 | // This is a port of the Clock ffplay.c from ffmpeg into c++ 15 | // 16 | // Big warning: This clock is NOT thread safe. The original ffplay.c code used 17 | // locks around the clock for the set/get in some places. We may decide to move 18 | // these locks into the set/get method if deemed necessary (it would be better 19 | // code design at the cost of performance). 20 | // 21 | class Clock { 22 | public: 23 | Clock(const int *queue_serial); 24 | 25 | Clock(); 26 | 27 | virtual ~Clock(); 28 | 29 | double GetTime() const; // for stream time, depends on rate 30 | 31 | inline double GetSerial() const { return serial; } 32 | 33 | void SetTime(double newTime, int newSerial); 34 | 35 | static void SyncMasterToSlave(Clock *master, Clock *slave, 36 | double noSyncThreshold); 37 | 38 | private: 39 | double time; // clock time 40 | int serial; // clock is based on a packet with this serial 41 | const int *p_serial_; // pointer to the current packet queue serial, 42 | // used for obsolete clock detection 43 | 44 | inline bool SerialNoMatch() const { return *p_serial_ != serial; } 45 | }; 46 | 47 | #endif CLOCK_H_ 48 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/MediaException.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins; 2 | 3 | public class MediaException extends RuntimeException { 4 | 5 | private MediaError error = null; 6 | 7 | /** 8 | * Constructor which merely passes its parameter to the corresponding 9 | * superclass constructor 10 | * {@link RuntimeException#RuntimeException(java.lang.String)}. 11 | * 12 | * @param message The detail message. 13 | */ 14 | public MediaException(String message) { 15 | super(message); 16 | } 17 | 18 | /** 19 | * Constructor which merely passes its parameters to the corresponding 20 | * superclass constructor 21 | * {@link RuntimeException#RuntimeException(java.lang.String, java.lang.Throwable)}. 22 | * 23 | * @param message The detail message. 24 | * @param cause The cause. 25 | */ 26 | public MediaException(String message, Throwable cause) { 27 | super(message, cause); 28 | } 29 | 30 | /** 31 | * Constructor which merely passes its parameters to the 32 | * corresponding superclass constructor 33 | * {@link RuntimeException#RuntimeException(java.lang.String, java.lang.Throwable)}. 34 | * 35 | * @param message The detail message. 36 | * @param cause The cause. 37 | * @param error The media error. 38 | */ 39 | public MediaException(String message, Throwable cause, MediaError error) { 40 | super(message, cause); 41 | this.error = error; 42 | } 43 | 44 | public MediaError getMediaError() { 45 | return error; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/util/MediaErrorToHeaderFile.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.util; 2 | 3 | import org.datavyu.plugins.MediaError; 4 | 5 | import java.io.File; 6 | import java.io.FileNotFoundException; 7 | import java.io.PrintWriter; 8 | 9 | /** 10 | * Generates the header file for the media error. 11 | * 12 | *

This file is only used during the compile process. 13 | * 14 | *

TODO(fraudies): Run this during the build with maven and add arguments for output path/file 15 | */ 16 | public class MediaErrorToHeaderFile { 17 | public static void main(String[] args) { 18 | String fileName = "FfmpegMediaErrors.h"; 19 | try { 20 | PrintWriter writer = new PrintWriter(new File(fileName)); 21 | writer.println("//DO NOT EDIT -- MACHINE GENERATED"); 22 | writer.println("#ifndef _FFMPEG_MEDIA_ERRORS_H_"); 23 | writer.println("#define _FFMPEG_MEDIA_ERRORS_H_"); 24 | writer.println(); 25 | for (MediaError mediaError : MediaError.values()) { 26 | writer.println("#define \t" + mediaError.name() + " \t" + mediaError.code()); 27 | } 28 | writer.println(); 29 | writer.println("#endif // _FFMPEG_MEDIA_ERRORS_H_"); 30 | writer.close(); 31 | } catch (FileNotFoundException noFile) { 32 | System.err.println(noFile.getMessage()); 33 | } 34 | System.out.println( 35 | "Generated header file for '" 36 | + MediaError.class.getName() 37 | + "' and wrote it to '" 38 | + fileName 39 | + "'"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/MediaPlayerData.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins; 2 | 3 | import javax.sound.sampled.AudioFormat; 4 | import java.awt.color.ColorSpace; 5 | 6 | /** 7 | * This provides the interface to the media player data when we 8 | * decide to play back data through java. 9 | * 10 | *

Otherwise, we play back data natively. 11 | */ 12 | public interface MediaPlayerData extends MediaPlayer { 13 | 14 | /** 15 | * Checks if the media has audio data 16 | * 17 | * @return True if data exists; otherwise false 18 | */ 19 | boolean hasAudioData(); 20 | 21 | /** 22 | * Checks if the media has image data 23 | * 24 | * @return True if data exists; otherwise false 25 | */ 26 | boolean hasImageData(); 27 | 28 | /** 29 | * Returns the output audio format that the audio data is 30 | * formatted in 31 | * 32 | * @return The audio format 33 | */ 34 | AudioFormat getAudioFormat(); 35 | 36 | /** 37 | * Returns the color space that the image data is formatted in 38 | * 39 | * @return The color space 40 | */ 41 | ColorSpace getColorSpace(); 42 | 43 | /** 44 | * Update the byte buffer with the most recent audio data to play 45 | * 46 | * @param data The data that is updated on the native side 47 | */ 48 | void updateAudioData(byte[] data); 49 | 50 | /** 51 | * Update the byte buffer with the most recent image data to play 52 | * 53 | * @param data The data that is updated on the native side 54 | */ 55 | void updateImageData(byte[] data); 56 | } 57 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegJavaAvPlayback.h: -------------------------------------------------------------------------------- 1 | #ifndef FFMPEGJAVAAVPLAYBACK_H_ 2 | #define FFMPEGJAVAAVPLAYBACK_H_ 3 | 4 | #include "FfmpegAVPlayback.h" 5 | #include "VideoState.h" 6 | 7 | class FfmpegJavaAvPlayback : public FfmpegAvPlayback { 8 | private: 9 | const AudioFormat *kPtrAudioFormat; 10 | const PixelFormat *kPtrPixelFormat; 11 | const int kAudioBufferSizeInBy; 12 | 13 | struct SwsContext *p_img_convert_ctx_; 14 | double remaining_time_to_display_; 15 | 16 | public: 17 | FfmpegJavaAvPlayback(const AudioFormat *kPtrAudioFormat, 18 | const PixelFormat *kPtrPixelFormat, 19 | const int kAudioBufferSizeInBy); 20 | virtual ~FfmpegJavaAvPlayback(); 21 | 22 | int Init(const char *p_filename, AVInputFormat *p_input_format); 23 | 24 | int AudioOpen(int64_t wanted_channel_layout, int wanted_nb_channels, 25 | int wanted_sample_rate, struct AudioParams *audio_hw_params); 26 | 27 | VideoState *GetVideoState(); 28 | 29 | void Destroy(); 30 | 31 | int StartStream(); 32 | 33 | void SetBalance(float balance); 34 | float GetBalance(); 35 | 36 | void SetAudioSyncDelay(long millis); 37 | long getAudioSyncDelay(); 38 | 39 | int GetImageWidth() const; 40 | int GetImageHeight() const; 41 | 42 | bool HasImageData() const; 43 | bool HasAudioData() const; 44 | 45 | bool DoDisplay(double *p_remaining_time); 46 | 47 | void UpdateImageBuffer(uint8_t *p_image_data, const long len); 48 | void UpdateAudioBuffer(uint8_t *p_audio_data, const long len); 49 | 50 | void GetAudioFormat(AudioFormat *p_audio_format); 51 | void GetPixelFormat(PixelFormat *p_pixel_format); 52 | }; 53 | 54 | #endif // end of FFMPEGJAVAAVPLAYBACK_H_ 55 | -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/xcuserdata/jesse.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/MediaPlayerWindow.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins; 2 | 3 | import java.util.ListIterator; 4 | 5 | /** 6 | * This provides the interface to control the media player Window when we 7 | * decide to play back streams through native display. 8 | */ 9 | public interface MediaPlayerWindow extends MediaPlayer { 10 | 11 | /** 12 | * Adds a listener for SDL player key events. 13 | * 14 | * @param listener listener to be added 15 | * @throws IllegalArgumentException if listener is null. 16 | */ 17 | void addSdlKeyEventListener(SdlKeyEventListener listener); 18 | 19 | /** 20 | * Removes a listener for SDL player key events. 21 | * 22 | * @param listener listener to be removed 23 | * @throws IllegalArgumentException if listener is null. 24 | */ 25 | void removeSdlKeyEventListener(SdlKeyEventListener listener); 26 | 27 | /** 28 | * Expose SDL player window, this method is available only for the SDL player, will throw an 29 | * exception if called from a Java player. 30 | */ 31 | void showWindow(); 32 | 33 | /** 34 | * Hide SDL player window, this method is available only for the SDL player, will throw an 35 | * exception if called from a Java player. 36 | */ 37 | void hideWindow(); 38 | 39 | boolean isVisible(); 40 | 41 | /** 42 | * Return Window Height 43 | * 44 | * @return window height 45 | */ 46 | int getWindowHeight(); 47 | 48 | /** 49 | * Return Window Width 50 | * 51 | * @return window width 52 | */ 53 | int getWindowWidth(); 54 | 55 | /** 56 | * Set Window new width and height 57 | * 58 | * @param width 59 | * @param height 60 | */ 61 | void setWindowSize(int width, int height); 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/nativeosx/NativeOSXPlayer.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins.nativeosx; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | import org.datavyu.util.LibraryLoader; 6 | 7 | import java.awt.*; 8 | import java.net.URI; 9 | 10 | public class NativeOSXPlayer extends Canvas { 11 | 12 | private static Logger logger = LogManager.getLogger(NativeOSXPlayer.class); 13 | private final URI mediaPath; 14 | 15 | static { 16 | try { 17 | LibraryLoader.extractAndLoad("NativeOSXCanvas"); 18 | } catch (Exception e) { 19 | logger.error("Unable to load the native library: ", e); 20 | } 21 | } 22 | 23 | public NativeOSXPlayer(URI mediaPath) { 24 | this.mediaPath = mediaPath; 25 | } 26 | 27 | public void addNotify() { 28 | super.addNotify(); 29 | addNativeOSXCoreAnimationLayer("file://" + mediaPath.getPath()); 30 | } 31 | 32 | // This method is implemented in native code. See NativeOSXCanvas.m 33 | native void addNativeOSXCoreAnimationLayer(String path); 34 | 35 | native void stop(int id); 36 | 37 | native void play(int id); 38 | 39 | native void setTime(long time, int id); 40 | 41 | native void setTimePrecise(long time, int id); 42 | 43 | native void setTimeModerate(long time, int id); 44 | 45 | native void setVolume(float time, int id); 46 | 47 | native void release(int id); 48 | 49 | native double getMovieHeight(int id); 50 | 51 | native double getMovieWidth(int id); 52 | 53 | native long getCurrentTime(int id); 54 | 55 | native long getDuration(int id); 56 | 57 | native float getRate(int id); 58 | 59 | native void setRate(float rate, int id); 60 | 61 | native boolean isPlaying(int id); 62 | 63 | native float getFPS(int id); 64 | } 65 | -------------------------------------------------------------------------------- /src/main/cpp/Decoder.h: -------------------------------------------------------------------------------- 1 | #include "FrameQueue.h" 2 | #include "PacketQueue.h" 3 | #include 4 | #include 5 | 6 | extern "C" { 7 | #include // codecs 8 | #include // error codes 9 | #include 10 | } 11 | 12 | #ifndef DECODER_H_ 13 | #define DECODER_H_ 14 | 15 | class Decoder { 16 | public: 17 | Decoder(AVCodecContext *avctx, PacketQueue *queue, 18 | std::condition_variable *empty_queue_cond); 19 | virtual ~Decoder(); 20 | 21 | int Decode(AVFrame *frame); 22 | 23 | inline void SetStartPts(int64_t start_pts) { start_pts_ = start_pts; } 24 | void SetStartPtsTimebase(AVRational start_pts_timebase) { 25 | start_pts_timebase_ = start_pts_timebase; 26 | } 27 | 28 | inline int GetSerial() const { return serial_; } 29 | inline int64_t GetNumberOfIncorrectDtsValues() const { 30 | return p_codec_context_->pts_correction_num_faulty_dts; 31 | } 32 | inline int64_t GetNumberOfIncorrectPtsValues() const { 33 | return p_codec_context_->pts_correction_num_faulty_pts; 34 | } 35 | 36 | inline bool IsFinished() const { return is_finished_; } 37 | inline void setFinished(bool finished) { is_finished_ = finished; } 38 | 39 | int Start(const std::function &decoding); 40 | void Stop(FrameQueue *frame_queue); 41 | 42 | private: 43 | AVPacket packet_; 44 | AVCodecContext *p_codec_context_; 45 | PacketQueue *p_packet_queue_; 46 | std::condition_variable *p_is_empty_condition_; 47 | int serial_; 48 | bool is_finished_; 49 | bool is_packet_pending_; 50 | int do_reorder_; // let decoder reorder pts 0=off 1=on -1=auto 51 | int64_t start_pts_; 52 | AVRational start_pts_timebase_; 53 | int64_t next_pts_; 54 | AVRational next_pts_timebase_; 55 | std::thread *p_decoder_thread_; 56 | }; 57 | 58 | #endif DECODER_H_ 59 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegSdlMediaPlayer.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/main/cpp/Media.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | #ifndef _MEDIA_H_ 27 | #define _MEDIA_H_ 28 | 29 | #include "Pipeline.h" 30 | #include 31 | #include 32 | 33 | using namespace std; 34 | 35 | /** 36 | * class CMedia 37 | * 38 | * Analagous to Jfxmedia's java version. 39 | */ 40 | class CMedia { 41 | public: 42 | CMedia(CPipeline *pPipe); 43 | virtual ~CMedia(); 44 | 45 | CPipeline *GetPipeline(); 46 | static bool IsValid(CMedia *pMedia); 47 | 48 | protected: 49 | CMedia() : p_pipeline(NULL) {} 50 | 51 | protected: 52 | CPipeline *p_pipeline; 53 | }; 54 | 55 | #endif //_MEDIA_H_ 56 | -------------------------------------------------------------------------------- /src/main/cpp/org_datavyu_plugins_ffmpeg_NativeMediaPlayer.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class org_datavyu_plugins_ffmpeg_NativeMediaPlayer */ 4 | 5 | #ifndef _Included_org_datavyu_plugins_ffmpeg_NativeMediaPlayer 6 | #define _Included_org_datavyu_plugins_ffmpeg_NativeMediaPlayer 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerUnknown 11 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerUnknown 100L 12 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerReady 13 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerReady 101L 14 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerPlaying 15 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerPlaying 102L 16 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerPaused 17 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerPaused 103L 18 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerStopped 19 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerStopped 104L 20 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerStalled 21 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerStalled 105L 22 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerFinished 23 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerFinished 106L 24 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerError 25 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_eventPlayerError 107L 26 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_SEEK_ACCURATE_FLAG 27 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_SEEK_ACCURATE_FLAG 1L 28 | #undef org_datavyu_plugins_ffmpeg_NativeMediaPlayer_SEEK_FAST_FLAG 29 | #define org_datavyu_plugins_ffmpeg_NativeMediaPlayer_SEEK_FAST_FLAG 16L 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | #endif 34 | -------------------------------------------------------------------------------- /src/main/cpp/Singleton.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | #ifndef _SINGLETON_H_ 27 | #define _SINGLETON_H_ 28 | 29 | #include "MediaPlayerErrors.h" 30 | #include 31 | 32 | template class Singleton { 33 | public: 34 | Singleton() { p_instance_ = NULL; } 35 | 36 | ~Singleton() { 37 | if (p_instance_) 38 | delete p_instance_; 39 | } 40 | 41 | uint32_t GetInstance(T **pInstance) { 42 | uint32_t uErrorCode = ERROR_NONE; 43 | 44 | if (NULL == p_instance_) 45 | uErrorCode = T::CreateInstance(&p_instance_); 46 | 47 | if (ERROR_NONE == uErrorCode) 48 | *pInstance = p_instance_; 49 | 50 | return uErrorCode; 51 | } 52 | 53 | private: 54 | T *p_instance_; 55 | }; 56 | 57 | #endif // _SINGLETON_H_ 58 | -------------------------------------------------------------------------------- /src/main/cpp/PipelineData.h: -------------------------------------------------------------------------------- 1 | #ifndef _PIPELINEDATA_H_ 2 | #define _PIPELINEDATA_H_ 3 | 4 | #include "AudioVideoFormats.h" 5 | #include "Pipeline.h" 6 | #include "PipelineOptions.h" 7 | #include 8 | #include 9 | 10 | class CPipelineData : public CPipeline { 11 | public: 12 | CPipelineData(CPipelineOptions *p_options = NULL); 13 | virtual ~CPipelineData(); 14 | 15 | virtual uint32_t Init(const char *filename) = 0; 16 | virtual void Dispose(); 17 | 18 | virtual uint32_t Play() = 0; 19 | virtual uint32_t Stop() = 0; 20 | virtual uint32_t Pause() = 0; 21 | virtual uint32_t StepForward() = 0; 22 | virtual uint32_t Finish() = 0; 23 | 24 | virtual uint32_t Seek(double seek_time) = 0; 25 | 26 | virtual uint32_t GetDuration(double *p_duration) = 0; 27 | virtual uint32_t GetStreamTime(double *p_stream_time) = 0; 28 | virtual uint32_t GetFps(double *p_fps) = 0; 29 | 30 | virtual uint32_t SetRate(float rate) = 0; 31 | virtual uint32_t GetRate(float *p_rate) = 0; 32 | 33 | virtual uint32_t SetVolume(float volume) = 0; 34 | virtual uint32_t GetVolume(float *p_volume) = 0; 35 | 36 | virtual uint32_t SetBalance(float balance) = 0; 37 | virtual uint32_t GetBalance(float *p_balance) = 0; 38 | 39 | virtual uint32_t SetAudioSyncDelay(long millis) = 0; 40 | virtual uint32_t GetAudioSyncDelay(long *p_millis) = 0; 41 | 42 | virtual uint32_t HasAudioData(bool *p_audio_data) const = 0; 43 | virtual uint32_t HasImageData(bool *b_image_data) const = 0; 44 | virtual uint32_t GetImageWidth(int *p_width) const = 0; 45 | virtual uint32_t GetImageHeight(int *p_height) const = 0; 46 | virtual uint32_t GetAudioFormat(AudioFormat *p_audio_format) const = 0; 47 | virtual uint32_t GetPixelFormat(PixelFormat *p_pixel_format) const = 0; 48 | virtual uint32_t UpdateImageBuffer(uint8_t *p_image_buffer, 49 | const long len) = 0; 50 | virtual uint32_t UpdateAudioBuffer(uint8_t *p_audio_buffer, 51 | const long len) = 0; 52 | }; 53 | 54 | #endif //_PIPELINEDATA_H_ 55 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegJavaAvPlaybackPipline.h: -------------------------------------------------------------------------------- 1 | #ifndef FFMPEGJAVAAVPLAYBACKPIPELINE_H_ 2 | #define FFMPEGJAVAAVPLAYBACKPIPELINE_H_ 3 | 4 | #include "FfmpegJavaAvPlayback.h" 5 | #include "MediaPlayerErrors.h"; 6 | #include "PipelineData.h" 7 | 8 | class FfmpegJavaAvPlaybackPipline : public CPipelineData { 9 | public: 10 | virtual uint32_t Init(const char *input_file); 11 | virtual void Dispose(); 12 | FfmpegJavaAvPlaybackPipline(CPipelineOptions *p_options); 13 | virtual ~FfmpegJavaAvPlaybackPipline(); 14 | 15 | private: 16 | virtual uint32_t Play(); 17 | virtual uint32_t Stop(); 18 | virtual uint32_t Pause(); 19 | virtual uint32_t StepForward(); 20 | virtual uint32_t StepBackward(); 21 | virtual uint32_t Finish(); 22 | 23 | virtual uint32_t Seek(double seek_time); 24 | 25 | virtual uint32_t GetDuration(double *p_duration); 26 | virtual uint32_t GetStreamTime(double *p_stream_time); 27 | virtual uint32_t GetFps(double *p_fps); 28 | 29 | virtual uint32_t SetRate(float rate); 30 | virtual uint32_t GetRate(float *p_rate); 31 | 32 | virtual uint32_t SetVolume(float volume); 33 | virtual uint32_t GetVolume(float *p_volume); 34 | 35 | virtual uint32_t SetBalance(float balance); 36 | virtual uint32_t GetBalance(float *p_balance); 37 | 38 | virtual uint32_t SetAudioSyncDelay(long millis); 39 | virtual uint32_t GetAudioSyncDelay(long *p_millis); 40 | 41 | // Full fill the data interface 42 | virtual uint32_t HasAudioData(bool *p_audio_data) const; 43 | virtual uint32_t HasImageData(bool *p_image_data) const; 44 | virtual uint32_t GetImageWidth(int *p_width) const; 45 | virtual uint32_t GetImageHeight(int *p_height) const; 46 | virtual uint32_t GetAudioFormat(AudioFormat *p_audio_params) const; 47 | virtual uint32_t GetPixelFormat(PixelFormat *p_pixel_format) const; 48 | virtual uint32_t UpdateImageBuffer(uint8_t *p_image_data, const long len); 49 | virtual uint32_t UpdateAudioBuffer(uint8_t *p_audio_data, const long len); 50 | 51 | FfmpegJavaAvPlayback *p_java_playback_; 52 | }; 53 | 54 | #endif // !FFMPEGJAVAAVPLAYBACKPIPELINE_H_ 55 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegSdlAvPlaybackPipeline.h: -------------------------------------------------------------------------------- 1 | #ifndef _FFMPEG_AV_PLAYBACK_PIPELINE_H_ 2 | #define _FFMPEG_AV_PLAYBACK_PIPELINE_H_ 3 | 4 | #include "FfmpegSdlAvPlayback.h" 5 | #include "Pipeline.h" 6 | #include "PipelineOptions.h" 7 | 8 | /** 9 | * class FfmpegAVPlaybackPipeline 10 | * 11 | * Class representing a Ffmpeg audio-video pipeline. 12 | * 13 | * Note, currently this pipeline uses SDL to play audio/image 14 | */ 15 | class FfmpegSdlAvPlaybackPipeline : public CPipeline { 16 | public: 17 | virtual uint32_t Init(const char *input_file); 18 | virtual void Dispose(); 19 | FfmpegSdlAvPlaybackPipeline(CPipelineOptions *pOptions); 20 | virtual ~FfmpegSdlAvPlaybackPipeline(); 21 | 22 | private: 23 | virtual uint32_t Play(); 24 | virtual uint32_t Stop(); 25 | virtual uint32_t Pause(); 26 | virtual uint32_t StepForward(); 27 | virtual uint32_t StepBackward(); 28 | virtual uint32_t Finish(); 29 | 30 | virtual uint32_t Seek(double seek_time); 31 | 32 | virtual uint32_t GetDuration(double *p_duration); 33 | virtual uint32_t GetStreamTime(double *p_stream_time); 34 | virtual uint32_t GetFps(double *p_fps); 35 | 36 | virtual uint32_t SetRate(float rate); 37 | virtual uint32_t GetRate(float *p_rate); 38 | 39 | virtual uint32_t SetVolume(float volume); 40 | virtual uint32_t GetVolume(float *p_volume); 41 | 42 | virtual uint32_t SetBalance(float balance); 43 | virtual uint32_t GetBalance(float *p_balance); 44 | 45 | virtual uint32_t SetAudioSyncDelay(long millis); 46 | virtual uint32_t GetAudioSyncDelay(long *p_millis); 47 | 48 | virtual uint32_t GetImageWidth(int *p_width) const; 49 | virtual uint32_t GetImageHeight(int *p_height) const; 50 | 51 | virtual uint32_t GetWindowHeight(int *p_height) const; 52 | virtual uint32_t GetWindowWidth(int *p_width) const; 53 | virtual uint32_t SetWindowSize(int width, int height); 54 | 55 | virtual uint32_t ShowWindow(); 56 | virtual uint32_t HideWindow(); 57 | virtual uint32_t IsVisible(int *visible) const; 58 | 59 | FfmpegSdlAvPlayback *p_sdl_playback_; 60 | }; 61 | 62 | #endif //_FFMPEG_AV_PLAYBACK_PIPELINE_H_ 63 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegJavaMediaPlayer.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/main/cpp/PacketQueue.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern "C" { 5 | #include // codecs 6 | #include // memory 7 | } 8 | 9 | #ifndef PACKET_QUEUE_H_ 10 | #define PACKET_QUEUE_H_ 11 | 12 | // Port of the packet queue from ffplay.c into c++ 13 | // 14 | // Replaces the SDL mutex through c++ std mutex/condition variable 15 | class PacketQueue { 16 | public: 17 | AVPacket 18 | flush_packet_; // TODO(fraudies): better use one object for all queues 19 | 20 | PacketQueue(); 21 | 22 | virtual ~PacketQueue() { 23 | Flush(); 24 | av_packet_unref(&flush_packet_); 25 | av_freep(&flush_packet_); 26 | } 27 | 28 | void Flush(); 29 | 30 | void Abort(); 31 | 32 | inline bool IsAbortRequested() const { return is_abort_requested_; } 33 | 34 | inline void GetPtrSerial(int **pp_serial) { *pp_serial = &serial_; } 35 | 36 | inline int GetSerial() const { return serial_; } 37 | 38 | inline int GetSize() const { return size_; } 39 | 40 | inline int getNumberOfPackets() const { return num_packets_; } 41 | 42 | inline int64_t GetDuration() const { return duration_; } 43 | 44 | void Start(); 45 | 46 | int Put(AVPacket *p_packet); // Must remain a pointer to cleanup package 47 | 48 | int PutNullPacket(int stream_index); 49 | 50 | int PutFlushPacket(); 51 | 52 | inline bool IsFlushPacket(const AVPacket &pkt) const { 53 | return pkt.data == flush_packet_.data; 54 | } 55 | 56 | /* return < 0 if aborted, 0 if no packet and > 0 if packet. */ 57 | int Get(AVPacket *pkt, int block, int *serial); 58 | 59 | private: 60 | // This list maintains the next for the queue 61 | typedef struct MyAVPacketList { 62 | AVPacket packet_; 63 | struct MyAVPacketList *p_next_; 64 | int serial_; 65 | } MyAVPacketList; 66 | 67 | bool is_abort_requested_; 68 | int serial_; 69 | int num_packets_; 70 | 71 | MyAVPacketList *p_first_packet_; 72 | MyAVPacketList *p_last_packet_; 73 | int size_; 74 | int64_t duration_; 75 | bool put_condition_; 76 | std::mutex mutex_; 77 | std::condition_variable condition_; 78 | 79 | int _Put(AVPacket *p_packet); 80 | }; 81 | 82 | #endif PACKET_QUEUE_H_ 83 | -------------------------------------------------------------------------------- /src/main/cpp/PipelineOptions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | #ifndef _PIPELINE_OPTIONS_H_ 27 | #define _PIPELINE_OPTIONS_H_ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "FfmpegJniUtils.h" 34 | 35 | using namespace std; 36 | 37 | class CPipelineOptions { 38 | public: 39 | CPipelineOptions(AudioFormat audioFormat = AudioFormat(), 40 | PixelFormat pixelFormat = PixelFormat(), 41 | int audioBufferSizeInBy = 0) 42 | : audio_format_(audioFormat), pixel_format_(pixelFormat), 43 | audio_buffer_size_in_by_(audioBufferSizeInBy) {} 44 | 45 | virtual ~CPipelineOptions() {} 46 | inline const AudioFormat *GetAudioFormat() const { return &audio_format_; } 47 | inline const PixelFormat *GetPixelFormat() const { return &pixel_format_; } 48 | inline const int GetAudioBufferSizeInBy() const { 49 | return audio_buffer_size_in_by_; 50 | } 51 | 52 | private: 53 | AudioFormat audio_format_; 54 | PixelFormat pixel_format_; 55 | int audio_buffer_size_in_by_; 56 | }; 57 | 58 | #endif //_PIPELINE_OPTIONS_H_ 59 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/PlayerStateEvent.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins; 2 | 3 | /** 4 | * This player state event is for the communication of the player 5 | * state between the native code which controls the state 6 | * transitions and the java side which requires state transitions. 7 | */ 8 | public class PlayerStateEvent extends PlayerEvent { 9 | 10 | public enum PlayerState { 11 | UNKNOWN, 12 | READY, 13 | PLAYING, 14 | PAUSED, 15 | STOPPED, 16 | STALLED, 17 | FINISHED, 18 | HALTED 19 | } 20 | 21 | private PlayerState playerState; 22 | private double playerTime; 23 | private String message; 24 | 25 | /** 26 | * Constructor. 27 | * 28 | * @param state The state of the player. 29 | * @param time The time in seconds when this event occurred. 30 | * @throws IllegalArgumentException if state is null or 31 | * time<0.0. 32 | */ 33 | public PlayerStateEvent(PlayerState state, double time) { 34 | if (state == null) { 35 | throw new IllegalArgumentException("state == null!"); 36 | } else if (time < 0.0) { 37 | throw new IllegalArgumentException("time < 0.0!"); 38 | } 39 | 40 | this.playerState = state; 41 | this.playerTime = time; 42 | } 43 | 44 | /** 45 | * Constructor. 46 | * 47 | * @param state The state of the player. 48 | * @param time The time in seconds when this event occurred. 49 | * @param message Carries auxiliary message. HALTED state has additional information. 50 | * @throws IllegalArgumentException if state is null or 51 | * time<0.0. 52 | */ 53 | public PlayerStateEvent(PlayerState state, double time, String message) { 54 | this(state, time); 55 | this.message = message; 56 | } 57 | 58 | /** 59 | * Retrieves the state of the media player. 60 | * 61 | * @return The player's state. 62 | */ 63 | public PlayerState getState() { 64 | return playerState; 65 | } 66 | 67 | /** 68 | * Presentation time when the event occurred. 69 | * 70 | * @return The time in seconds of the state transition. 71 | */ 72 | public double getTime() { 73 | return playerTime; 74 | } 75 | 76 | /** 77 | * Auxiliary message information when available. 78 | * 79 | * @return The message or null. 80 | */ 81 | public String getMessage() { 82 | return message; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/ffmpeg/FfmpegMediaPlayer.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins.ffmpeg; 2 | 3 | import org.datavyu.plugins.DatavyuMediaPlayer; 4 | import org.datavyu.plugins.MediaException; 5 | import org.datavyu.plugins.PlayerStateEvent; 6 | 7 | import org.datavyu.plugins.PlayerStateListener; 8 | import java.net.URI; 9 | 10 | /** Uses ffmpeg to decode and transcode (optional) image and audio data */ 11 | abstract class FfmpegMediaPlayer extends DatavyuMediaPlayer { 12 | 13 | private PlayerStateListener stateListener; 14 | 15 | protected final Object initLock = new Object(); 16 | 17 | protected double startTime = 0.0; 18 | 19 | /** 20 | * Create an ffmpeg media player instance 21 | * 22 | * @param mediaPath The path to the media 23 | */ 24 | protected FfmpegMediaPlayer(URI mediaPath) { 25 | super(mediaPath); 26 | stateListener = new FfmpegPlayerStateListener(); 27 | this.addMediaPlayerStateListener(stateListener); 28 | } 29 | 30 | @Override 31 | protected double playerGetStartTime() throws MediaException { 32 | return startTime; 33 | } 34 | 35 | @Override 36 | protected void playerSetStartTime(double startTime) throws MediaException { 37 | this.startTime = startTime; 38 | playerSeek(startTime); 39 | } 40 | 41 | @Override 42 | protected boolean playerIsSeekPlaybackEnabled() { 43 | return playBackRate < 0F || playBackRate > 32F; 44 | } 45 | 46 | @Override 47 | protected boolean playerRateIsSupported(final float rate) { 48 | return 0F <= rate && rate <= 32F; 49 | } 50 | 51 | class FfmpegPlayerStateListener implements PlayerStateListener { 52 | 53 | @Override 54 | public void onReady(PlayerStateEvent evt) { 55 | synchronized (initLock) { 56 | try { 57 | // wait for the initialization of the Java Side 58 | // This will make sure to have a correct PTS 59 | initLock.wait(100); 60 | } catch (InterruptedException e) { 61 | e.printStackTrace(); 62 | } 63 | } 64 | } 65 | 66 | @Override 67 | public void onPlaying(PlayerStateEvent evt) {} 68 | 69 | @Override 70 | public void onPause(PlayerStateEvent evt) {} 71 | 72 | @Override 73 | public void onStop(PlayerStateEvent evt) {} 74 | 75 | @Override 76 | public void onStall(PlayerStateEvent evt) {} 77 | 78 | @Override 79 | public void onFinish(PlayerStateEvent evt) {} 80 | 81 | @Override 82 | public void onHalt(PlayerStateEvent evt) {} 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegAvPlayback.cpp: -------------------------------------------------------------------------------- 1 | #include "FfmpegAvPlayback.h" 2 | #include "MediaPlayerErrors.h" 3 | 4 | bool FfmpegAvPlayback::kEnableShowStatus = true; 5 | 6 | FfmpegAvPlayback::FfmpegAvPlayback() 7 | : p_video_state_(nullptr), display_disabled_(false), frame_width_(0), 8 | frame_height_(0), force_refresh_(true), num_frame_drops_late_(0) {} 9 | 10 | int FfmpegAvPlayback::OpenVideo(const char *filename, 11 | AVInputFormat *p_input_format, 12 | int audio_buffer_size) { 13 | return VideoState::OpenStream(&p_video_state_, filename, p_input_format, 14 | audio_buffer_size); 15 | } 16 | 17 | void FfmpegAvPlayback::SetUpdatePlayerStateCallbackFunction( 18 | PlayerState::State state, const std::function &func) { 19 | update_player_state_callbacks[state] = func; 20 | p_video_state_->SetUpdatePlayerStateCallbackFunction(state, func); 21 | } 22 | 23 | void FfmpegAvPlayback::Play() { 24 | if (IsPaused() || IsStopped() || IsReady()) { 25 | SetPlaying(); 26 | } 27 | } 28 | 29 | void FfmpegAvPlayback::Pause() { 30 | if (!IsPaused() && !IsReady()) { 31 | SetPaused(); 32 | } 33 | } 34 | 35 | // Stop and put the playback speed to 0x 36 | void FfmpegAvPlayback::Stop() { 37 | if (!IsStopped() && !IsReady()) { 38 | SetStopped(); 39 | } 40 | } 41 | 42 | // Pause and keep the playback speed 43 | void FfmpegAvPlayback::TogglePauseAndStopStep(bool mute) { 44 | p_video_state_->TogglePauseAndMute(mute); 45 | p_video_state_->SetStepping(false); 46 | } 47 | 48 | int FfmpegAvPlayback::SetSpeed(double speed) { 49 | int err = ERROR_NONE; 50 | if (speed < 0) { 51 | err = ERROR_FFMPEG_FILTER_NOT_FOUND; // no filter available for backward 52 | // playback 53 | } else if (speed < std::numeric_limits::epsilon()) { 54 | Pause(); 55 | } else { 56 | err = p_video_state_->SetSpeed(speed); 57 | } 58 | return err ? ERROR_FFMPEG_FILTER_NOT_FOUND : ERROR_NONE; 59 | } 60 | 61 | double FfmpegAvPlayback::ComputeFrameDuration(Frame *vp, Frame *nextvp, 62 | double max_frame_duration) { 63 | if (vp->serial_ == nextvp->serial_) { 64 | double duration = (nextvp->pts_ - vp->pts_) / p_video_state_->GetSpeed(); 65 | if (isnan(duration) || duration <= 0 || duration > max_frame_duration) 66 | return vp->duration_; 67 | else 68 | return duration; 69 | } else { 70 | return 0.0; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/cpp/JniUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | #ifndef _JNI_UTILS_H_ 27 | #define _JNI_UTILS_H_ 28 | 29 | #include 30 | #include 31 | 32 | #if defined(_LP64) || defined(_WIN64) 33 | #define jlong_to_ptr(a) ((void *)(a)) 34 | #define ptr_to_jlong(a) ((jlong)(a)) 35 | #else 36 | #define jlong_to_ptr(a) ((void *)(int)(a)) 37 | #define ptr_to_jlong(a) ((jlong)(int)(a)) 38 | #endif 39 | 40 | // Gets a valid, usable JNIEnv for the current thread 41 | // if didAttach is true on return then you should call 42 | // jvm->DetachCurrentThread() when done 43 | JNIEnv *GetJavaEnvironment(JavaVM *jvm, jboolean &didAttach); 44 | 45 | /* 46 | * Example usage of this class: 47 | * { 48 | * JavaVM *jvm = ...; 49 | * CJavaEnvironment jenv(jvm); 50 | * if ((env = jenv->getEnvironment()) != NULL) { 51 | * env->...; 52 | * } 53 | * } 54 | */ 55 | class CJavaEnvironment { 56 | public: 57 | CJavaEnvironment(JavaVM *); 58 | CJavaEnvironment(JNIEnv *); // create with an existing JNIEnv 59 | ~CJavaEnvironment(); 60 | 61 | JNIEnv *GetEnvironment(); 62 | bool HasException(); // return true if an exception is raised (but do nothing 63 | // with it) 64 | bool ClearException(); // if an exception is raised, clear it and return true 65 | bool ReportException(); // as above but log the exception to Logger 66 | 67 | private: 68 | JNIEnv *p_environment; 69 | jboolean attached; 70 | }; 71 | 72 | #endif //_JNI_UTILS_H_ 73 | -------------------------------------------------------------------------------- /demo/JavaFXMediaPlayer.java: -------------------------------------------------------------------------------- 1 | import javafx.application.Application; 2 | import javafx.application.Platform; 3 | import javafx.concurrent.Task; 4 | import javafx.stage.Stage; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.datavyu.plugins.MediaPlayerWindow; 8 | import org.datavyu.plugins.ffmpeg.FfmpegSdlMediaPlayer; 9 | 10 | import java.io.File; 11 | import java.net.URI; 12 | import java.util.concurrent.ExecutorService; 13 | import java.util.concurrent.Executors; 14 | 15 | public class JavaFXMediaPlayer extends Application { 16 | private static Logger logger = LogManager.getLogger(JavaFXMediaPlayer.class); 17 | private JMediaPlayerControlFrame controller; 18 | private MediaPlayerWindow mediaPlayer; 19 | private URI mediaPath; 20 | 21 | @Override 22 | public void start(Stage primaryStage) { 23 | mediaPath = new File("Nature_30fps_1080p.mp4").toURI(); 24 | 25 | MediaPlayerTask mediaPlayerTask = new MediaPlayerTask(mediaPath); 26 | 27 | mediaPlayerTask.setOnSucceeded( 28 | event -> { 29 | mediaPlayer = mediaPlayerTask.getValue(); 30 | 31 | mediaPlayer.addMediaErrorListener( 32 | // Handle error thrown by The Media Player 33 | (source, errorCode, message) -> logger.error(errorCode + ": " + message)); 34 | 35 | // Handle Window Key events triggered from SDL window 36 | mediaPlayer.addSdlKeyEventListener( 37 | (source, nativeMediaRef, javaKeyCode) -> 38 | controller.handleKeyEvents(javaKeyCode)); 39 | // Open a simple JFrame to control the media player through key commands 40 | // Be creative and create your own controller in JavaFX 41 | Platform.runLater( 42 | () -> { 43 | controller = new JMediaPlayerControlFrame(mediaPlayer); 44 | }); 45 | }); 46 | 47 | mediaPlayerTask.setOnFailed(event -> Platform.exit()); 48 | 49 | ExecutorService executorService = Executors.newSingleThreadExecutor(); 50 | executorService.execute(mediaPlayerTask); 51 | executorService.shutdown(); 52 | } 53 | } 54 | 55 | class MediaPlayerTask extends Task { 56 | private URI mediaPath; 57 | 58 | MediaPlayerTask(URI mediaPath) { 59 | this.mediaPath = mediaPath; 60 | } 61 | 62 | @Override 63 | protected MediaPlayerWindow call() throws Exception { 64 | MediaPlayerWindow mediaPlayer = new FfmpegSdlMediaPlayer(mediaPath); 65 | mediaPlayer.init(); 66 | return mediaPlayer; 67 | } 68 | } -------------------------------------------------------------------------------- /src/main/cpp/Media.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | #include "Media.h" 27 | 28 | //************************************************************************************************* 29 | //********** class CMedia 30 | //************************************************************************************************* 31 | 32 | /** 33 | * CMedia::CMedia() 34 | * 35 | * Constructor. A CPipeline object must be associated with the CMedia instance. 36 | * It's the only way for the CMedia object to get information about the media 37 | * itself. 38 | * 39 | * @param pPipe CPipeline object to associate with the CMedia 40 | */ 41 | CMedia::CMedia(CPipeline *pPipe) { p_pipeline = pPipe; } 42 | 43 | /** 44 | * CMedia::~CMedia() 45 | * 46 | * Destructor 47 | */ 48 | CMedia::~CMedia() { 49 | if (p_pipeline != NULL) { 50 | p_pipeline->Dispose(); 51 | delete p_pipeline; 52 | p_pipeline = NULL; 53 | } 54 | } 55 | 56 | /** 57 | * CMedia::IsValid(CMedia* pMedia) 58 | * 59 | * Checks if the CMedia object is valid 60 | * 61 | * @param pMedia pointer to a CMedia object 62 | * 63 | * @return true/false 64 | */ 65 | bool CMedia::IsValid(CMedia *pMedia) { 66 | bool bValid = false; 67 | 68 | //***** CMedia is valid if there is a pipeline associated with the media 69 | bValid = (NULL != pMedia) && (NULL != pMedia->p_pipeline); 70 | 71 | return bValid; 72 | } 73 | 74 | /** 75 | * CMedia::GetPipeline() 76 | * 77 | * Returns a pPointer to the associated CPipeline object. 78 | */ 79 | CPipeline *CMedia::GetPipeline() { return p_pipeline; } 80 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | #*.xcworkspace merge=binary 38 | #*.xcodeproj merge=binary 39 | 40 | ############################################################################### 41 | # behavior for image files 42 | # 43 | # image files are treated as binary by default. 44 | ############################################################################### 45 | #*.jpg binary 46 | #*.png binary 47 | #*.gif binary 48 | 49 | ############################################################################### 50 | # diff behavior for common document formats 51 | # 52 | # Convert binary document formats to text before diffing them. This feature 53 | # is only available from the command line. Turn it on by uncommenting the 54 | # entries below. 55 | ############################################################################### 56 | #*.doc diff=astextplain 57 | #*.DOC diff=astextplain 58 | #*.docx diff=astextplain 59 | #*.DOCX diff=astextplain 60 | #*.dot diff=astextplain 61 | #*.DOT diff=astextplain 62 | #*.pdf diff=astextplain 63 | #*.PDF diff=astextplain 64 | #*.rtf diff=astextplain 65 | #*.RTF diff=astextplain 66 | -------------------------------------------------------------------------------- /NativeOSXCanvas/make/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | "Nothing to do for install-headers phase" 89 | 90 | 91 | -------------------------------------------------------------------------------- /src/main/cpp/TestPacketQueue.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | 3 | #include "PacketQueue.h" 4 | 5 | #include 6 | 7 | extern "C" { 8 | #include // codecs 9 | } 10 | 11 | TEST(PacketQueueTest, CreateDeletePacketTest) { 12 | PacketQueue packetQueue; 13 | packetQueue.Start(); 14 | packetQueue.Flush(); 15 | } 16 | 17 | TEST(PacketQueueTest, FlushPacketQueueTest) { 18 | // Prepare the queue 19 | PacketQueue packetQueue; 20 | packetQueue.Start(); 21 | packetQueue.Flush(); // flushes all packets 22 | AVPacket getPkt; 23 | ASSERT_EQ(0, packetQueue.Get(&getPkt, 0, 24 | nullptr)); // non-blocking get of empty queue 25 | } 26 | 27 | TEST(PacketQueueTest, PutGetPacketTest) { 28 | // Create and initialize some packets 29 | uint8_t dummy = 123; 30 | AVPacket putPkt; 31 | AVPacket getPkt; 32 | av_init_packet(&putPkt); 33 | putPkt.pos = 123; 34 | putPkt.data = &dummy; 35 | // Create, start the packet queue and put/get 36 | PacketQueue packetQueue; 37 | packetQueue.Start(); 38 | packetQueue.Flush(); 39 | ASSERT_EQ(0, packetQueue.Put(&putPkt)); 40 | ASSERT_LT(0, packetQueue.Get(&getPkt, 1, nullptr)); 41 | ASSERT_EQ(getPkt.pos, putPkt.pos); 42 | ASSERT_EQ(*getPkt.data, *putPkt.data); 43 | // Note, I don't free the packets here to simplify the code 44 | } 45 | 46 | TEST(PacketQueueTest, PutGetFlushPacketTest) { 47 | AVPacket getPkt; 48 | PacketQueue packetQueue; 49 | packetQueue.Start(); 50 | packetQueue.Flush(); 51 | packetQueue.PutFlushPacket(); 52 | ASSERT_LT(0, packetQueue.Get(&getPkt, 1, nullptr)); 53 | ASSERT_TRUE(packetQueue.IsFlushPacket(getPkt)); 54 | } 55 | 56 | TEST(PacketQueueTest, AbortBlockReadPacketTest) { 57 | // Prepare the queue 58 | PacketQueue packetQueue; 59 | packetQueue.Start(); 60 | packetQueue.Flush(); 61 | 62 | // Read packet but blocked 63 | std::thread reader([&packetQueue] { 64 | AVPacket getPkt; 65 | ASSERT_EQ(-1, packetQueue.Get(&getPkt, 1, nullptr)); // abort returns -1 66 | }); 67 | 68 | packetQueue.Abort(); 69 | reader.join(); 70 | } 71 | 72 | TEST(PacketQueueTest, MultiThreadPutGetPacketTest) { 73 | // Prepare the queue 74 | PacketQueue packetQueue; 75 | packetQueue.Start(); 76 | packetQueue.Flush(); 77 | 78 | // Write some packets 79 | std::thread writer([&packetQueue] { 80 | for (int writes = 0; writes < 10; writes++) { 81 | AVPacket putPkt; 82 | av_init_packet(&putPkt); 83 | putPkt.pos = writes; 84 | packetQueue.Put(&putPkt); 85 | } 86 | }); 87 | 88 | // Read some packets (blocking) 89 | std::thread reader([&packetQueue] { 90 | AVPacket getPkt; 91 | for (int reads = 0; reads < 10; reads++) { 92 | ASSERT_LT(0, packetQueue.Get(&getPkt, 1, nullptr)); 93 | ASSERT_EQ(getPkt.pos, reads); 94 | } 95 | }); 96 | 97 | writer.join(); 98 | reader.join(); 99 | } 100 | -------------------------------------------------------------------------------- /src/main/cpp/VideoState.vcxitems: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | {90f330aa-8e8c-4625-87cd-a321c52cb6e9} 7 | 8 | 9 | 10 | %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/main/cpp/JavaPlayerEventDispatcher.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | #ifndef _JAVA_PLAYER_EVENT_DISPATCHER_H_ 27 | #define _JAVA_PLAYER_EVENT_DISPATCHER_H_ 28 | 29 | #include 30 | 31 | #include "Media.h" 32 | #include "Pipeline.h" 33 | 34 | using namespace std; 35 | 36 | class CJavaPlayerEventDispatcher { 37 | public: 38 | CJavaPlayerEventDispatcher(); 39 | ~CJavaPlayerEventDispatcher(); 40 | 41 | void Init(JNIEnv *env, jobject PlayerInstance, CMedia *pMedia); 42 | void Dispose(); 43 | 44 | virtual bool SendPlayerMediaErrorEvent(int errorCode); 45 | virtual bool SendPlayerStateEvent(int newState, double presentTime); 46 | #ifdef SDL_ENABLED 47 | virtual bool SendSdlPlayerKeyEvent(int keyId); 48 | #endif // SDL_ENABLED 49 | 50 | private: 51 | JavaVM *p_player_vm_; 52 | jobject player_instance_; 53 | jlong media_reference_; // FIXME: Nuke this field, it's completely unused 54 | 55 | static jmethodID send_warning_method_; 56 | 57 | static jmethodID send_player_media_error_event_method_; 58 | static jmethodID send_player_state_event_method_; 59 | #ifdef SDL_ENABLED 60 | static jmethodID send_sdl_player_key_event_method_; 61 | #endif // SDL_ENABLED 62 | 63 | static jobject CreateObject(JNIEnv *env, jmethodID *cid, 64 | const char *class_name, const char *signature, 65 | jvalue *value); 66 | static jobject CreateBoolean(JNIEnv *env, jboolean boolean_value); 67 | static jobject CreateInteger(JNIEnv *env, jint int_value); 68 | static jobject CreateLong(JNIEnv *env, jlong long_value); 69 | static jobject CreateDouble(JNIEnv *env, jdouble double_value); 70 | static jobject CreateDuration(JNIEnv *env, jlong duration); 71 | }; 72 | 73 | #endif // _JAVA_PLAYER_EVENT_DISPATCHER_H_ 74 | -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/xcuserdata/jesse.xcuserdatad/xcschemes/JAWTExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/xcuserdata/jesse.xcuserdatad/xcschemes/Compile Java.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/xcuserdata/jesse.xcuserdatad/xcschemes/Compile Native.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 60 | 61 | 67 | 68 | 69 | 70 | 72 | 73 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegJavaMediaPlayer.xcodeproj/xcuserdata/RedaNezzar.xcuserdatad/xcschemes/FfmpegJavaMediaPlayer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/ffmpeg/AudioPlayerThread.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins.ffmpeg; 2 | 3 | import org.datavyu.plugins.MediaPlayerData; 4 | 5 | import javax.sound.sampled.*; 6 | 7 | class AudioPlayerThread extends Thread { 8 | private static final AudioFormat MONO_FORMAT = 9 | new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 1, 2, 44100, false); 10 | 11 | private static final AudioFormat STEREO_FORMAT = 12 | new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED, 44100, 8, 2, 2, 44100, false); 13 | private FloatControl volumeControl; 14 | private BooleanControl muteControl; 15 | private boolean isInit = false; 16 | 17 | /** 18 | * Get new audio format for mono playback. 19 | * 20 | * @return AudioFormat for mono playback. 21 | */ 22 | public static AudioFormat getMonoFormat() { 23 | return MONO_FORMAT; 24 | } 25 | 26 | /** 27 | * Get new audio format for stereo playback. 28 | * 29 | * @return AudioFormat for stereo playback. 30 | */ 31 | public static AudioFormat getStereoFormat() { 32 | return STEREO_FORMAT; 33 | } 34 | 35 | private MediaPlayerData mediaPlayerData; 36 | private SourceDataLine soundLine = null; 37 | private volatile boolean stopped = false; 38 | private byte[] data; 39 | 40 | AudioPlayerThread(MediaPlayerData mediaPlayerData) { 41 | this.mediaPlayerData = mediaPlayerData; 42 | setName("FFmpeg audio player thread"); 43 | setDaemon(false); 44 | } 45 | 46 | public void init(AudioFormat audioFormat, int bufferSize) throws LineUnavailableException { 47 | // Get the data line 48 | DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat); 49 | soundLine = (SourceDataLine) AudioSystem.getLine(info); 50 | soundLine.open(audioFormat); 51 | 52 | volumeControl = (FloatControl) soundLine.getControl(FloatControl.Type.MASTER_GAIN); 53 | muteControl = (BooleanControl) soundLine.getControl(BooleanControl.Type.MUTE); 54 | 55 | data = new byte[bufferSize]; 56 | soundLine.start(); 57 | 58 | isInit = true; 59 | } 60 | 61 | public boolean isInit() { 62 | return isInit; 63 | } 64 | 65 | public void setVolume(final float newVolume) { 66 | // Adjust the volume on the output line. 67 | if (volumeControl != null) { 68 | volumeControl.setValue((float) (20.0f * Math.log10(newVolume))); 69 | } 70 | } 71 | 72 | public float getVolume() { 73 | if (volumeControl != null) { 74 | // Convert from decibel to linear 75 | return (float) Math.pow(10.0F, volumeControl.getValue() / 20.0F); 76 | } 77 | return 0; 78 | } 79 | 80 | public void setMute(final boolean newMute) { 81 | if (muteControl != null) { 82 | muteControl.setValue(newMute); 83 | } 84 | } 85 | 86 | public boolean isMute() { 87 | return muteControl != null && muteControl.getValue(); 88 | } 89 | 90 | @Override 91 | public void run() { 92 | while (!stopped) { 93 | mediaPlayerData.updateAudioData(data); 94 | // Write blocks when data can't be consumed fast enough 95 | // Since we handle the pause natively we don't have to buffer non-written bytes here 96 | soundLine.write(data, 0, data.length); 97 | } 98 | } 99 | 100 | public void terminate() { 101 | stopped = true; 102 | isInit = false; 103 | soundLine.drain(); 104 | soundLine.stop(); 105 | soundLine.close(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /NativeOSXCanvas/QTKitCanvas.xcodeproj/xcuserdata/jesse.xcuserdatad/xcschemes/Assemble Application.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /NativeOSXCanvas/src/java/com/apple/dts/samplecode/jawtexample/NativeDrawnCanvas.java: -------------------------------------------------------------------------------- 1 | /* 2 | File: NativeDrawnCanvas.java 3 | Abstract: AWT Canvas which interleaves Java and native drawing. 4 | Version: 2.0 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2011 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | package com.apple.dts.samplecode.jawtexample; 49 | 50 | import java.awt.*; 51 | 52 | public class NativeDrawnCanvas extends Canvas { 53 | static { 54 | // Standard JNI: load the native library 55 | System.loadLibrary("JAWTExample"); 56 | } 57 | 58 | // Paint 5 layered rects: 59 | // Draw first two in Java, 60 | // draw third with native code, 61 | // draw two more in Java 62 | public void paint(final Graphics g) { 63 | g.setColor(Color.green); 64 | g.fillRect(0, 0, 100, 100); 65 | 66 | g.setColor(Color.blue); 67 | g.fillRect(5, 5, 90, 90); 68 | 69 | // flush any outstanding graphics operations 70 | Toolkit.getDefaultToolkit().sync(); 71 | // Call native code to render third (red) rect 72 | nativePaintOnCanvas(); 73 | 74 | g.setColor(Color.yellow); 75 | g.fillRect(25, 25, 50, 50); 76 | 77 | g.setColor(Color.black); 78 | g.fillRect(40, 40, 20, 20); 79 | } 80 | 81 | // This method is implemented in native code. See DrawingCanvas.m 82 | public native void nativePaintOnCanvas(); 83 | } -------------------------------------------------------------------------------- /src/main/cpp/FrameQueue.cpp: -------------------------------------------------------------------------------- 1 | #include "FrameQueue.h" 2 | 3 | void unref_item(Frame *vp) { av_frame_unref(vp->p_frame_); } 4 | 5 | FrameQueue::FrameQueue(const PacketQueue *pktq, int max_size, bool keep_last) 6 | : read_index_(0), write_index_(0), size_(0), max_size_(max_size), 7 | keep_last_(keep_last), read_index_shown_(0), p_packet_queue_(pktq) {} 8 | 9 | FrameQueue::~FrameQueue() { 10 | for (int i = 0; i < max_size_; i++) { 11 | Frame *vp = &p_frames_[i]; 12 | if (vp) { 13 | unref_item(vp); 14 | av_frame_free(&vp->p_frame_); 15 | } 16 | } 17 | delete[] p_frames_; 18 | } 19 | 20 | int FrameQueue::CreateFrameQueue(FrameQueue **pp_frame_queue, 21 | const PacketQueue *p_packet_queue, 22 | int max_size, bool keep_last) { 23 | *pp_frame_queue = 24 | new (std::nothrow) FrameQueue(p_packet_queue, max_size, keep_last); 25 | 26 | if (!(*pp_frame_queue)) { 27 | av_log(NULL, AV_LOG_ERROR, "Unable to create frame queue object"); 28 | return ENOMEM; 29 | } 30 | 31 | (*pp_frame_queue)->p_frames_ = 32 | new (std::nothrow) Frame[max_size](); // initialize with zeros 33 | 34 | if (!(*pp_frame_queue)->p_frames_) { 35 | av_log(NULL, AV_LOG_ERROR, "Unable to initialize frame queue"); 36 | return ENOMEM; 37 | } 38 | 39 | for (int i = 0; i < max_size; i++) { 40 | (*pp_frame_queue)->p_frames_[i].p_frame_ = av_frame_alloc(); 41 | 42 | if (!(*pp_frame_queue)->p_frames_[i].p_frame_) { 43 | av_log(NULL, AV_LOG_ERROR, "Unable to create frame in queue"); 44 | delete (*pp_frame_queue); // will clean up any memory allocated before 45 | return ENOMEM; 46 | } 47 | } 48 | 49 | return 0; 50 | } 51 | 52 | void FrameQueue::Signal() { 53 | std::unique_lock locker(mutex_); 54 | condition_.notify_one(); 55 | locker.unlock(); 56 | } 57 | 58 | void FrameQueue::PeekWritable(Frame **pp_frame) { 59 | // waits until we have space to put a new frame 60 | std::unique_lock locker(mutex_); 61 | condition_.wait(locker, [&] { 62 | return size_ < max_size_ || p_packet_queue_->IsAbortRequested(); 63 | }); 64 | locker.unlock(); 65 | *pp_frame = 66 | p_packet_queue_->IsAbortRequested() ? nullptr : &p_frames_[write_index_]; 67 | } 68 | 69 | void FrameQueue::PeekReadable(Frame **pp_frame) { 70 | // waits until we have a readable new frame 71 | std::unique_lock locker(mutex_); 72 | condition_.wait(locker, [&] { 73 | return size_ - read_index_shown_ > 0 || p_packet_queue_->IsAbortRequested(); 74 | }); 75 | locker.unlock(); 76 | *pp_frame = p_packet_queue_->IsAbortRequested() 77 | ? nullptr 78 | : &p_frames_[(read_index_ + read_index_shown_) % max_size_]; 79 | } 80 | 81 | void FrameQueue::Push() { 82 | if (++write_index_ == max_size_) { 83 | write_index_ = 0; 84 | } 85 | std::unique_lock locker(mutex_); 86 | size_++; 87 | condition_.notify_one(); 88 | locker.unlock(); 89 | } 90 | 91 | void FrameQueue::Next() { 92 | if (keep_last_ && !read_index_shown_) { 93 | read_index_shown_ = 1; 94 | return; 95 | } 96 | unref_item(&p_frames_[read_index_]); 97 | if (++read_index_ == max_size_) { 98 | read_index_ = 0; 99 | } 100 | std::unique_lock locker(mutex_); 101 | size_--; 102 | condition_.notify_one(); 103 | locker.unlock(); 104 | } 105 | 106 | // return last shown position 107 | int64_t FrameQueue::GetBytePosOfLastFrame() { 108 | Frame *fp = &p_frames_[read_index_]; 109 | return read_index_shown_ && fp->serial_ == p_packet_queue_->GetSerial() 110 | ? fp->byte_pos_ 111 | : -1; 112 | } 113 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPlayer.xcodeproj/xcuserdata/RedaNezzar.xcuserdatad/xcschemes/MediaPlayer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 55 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 74 | 76 | 82 | 83 | 84 | 85 | 87 | 88 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /src/main/cpp/JniUtils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | #include "JniUtils.h" 27 | 28 | JNIEnv *GetJavaEnvironment(JavaVM *jvm, jboolean &didAttach) { 29 | JNIEnv *env = NULL; 30 | didAttach = false; 31 | if (jvm) { 32 | if (jvm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) { 33 | didAttach = true; 34 | jvm->AttachCurrentThreadAsDaemon((void **)&env, NULL); 35 | } 36 | } 37 | return env; 38 | } 39 | 40 | bool CJavaEnvironment::HasException() { 41 | return (p_environment ? (bool)p_environment->ExceptionCheck() : false); 42 | } 43 | 44 | bool CJavaEnvironment::ClearException() { 45 | if (p_environment ? p_environment->ExceptionCheck() : false) { 46 | p_environment->ExceptionClear(); 47 | return true; 48 | } 49 | return false; 50 | } 51 | 52 | /** 53 | * Check whether there is a pending exception and if so, log its string version 54 | * and return true, otherwise, i.e., if there is no exception, return false. 55 | */ 56 | bool CJavaEnvironment::ReportException() { 57 | if (p_environment) { 58 | jthrowable exc = p_environment->ExceptionOccurred(); 59 | if (exc) { 60 | p_environment->ExceptionClear(); // Clear current exception 61 | jclass cid = p_environment->FindClass("java/lang/Throwable"); 62 | if (!ClearException()) { 63 | jmethodID mid = 64 | p_environment->GetMethodID(cid, "toString", "()Ljava/lang/String;"); 65 | if (!ClearException()) { 66 | jstring jmsg = (jstring)p_environment->CallObjectMethod(exc, mid); 67 | if (!ClearException()) { 68 | char *pmsg = (char *)p_environment->GetStringUTFChars(jmsg, NULL); 69 | p_environment->ReleaseStringUTFChars(jmsg, pmsg); 70 | } 71 | } 72 | p_environment->DeleteLocalRef(cid); 73 | } 74 | p_environment->DeleteLocalRef(exc); 75 | return true; 76 | } 77 | } 78 | return false; 79 | } 80 | 81 | CJavaEnvironment::CJavaEnvironment(JavaVM *jvm) 82 | : attached(false), p_environment(NULL) { 83 | if (jvm) { 84 | p_environment = GetJavaEnvironment(jvm, attached); 85 | } 86 | } 87 | 88 | CJavaEnvironment::CJavaEnvironment(JNIEnv *env) : attached(false) { 89 | p_environment = env; 90 | } 91 | 92 | CJavaEnvironment::~CJavaEnvironment() { 93 | if (attached && p_environment) { 94 | JavaVM *jvm; 95 | if (p_environment->GetJavaVM(&jvm) == JNI_OK) { 96 | jvm->DetachCurrentThread(); 97 | } 98 | } 99 | } 100 | 101 | JNIEnv *CJavaEnvironment::GetEnvironment() { return p_environment; } 102 | -------------------------------------------------------------------------------- /src/main/cpp/PacketQueue.cpp: -------------------------------------------------------------------------------- 1 | #include "PacketQueue.h" 2 | 3 | int PacketQueue::_Put(AVPacket *p_packet) { 4 | MyAVPacketList *pkt1; 5 | 6 | if (is_abort_requested_) { 7 | return -1; 8 | } 9 | 10 | pkt1 = (struct MyAVPacketList *)av_malloc(sizeof(MyAVPacketList)); 11 | if (!pkt1) { 12 | return -1; 13 | } 14 | pkt1->packet_ = *p_packet; 15 | pkt1->p_next_ = NULL; 16 | 17 | // If we request a flush, then increase the serial to flush all dependent 18 | // queues 19 | if (p_packet == &flush_packet_) { 20 | serial_++; 21 | } 22 | 23 | pkt1->serial_ = serial_; 24 | 25 | if (!p_last_packet_) { 26 | p_first_packet_ = pkt1; 27 | } else { 28 | p_last_packet_->p_next_ = pkt1; 29 | } 30 | p_last_packet_ = pkt1; 31 | num_packets_++; 32 | size_ += pkt1->packet_.size + sizeof(*pkt1); 33 | duration_ += pkt1->packet_.duration; 34 | /* XXX: should duplicate packet data in DV case */ 35 | put_condition_ = true; 36 | condition_.notify_one(); 37 | return 0; 38 | } 39 | 40 | PacketQueue::PacketQueue() 41 | : is_abort_requested_(true), serial_(0), num_packets_(0), 42 | p_first_packet_(nullptr), p_last_packet_(nullptr), size_(0), duration_(0), 43 | put_condition_(false) { 44 | 45 | av_init_packet(&flush_packet_); 46 | flush_packet_.data = (uint8_t *)&flush_packet_; 47 | } 48 | 49 | void PacketQueue::Flush() { 50 | MyAVPacketList *pkt, *pkt1; 51 | 52 | std::unique_lock locker(mutex_); 53 | for (pkt = p_first_packet_; pkt; pkt = pkt1) { 54 | pkt1 = pkt->p_next_; 55 | av_packet_unref(&pkt->packet_); 56 | av_freep(&pkt); 57 | } 58 | p_last_packet_ = NULL; 59 | p_first_packet_ = NULL; 60 | num_packets_ = 0; 61 | size_ = 0; 62 | duration_ = 0; 63 | locker.unlock(); 64 | } 65 | 66 | void PacketQueue::Abort() { 67 | std::unique_lock locker(mutex_); 68 | 69 | is_abort_requested_ = true; 70 | 71 | put_condition_ = true; 72 | condition_.notify_one(); 73 | 74 | locker.unlock(); 75 | } 76 | 77 | void PacketQueue::Start() { 78 | std::unique_lock locker(mutex_); 79 | is_abort_requested_ = false; 80 | _Put(&flush_packet_); 81 | locker.unlock(); 82 | } 83 | 84 | int PacketQueue::Put(AVPacket *p_packet) { 85 | int ret; 86 | 87 | std::unique_lock locker(mutex_); 88 | ret = _Put(p_packet); 89 | locker.unlock(); 90 | 91 | if (p_packet != &flush_packet_ && ret < 0) { 92 | av_packet_unref(p_packet); 93 | } 94 | 95 | return ret; 96 | } 97 | 98 | int PacketQueue::PutNullPacket(int stream_index) { 99 | AVPacket pkt1, *pkt = &pkt1; 100 | av_init_packet(pkt); 101 | pkt->data = NULL; 102 | pkt->size = 0; 103 | pkt->stream_index = stream_index; 104 | return Put(pkt); 105 | } 106 | 107 | int PacketQueue::PutFlushPacket() { return Put(&flush_packet_); } 108 | 109 | /* return < 0 if aborted, 0 if no packet and > 0 if packet. */ 110 | int PacketQueue::Get(AVPacket *pkt, int block, int *serial) { 111 | MyAVPacketList *pkt1; 112 | int ret; 113 | 114 | std::unique_lock locker(mutex_); 115 | 116 | for (;;) { 117 | if (is_abort_requested_) { 118 | ret = -1; 119 | break; 120 | } 121 | 122 | pkt1 = p_first_packet_; 123 | if (pkt1) { 124 | p_first_packet_ = pkt1->p_next_; 125 | if (!p_first_packet_) { 126 | p_last_packet_ = NULL; 127 | } 128 | num_packets_--; 129 | size_ -= pkt1->packet_.size + sizeof(*pkt1); 130 | duration_ -= pkt1->packet_.duration; 131 | *pkt = pkt1->packet_; 132 | if (serial) { 133 | *serial = pkt1->serial_; 134 | } 135 | av_free(pkt1); 136 | ret = 1; 137 | break; 138 | } else if (!block) { 139 | ret = 0; 140 | break; 141 | } else { 142 | put_condition_ = false; 143 | condition_.wait(locker, [&] { return put_condition_; }); 144 | } 145 | } 146 | locker.unlock(); 147 | return ret; 148 | } 149 | -------------------------------------------------------------------------------- /src/main/cpp/FrameQueue.h: -------------------------------------------------------------------------------- 1 | #include "PacketQueue.h" 2 | #include 3 | #include 4 | 5 | extern "C" { 6 | #include // codecs 7 | } 8 | 9 | #ifndef FRAME_QUEUE_H_ 10 | #define FRAME_QUEUE_H_ 11 | 12 | // Common struct for handling decoded data and allocated buffers 13 | typedef struct Frame { 14 | AVFrame *p_frame_; 15 | int serial_; 16 | double pts_; // presentation timestamp for the frame 17 | double duration_; // estimated duration of the frame 18 | int64_t byte_pos_; // byte position of the frame in the input file 19 | int frame_pos_; // The Frame positin in the input file 20 | int width_; 21 | int height_; 22 | int format_; 23 | AVRational aspect_ratio_; 24 | bool is_uploaded_; 25 | } Frame; 26 | 27 | // Frame queue provides a container for frames that hold audio and image data 28 | // Notice that the typical size for the audio/image data differs 29 | // 30 | // I made the following changes to the original code 31 | // - removed the sub title 32 | // - replaced the SDL mutex/condition by the 33 | // std::mutex/std::conditional_variable 34 | // - changed the allocation of the queue from static to dymanic to support all 35 | // max_sizes 36 | // 37 | // Odities of the current API (per original code) 38 | // - Always call push and next to write/read a frame 39 | // - nb_remaining is the number of available frames to read 40 | // - Coupled to packet queue which can cause an abort and when the frame queue 41 | // is signaled returns nullptr 42 | // - Use peek_readable and peek_writable to get a read/write pointer (in most 43 | // cases) 44 | // - In rarer cases use peek, peek_next, and peek_last (see tests for examples 45 | // of the logic) 46 | // 47 | class FrameQueue { 48 | public: 49 | // Use this method to create a new frame queue to ensure cases where memory 50 | // allocation fails are handled properly 51 | static int CreateFrameQueue(FrameQueue **pp_frame_queue, 52 | const PacketQueue *p_packet_queue, int max_size, 53 | bool keep_last); 54 | 55 | virtual ~FrameQueue(); 56 | 57 | void Signal(); 58 | 59 | // Last shown frame 60 | inline void Peek(Frame **pp_frame) { 61 | *pp_frame = &p_frames_[(read_index_ + read_index_shown_) % max_size_]; 62 | } 63 | 64 | // Next to show frame 65 | inline void PeekNext(Frame **pp_frame) { 66 | *pp_frame = &p_frames_[(read_index_ + read_index_shown_ + 1) % max_size_]; 67 | } 68 | 69 | // Last read index 70 | inline void PeekLast(Frame **pp_frame) { 71 | *pp_frame = &p_frames_[read_index_]; 72 | } 73 | 74 | // Need to pass out a reference for the lock to work 75 | inline std::mutex &GetMutex() { return mutex_; } 76 | 77 | // True if this frame queue has shown a frame 78 | inline bool HasShownFrame() const { return read_index_shown_; } 79 | 80 | // Peek frame pointer to write to (Push will write) 81 | void PeekWritable(Frame **pp_frame); 82 | 83 | // Peek frame pointer to read from (Next will advance the pointer) 84 | void PeekReadable(Frame **pp_frame); 85 | 86 | void Push(); 87 | 88 | void Next(); 89 | 90 | // return the number of undisplayed frames in the queue 91 | inline int GetNumToDisplay() const { return size_ - read_index_shown_; } 92 | 93 | // return the byte position of the frame last shown 94 | int64_t GetBytePosOfLastFrame(); 95 | 96 | private: 97 | Frame *p_frames_; // container for the frames 98 | int read_index_; // read index 99 | int write_index_; // write index 100 | int size_; // size in bytes 101 | int max_size_; 102 | bool keep_last_; 103 | int read_index_shown_; // read index shown 104 | std::mutex mutex_; 105 | std::condition_variable condition_; 106 | const PacketQueue *p_packet_queue_; // packet queue 107 | 108 | static void unref_item(Frame *vp) { av_frame_unref(vp->p_frame_); } 109 | 110 | FrameQueue(const PacketQueue *pktq, int max_size, 111 | bool keep_last); // private because of memory management 112 | }; 113 | 114 | #endif FRAME_QUEUE_H_ 115 | -------------------------------------------------------------------------------- /src/main/cpp/Pipeline.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software; you can redistribute it and/or modify it 6 | * under the terms of the GNU General Public License version 2 only, as 7 | * published by the Free Software Foundation. Oracle designates this 8 | * particular file as subject to the "Classpath" exception as provided 9 | * by Oracle in the LICENSE file that accompanied this code. 10 | * 11 | * This code is distributed in the hope that it will be useful, but WITHOUT 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 | * version 2 for more details (a copy is included in the LICENSE file that 15 | * accompanied this code). 16 | * 17 | * You should have received a copy of the GNU General Public License version 18 | * 2 along with this work; if not, write to the Free Software Foundation, 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 | * 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 | * or visit www.oracle.com if you need additional information or have any 23 | * questions. 24 | */ 25 | 26 | #ifndef _PIPELINE_H_ 27 | #define _PIPELINE_H_ 28 | 29 | #include "AudioVideoFormats.h" 30 | #include "PipelineOptions.h" 31 | #include "PlayerState.h" 32 | #include 33 | #include 34 | 35 | extern "C" { 36 | #ifdef SDL_ENABLED 37 | #include 38 | #endif // SDL_ENABLED 39 | } 40 | 41 | class CMedia; 42 | class CJavaPlayerEventDispatcher; 43 | 44 | // class CPipeline 45 | // 46 | // Underlying object that interfaces the JNI layer to the actual media engine 47 | class CPipeline { 48 | public: 49 | CPipeline(CPipelineOptions *p_options = NULL); 50 | virtual ~CPipeline(); 51 | 52 | void SetEventDispatcher(CJavaPlayerEventDispatcher *p_event_dispatcher); 53 | 54 | virtual uint32_t Init(const char *filename) = 0; 55 | virtual void Dispose(); 56 | 57 | virtual uint32_t Play() = 0; 58 | virtual uint32_t Stop() = 0; 59 | virtual uint32_t Pause() = 0; 60 | virtual uint32_t StepForward() = 0; 61 | virtual uint32_t StepBackward() = 0; 62 | virtual uint32_t Finish() = 0; 63 | 64 | virtual uint32_t Seek(double dSeekTime) = 0; 65 | 66 | virtual uint32_t GetDuration(double *pdDuration) = 0; 67 | virtual uint32_t GetStreamTime(double *pdStreamTime) = 0; 68 | virtual uint32_t GetFps(double *pdFps) = 0; 69 | virtual uint32_t GetImageWidth(int *iWidth) const = 0; 70 | virtual uint32_t GetImageHeight(int *iheight) const = 0; 71 | 72 | virtual uint32_t SetRate(float fRate) = 0; 73 | virtual uint32_t GetRate(float *pfRate) = 0; 74 | 75 | virtual uint32_t SetVolume(float fVolume) = 0; 76 | virtual uint32_t GetVolume(float *pfVolume) = 0; 77 | 78 | virtual uint32_t SetBalance(float fBalance) = 0; 79 | virtual uint32_t GetBalance(float *pfBalance) = 0; 80 | 81 | virtual uint32_t SetAudioSyncDelay(long lMillis) = 0; 82 | virtual uint32_t GetAudioSyncDelay(long *plMillis) = 0; 83 | 84 | #ifdef SDL_ENABLED 85 | virtual uint32_t GetWindowWidth(int *p_width) const = 0; 86 | virtual uint32_t GetWindowHeight(int *p_height) const = 0; 87 | virtual uint32_t SetWindowSize(int width, int height) = 0; 88 | 89 | virtual uint32_t ShowWindow() = 0; 90 | virtual uint32_t HideWindow() = 0; 91 | virtual uint32_t IsVisible(int *isVisible) const = 0; 92 | #endif 93 | 94 | protected: 95 | CJavaPlayerEventDispatcher *p_event_dispatcher_; 96 | CPipelineOptions *p_options_; 97 | PlayerState::State player_state_; 98 | PlayerState::State 99 | player_pending_state_; // This is necessary to get from stalled 100 | // into the next correct state 101 | 102 | bool IsPlayerState(PlayerState::State state); 103 | void SetPendingPlayerState(); 104 | void UpdatePlayerState(PlayerState::State new_state); 105 | void SetPlayerState(PlayerState::State new_state, bool silent); 106 | #ifdef SDL_ENABLED 107 | void MapSdlToJavaKey(SDL_Keycode sdlkeyCode); 108 | void DispatchKeyEvent(int javaKeyCode); 109 | #endif // SDL_ENABLED 110 | }; 111 | 112 | #endif //_PIPELINE_H_ 113 | -------------------------------------------------------------------------------- /src/test/java/org/datavyu/plugins/ffmpeg/MediaInformation.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins.ffmpeg; 2 | 3 | import java.net.URLConnection; 4 | import org.apache.commons.io.FileUtils; 5 | import org.apache.logging.log4j.Level; 6 | import org.apache.logging.log4j.LogManager; 7 | import org.apache.logging.log4j.Logger; 8 | import org.apache.logging.log4j.core.config.Configurator; 9 | 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.net.URI; 13 | import java.net.URL; 14 | import java.util.Optional; 15 | 16 | public class MediaInformation { 17 | private static final String RESOURCE_NAME = "resources"; 18 | private static final String RESOURCE_DIR = System.getProperty("user.home"); // 19 | private static final String LOCAL_RESOURCE_DIR = createLocalResourcePath(RESOURCE_NAME); 20 | private static final Logger LOGGER = LogManager.getFormatterLogger(MediaInformation.class); 21 | 22 | static { 23 | Configurator.setRootLevel(Level.DEBUG); 24 | } 25 | 26 | MediaInformation( 27 | URI localPath, 28 | double startTime, 29 | double duration, 30 | int imageWidth, 31 | int imageHeight, 32 | double framesPerSecond) { 33 | this.localPath = localPath; 34 | this.startTime = startTime; 35 | this.duration = duration; 36 | this.imageWidth = imageWidth; 37 | this.imageHeight = imageHeight; 38 | this.framesPerSecond = framesPerSecond; 39 | } 40 | 41 | public static Optional create( 42 | String remoteName, 43 | double startTime, 44 | double duration, 45 | int width, 46 | int height, 47 | double framesPerSecond) { 48 | try { 49 | return Optional.of( 50 | new MediaInformation( 51 | new File(copyToLocal(LOCAL_RESOURCE_DIR, new URL(remoteName))).toURI(), 52 | startTime, 53 | duration, 54 | width, 55 | height, 56 | framesPerSecond)); 57 | } catch (IOException e) { 58 | LOGGER.error(e); 59 | } 60 | return Optional.empty(); 61 | } 62 | 63 | private URI localPath; 64 | private double startTime; 65 | private double duration; 66 | private int imageWidth; 67 | private int imageHeight; 68 | private double framesPerSecond; 69 | 70 | public URI getLocalPath() { 71 | return localPath; 72 | } 73 | 74 | public double getStartTime() { 75 | return startTime; 76 | } 77 | 78 | public double getDuration() { 79 | return duration; 80 | } 81 | 82 | public int getImageWidth() { 83 | return imageWidth; 84 | } 85 | 86 | public int getImageHeight() { 87 | return imageHeight; 88 | } 89 | 90 | public double getFramesPerSecond() { 91 | return framesPerSecond; 92 | } 93 | 94 | /** 95 | * Copies the resource from the URL url to a local resource directory and returns while preserving 96 | * the original file name 97 | * 98 | * @param remoteUrl The URL to the resource 99 | * @return The file path to the copied resource locally 100 | * @throws IOException if the directory can't be created or the resource can't be downloaded 101 | */ 102 | private static String copyToLocal(String localResourceDir, URL remoteUrl) throws IOException { 103 | 104 | // Get the file name 105 | String fileName = new File(remoteUrl.toString()).getName(); 106 | 107 | // Define the output file url 108 | File outPath = new File(localResourceDir, fileName); 109 | 110 | // If the file does not exist yet copy it from the www 111 | if (!outPath.exists()) { 112 | URLConnection conn = remoteUrl.openConnection(); 113 | conn.setRequestProperty("User-Agent", ""); 114 | conn.connect(); 115 | FileUtils.copyInputStreamToFile(conn.getInputStream(), outPath); 116 | LOGGER.info("Copied resource from " + remoteUrl + " to " + outPath); 117 | } else { 118 | LOGGER.info("Found existing resource " + outPath); 119 | } 120 | return outPath.getAbsolutePath(); 121 | } 122 | 123 | private static String createLocalResourcePath(String resourceName) { 124 | try { 125 | File resourcePath = new File(RESOURCE_DIR + "/" + resourceName); 126 | FileUtils.forceMkdir(resourcePath); 127 | return resourcePath.getAbsolutePath(); 128 | } catch (IOException io) { 129 | LOGGER.error(io); 130 | } 131 | return "./"; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPlayer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2035 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MediaPlayer", "FFplay.vcxproj", "{6EA34670-B97C-440E-860D-3B5AF0BE87D8}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FfmpegJavaMediaPlayer", "FfmpegJavaMediaPlayer.vcxproj", "{C841902E-8956-4E65-9524-E5063AFBD1C2}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FfmpegSdlMediaPlayer", "FfmpegSdlMediaPlayer.vcxproj", "{C691A93F-CD1E-4FC6-A79C-22B2BD38BB0C}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VideoState", "VideoState.vcxitems", "{90F330AA-8E8C-4625-87CD-A321C52CB6E9}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MediaPlayerTest", "MediaPlayerTest.vcxproj", "{7209427C-2CB3-4110-B3DF-D932BBFEECDB}" 15 | EndProject 16 | Global 17 | GlobalSection(SharedMSBuildProjectFiles) = preSolution 18 | VideoState.vcxitems*{6ea34670-b97c-440e-860d-3b5af0be87d8}*SharedItemsImports = 4 19 | VideoState.vcxitems*{7209427c-2cb3-4110-b3df-d932bbfeecdb}*SharedItemsImports = 4 20 | VideoState.vcxitems*{90f330aa-8e8c-4625-87cd-a321c52cb6e9}*SharedItemsImports = 9 21 | VideoState.vcxitems*{c691a93f-cd1e-4fc6-a79c-22b2bd38bb0c}*SharedItemsImports = 4 22 | VideoState.vcxitems*{c841902e-8956-4e65-9524-e5063afbd1c2}*SharedItemsImports = 4 23 | EndGlobalSection 24 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 25 | Debug|x64 = Debug|x64 26 | Debug|x86 = Debug|x86 27 | Release|x64 = Release|x64 28 | Release|x86 = Release|x86 29 | EndGlobalSection 30 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 31 | {6EA34670-B97C-440E-860D-3B5AF0BE87D8}.Debug|x64.ActiveCfg = Debug|x64 32 | {6EA34670-B97C-440E-860D-3B5AF0BE87D8}.Debug|x64.Build.0 = Debug|x64 33 | {6EA34670-B97C-440E-860D-3B5AF0BE87D8}.Debug|x86.ActiveCfg = Debug|Win32 34 | {6EA34670-B97C-440E-860D-3B5AF0BE87D8}.Debug|x86.Build.0 = Debug|Win32 35 | {6EA34670-B97C-440E-860D-3B5AF0BE87D8}.Release|x64.ActiveCfg = Release|x64 36 | {6EA34670-B97C-440E-860D-3B5AF0BE87D8}.Release|x64.Build.0 = Release|x64 37 | {6EA34670-B97C-440E-860D-3B5AF0BE87D8}.Release|x86.ActiveCfg = Release|Win32 38 | {6EA34670-B97C-440E-860D-3B5AF0BE87D8}.Release|x86.Build.0 = Release|Win32 39 | {C841902E-8956-4E65-9524-E5063AFBD1C2}.Debug|x64.ActiveCfg = Debug|x64 40 | {C841902E-8956-4E65-9524-E5063AFBD1C2}.Debug|x64.Build.0 = Debug|x64 41 | {C841902E-8956-4E65-9524-E5063AFBD1C2}.Debug|x86.ActiveCfg = Debug|Win32 42 | {C841902E-8956-4E65-9524-E5063AFBD1C2}.Debug|x86.Build.0 = Debug|Win32 43 | {C841902E-8956-4E65-9524-E5063AFBD1C2}.Release|x64.ActiveCfg = Release|x64 44 | {C841902E-8956-4E65-9524-E5063AFBD1C2}.Release|x64.Build.0 = Release|x64 45 | {C841902E-8956-4E65-9524-E5063AFBD1C2}.Release|x86.ActiveCfg = Release|Win32 46 | {C841902E-8956-4E65-9524-E5063AFBD1C2}.Release|x86.Build.0 = Release|Win32 47 | {C691A93F-CD1E-4FC6-A79C-22B2BD38BB0C}.Debug|x64.ActiveCfg = Debug|x64 48 | {C691A93F-CD1E-4FC6-A79C-22B2BD38BB0C}.Debug|x64.Build.0 = Debug|x64 49 | {C691A93F-CD1E-4FC6-A79C-22B2BD38BB0C}.Debug|x86.ActiveCfg = Debug|Win32 50 | {C691A93F-CD1E-4FC6-A79C-22B2BD38BB0C}.Debug|x86.Build.0 = Debug|Win32 51 | {C691A93F-CD1E-4FC6-A79C-22B2BD38BB0C}.Release|x64.ActiveCfg = Release|x64 52 | {C691A93F-CD1E-4FC6-A79C-22B2BD38BB0C}.Release|x64.Build.0 = Release|x64 53 | {C691A93F-CD1E-4FC6-A79C-22B2BD38BB0C}.Release|x86.ActiveCfg = Release|Win32 54 | {C691A93F-CD1E-4FC6-A79C-22B2BD38BB0C}.Release|x86.Build.0 = Release|Win32 55 | {7209427C-2CB3-4110-B3DF-D932BBFEECDB}.Debug|x64.ActiveCfg = Debug|x64 56 | {7209427C-2CB3-4110-B3DF-D932BBFEECDB}.Debug|x64.Build.0 = Debug|x64 57 | {7209427C-2CB3-4110-B3DF-D932BBFEECDB}.Debug|x86.ActiveCfg = Debug|Win32 58 | {7209427C-2CB3-4110-B3DF-D932BBFEECDB}.Debug|x86.Build.0 = Debug|Win32 59 | {7209427C-2CB3-4110-B3DF-D932BBFEECDB}.Release|x64.ActiveCfg = Release|x64 60 | {7209427C-2CB3-4110-B3DF-D932BBFEECDB}.Release|x64.Build.0 = Release|x64 61 | {7209427C-2CB3-4110-B3DF-D932BBFEECDB}.Release|x86.ActiveCfg = Release|Win32 62 | {7209427C-2CB3-4110-B3DF-D932BBFEECDB}.Release|x86.Build.0 = Release|Win32 63 | EndGlobalSection 64 | GlobalSection(SolutionProperties) = preSolution 65 | HideSolutionNode = FALSE 66 | EndGlobalSection 67 | GlobalSection(ExtensibilityGlobals) = postSolution 68 | SolutionGuid = {8022637E-056C-45EF-8B7B-9B6CAE0C370D} 69 | EndGlobalSection 70 | EndGlobal 71 | -------------------------------------------------------------------------------- /src/main/cpp/Decoder.cpp: -------------------------------------------------------------------------------- 1 | #include "Decoder.h" 2 | 3 | Decoder::Decoder(AVCodecContext *avctx, PacketQueue *queue, 4 | std::condition_variable *empty_queue_cond) 5 | : p_codec_context_(avctx), p_packet_queue_(queue), 6 | p_is_empty_condition_(empty_queue_cond), serial_(-1), is_finished_(false), 7 | is_packet_pending_(false), do_reorder_(-1), start_pts_(AV_NOPTS_VALUE), 8 | start_pts_timebase_(av_make_q(0, 0)), next_pts_(0), 9 | next_pts_timebase_(av_make_q(0, 0)), p_decoder_thread_(nullptr) { 10 | // Note, that pkt will need to be initialized for the case when decode_frame 11 | // is never run Sidenote: the move ref code will clean this initialization 12 | av_init_packet(&packet_); 13 | } 14 | 15 | Decoder::~Decoder() { 16 | av_packet_unref(&packet_); 17 | // TODO(fraudies): Move initialization of codec context into Decoder from 18 | // VideoState 19 | avcodec_free_context(&p_codec_context_); 20 | } 21 | 22 | int Decoder::Decode(AVFrame *frame) { 23 | int ret = AVERROR(EAGAIN); 24 | 25 | for (;;) { 26 | AVPacket packet; 27 | 28 | if (p_packet_queue_->GetSerial() == serial_) { 29 | do { 30 | if (p_packet_queue_->IsAbortRequested()) 31 | return -1; 32 | 33 | switch (p_codec_context_->codec_type) { 34 | case AVMEDIA_TYPE_VIDEO: 35 | ret = avcodec_receive_frame(p_codec_context_, frame); 36 | if (ret >= 0) { 37 | if (do_reorder_ == -1) { 38 | frame->pts = frame->best_effort_timestamp; 39 | } else if (!do_reorder_) { 40 | frame->pts = frame->pkt_dts; 41 | } 42 | } 43 | break; 44 | case AVMEDIA_TYPE_AUDIO: 45 | ret = avcodec_receive_frame(p_codec_context_, frame); 46 | if (ret >= 0) { 47 | AVRational tb = av_make_q(1, frame->sample_rate); 48 | if (frame->pts != AV_NOPTS_VALUE) 49 | frame->pts = 50 | av_rescale_q(frame->pts, p_codec_context_->pkt_timebase, tb); 51 | else if (next_pts_ != AV_NOPTS_VALUE) 52 | frame->pts = av_rescale_q(next_pts_, next_pts_timebase_, tb); 53 | if (frame->pts != AV_NOPTS_VALUE) { 54 | next_pts_ = frame->pts + frame->nb_samples; 55 | next_pts_timebase_ = tb; 56 | } 57 | } 58 | break; 59 | } 60 | if (ret == AVERROR_EOF) { 61 | is_finished_ = serial_; 62 | avcodec_flush_buffers(p_codec_context_); 63 | return 0; 64 | } 65 | if (ret >= 0) { 66 | return 1; 67 | } 68 | } while (ret != AVERROR(EAGAIN)); 69 | } 70 | 71 | do { 72 | if (p_packet_queue_->getNumberOfPackets() == 0) 73 | p_is_empty_condition_->notify_one(); 74 | if (is_packet_pending_) { 75 | av_packet_move_ref(&packet, &packet_); 76 | is_packet_pending_ = false; 77 | } else { 78 | if (p_packet_queue_->Get(&packet, 1, &serial_) < 0) 79 | return -1; 80 | } 81 | } while (p_packet_queue_->GetSerial() != serial_); 82 | 83 | if (p_packet_queue_->IsFlushPacket(packet)) { 84 | avcodec_flush_buffers(p_codec_context_); 85 | is_finished_ = 0; 86 | next_pts_ = start_pts_; 87 | next_pts_timebase_ = start_pts_timebase_; 88 | } else { 89 | if (p_codec_context_->codec_type != AVMEDIA_TYPE_SUBTITLE && 90 | avcodec_send_packet(p_codec_context_, &packet) == AVERROR(EAGAIN)) { 91 | av_log(p_codec_context_, AV_LOG_ERROR, 92 | "Receive_frame and send_packet both returned EAGAIN, which is " 93 | "an API violation.\n"); 94 | is_packet_pending_ = true; 95 | av_packet_move_ref(&packet_, &packet); 96 | } 97 | av_packet_unref(&packet); 98 | } 99 | } 100 | } 101 | 102 | int Decoder::Start(const std::function &decoding) { 103 | p_packet_queue_->Start(); 104 | p_decoder_thread_ = new std::thread([decoding] { decoding(); }); 105 | if (!p_decoder_thread_) { 106 | av_log(NULL, AV_LOG_ERROR, "Can't create thread"); 107 | return AVERROR(ENOMEM); 108 | } 109 | return 0; 110 | } 111 | 112 | void Decoder::Stop(FrameQueue *frame_queue) { 113 | // TODO(fraudies): Cleanup this design by keeping frame queue and packet queue 114 | // together 115 | p_packet_queue_->Abort(); 116 | frame_queue->Signal(); 117 | // Take care of the case when we never called start 118 | if (p_decoder_thread_) { 119 | p_decoder_thread_->join(); 120 | delete p_decoder_thread_; 121 | p_decoder_thread_ = nullptr; 122 | } 123 | p_packet_queue_->Flush(); 124 | } 125 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegErrorUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "FfmpegErrorUtils.h" 2 | #include "MediaPlayerErrors.h" 3 | #include 4 | 5 | #define __STDC_CONSTANT_MACROS 6 | #define inline __inline 7 | 8 | #ifndef INT64_C 9 | #define INT64_C(c) (c##LL) 10 | #define UINT64_C(c) (c##ULL) 11 | #endif 12 | 13 | extern "C" { 14 | #include "libavutil/common.h" 15 | #include "libavutil/error.h" 16 | } 17 | 18 | int FfmpegToJavaErrNo(int ffmpegErrNo) { 19 | int err = AVERROR(EINVAL); 20 | if (ffmpegErrNo == err) { 21 | std::cout << "EINVAL error" << std::endl; 22 | } 23 | 24 | switch (ffmpegErrNo) { 25 | case ERROR_NONE: 26 | return ERROR_NONE; 27 | // Map ffmpeg internal errors 28 | case AVERROR_BSF_NOT_FOUND: 29 | return ERROR_FFMPEG_BSF_NOT_FOUND; 30 | case AVERROR_BUG: 31 | return ERROR_FFMPEG_BUG; 32 | case AVERROR_BUFFER_TOO_SMALL: 33 | return ERROR_FFMPEG_BUFFER_TOO_SMALL; 34 | case AVERROR_DECODER_NOT_FOUND: 35 | return ERROR_FFMPEG_DECODER_NOT_FOUND; 36 | case AVERROR_DEMUXER_NOT_FOUND: 37 | return ERROR_FFMPEG_DEMUXER_NOT_FOUND; 38 | case AVERROR_ENCODER_NOT_FOUND: 39 | return ERROR_FFMPEG_ENCODER_NOT_FOUND; 40 | case AVERROR_EOF: 41 | return ERROR_FFMPEG_EOF; 42 | case AVERROR_EXIT: 43 | return ERROR_FFMPEG_EXIT; 44 | case AVERROR_EXTERNAL: 45 | return ERROR_FFMPEG_EXTERNAL; 46 | case AVERROR_FILTER_NOT_FOUND: 47 | return ERROR_FFMPEG_FILTER_NOT_FOUND; 48 | case AVERROR_INVALIDDATA: 49 | return ERROR_FFMPEG_INVALIDDATA; 50 | case AVERROR_MUXER_NOT_FOUND: 51 | return ERROR_FFMPEG_MUXER_NOT_FOUND; 52 | case AVERROR_OPTION_NOT_FOUND: 53 | return ERROR_FFMPEG_OPTION_NOT_FOUND; 54 | case AVERROR_PATCHWELCOME: 55 | return ERROR_FFMPEG_PATCHWELCOME; 56 | case AVERROR_PROTOCOL_NOT_FOUND: 57 | return ERROR_FFMPEG_PROTOCOL_NOT_FOUND; 58 | case AVERROR_STREAM_NOT_FOUND: 59 | return ERROR_FFMPEG_STREAM_NOT_FOUND; 60 | case AVERROR_BUG2: 61 | return ERROR_FFMPEG_BUG2; 62 | case AVERROR_EXPERIMENTAL: 63 | return ERROR_FFMPEG_EXTERNAL; 64 | case AVERROR_INPUT_CHANGED: 65 | return ERROR_FFMPEG_INPUT_CHANGED; 66 | case AVERROR_OUTPUT_CHANGED: 67 | return ERROR_FFMPEG_OUTPUT_CHANGED; 68 | case AVERROR_HTTP_BAD_REQUEST: 69 | return ERROR_FFMPEG_HTTP_BAD_REQUEST; 70 | case AVERROR_HTTP_UNAUTHORIZED: 71 | return ERROR_FFMPEG_HTTP_UNAUTHORIZED; 72 | case AVERROR_HTTP_FORBIDDEN: 73 | return ERROR_FFMPEG_HTTP_FORBIDDEN; 74 | case AVERROR_HTTP_NOT_FOUND: 75 | return ERROR_FFMPEG_HTTP_NOT_FOUND; 76 | case AVERROR_HTTP_OTHER_4XX: 77 | return ERROR_FFMPEG_HTTP_OTHER_4XX; 78 | case AVERROR_HTTP_SERVER_ERROR: 79 | return ERROR_FFMPEG_HTTP_SERVER_ERROR; 80 | // Map system errors used by ffmpeg 81 | case AVERROR(EPERM): 82 | return ERROR_SYSTEM_EPERM; 83 | case AVERROR(ENOENT): 84 | return ERROR_SYSTEM_ENOENT; 85 | case AVERROR(ESRCH): 86 | return ERROR_SYSTEM_ESRCH; 87 | case AVERROR(EINTR): 88 | return ERROR_SYSTEM_EINTR; 89 | case AVERROR(EIO): 90 | return ERROR_SYSTEM_EIO; 91 | case AVERROR(ENXIO): 92 | return ERROR_SYSTEM_ENXIO; 93 | case AVERROR(E2BIG): 94 | return ERROR_SYSTEM_E2BIG; 95 | case AVERROR(ENOEXEC): 96 | return ERROR_SYSTEM_ENOEXEC; 97 | case AVERROR(EBADF): 98 | return ERROR_SYSTEM_EBADF; 99 | case AVERROR(ECHILD): 100 | return ERROR_SYSTEM_ECHILD; 101 | case AVERROR(EAGAIN): 102 | return ERROR_SYSTEM_EAGAIN; 103 | case AVERROR(ENOMEM): 104 | return ERROR_SYSTEM_ENOMEM; 105 | case AVERROR(EACCES): 106 | return ERROR_SYSTEM_EACCES; 107 | case AVERROR(EFAULT): 108 | return ERROR_SYSTEM_EFAULT; 109 | case AVERROR(EBUSY): 110 | return ERROR_SYSTEM_EBUSY; 111 | case AVERROR(EEXIST): 112 | return ERROR_SYSTEM_EEXIST; 113 | case AVERROR(EXDEV): 114 | return ERROR_SYSTEM_EXDEV; 115 | case AVERROR(ENODEV): 116 | return ERROR_SYSTEM_ENODEV; 117 | case AVERROR(ENOTDIR): 118 | return ERROR_SYSTEM_ENOTDIR; 119 | case AVERROR(EISDIR): 120 | return ERROR_SYSTEM_EISDIR; 121 | case AVERROR(EINVAL): 122 | return ERROR_SYSTEM_EINVAL; 123 | case AVERROR(ENFILE): 124 | return ERROR_SYSTEM_ENFILE; 125 | case AVERROR(EMFILE): 126 | return ERROR_SYSTEM_EMFILE; 127 | case AVERROR(ENOTTY): 128 | return ERROR_SYSTEM_ENOTTY; 129 | case AVERROR(EFBIG): 130 | return ERROR_SYSTEM_EFBIG; 131 | case AVERROR(ENOSPC): 132 | return ERROR_SYSTEM_ENOSPC; 133 | case AVERROR(ESPIPE): 134 | return ERROR_SYSTEM_ESPIPE; 135 | case AVERROR(EROFS): 136 | return ERROR_SYSTEM_EROFS; 137 | case AVERROR(EMLINK): 138 | return ERROR_SYSTEM_EMLINK; 139 | case AVERROR(EPIPE): 140 | return ERROR_SYSTEM_EPIPE; 141 | case AVERROR(EDOM): 142 | return ERROR_SYSTEM_EDOM; 143 | case AVERROR(ERANGE): 144 | return ERROR_SYSTEM_ERANGE; 145 | case AVERROR(EDEADLK): 146 | return ERROR_SYSTEM_EDEADLK; 147 | case AVERROR(ENAMETOOLONG): 148 | return ERROR_SYSTEM_ENAMETOOLONG; 149 | case AVERROR(ENOLCK): 150 | return ERROR_SYSTEM_ENOLCK; 151 | case AVERROR(ENOSYS): 152 | return ERROR_SYSTEM_ENOSYS; 153 | case AVERROR(ENOTEMPTY): 154 | return ERROR_SYSTEM_ENOTEMPTY; 155 | } 156 | return ERROR_FFMPEG_UNKNOWN; 157 | } 158 | -------------------------------------------------------------------------------- /src/test/java/org/datavyu/plugins/ffmpeg/FfmpegJavaMediaPlayerTest.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins.ffmpeg; 2 | 3 | import java.awt.Container; 4 | import javax.swing.JDialog; 5 | import org.apache.logging.log4j.LogManager; 6 | import org.apache.logging.log4j.Logger; 7 | import org.datavyu.plugins.MediaException; 8 | import org.datavyu.plugins.MediaPlayer; 9 | import org.testng.annotations.DataProvider; 10 | import org.testng.annotations.Test; 11 | 12 | /** Tests the ffmpeg player using an AWT window for display */ 13 | public class FfmpegJavaMediaPlayerTest extends MediaPlayerTest { 14 | private static final Logger logger = LogManager.getFormatterLogger(FfmpegJavaMediaPlayerTest.class); 15 | 16 | public static class FfmpegBuilder implements Builder { 17 | private MediaInformation mediaInformation; 18 | private Container container; 19 | 20 | FfmpegBuilder() {} 21 | 22 | FfmpegBuilder withMedia(MediaInformation mediaInformation) { 23 | this.mediaInformation = mediaInformation; 24 | return this; 25 | } 26 | 27 | FfmpegBuilder withContainer(Container container) { 28 | this.container = container; 29 | return this; 30 | } 31 | 32 | @Override 33 | public MediaPlayerSync build() { 34 | MediaPlayer mediaPlayer = 35 | new FfmpegJavaMediaPlayer(mediaInformation.getLocalPath(), container); 36 | return MediaPlayerSync.createMediaPlayerSync(mediaPlayer); 37 | } 38 | } 39 | 40 | @DataProvider(name = "shortMedia") 41 | public Object[][] createPlayerWithShortMedia() { 42 | return new Object[][] { 43 | {new FfmpegBuilder().withMedia(SHORT_MEDIA).withContainer(new JDialog()), SHORT_MEDIA} 44 | }; 45 | } 46 | 47 | @DataProvider(name = "longMedia") 48 | public Object[][] createPlayerWithLongMedia() { 49 | return new Object[][] { 50 | {new FfmpegBuilder().withMedia(LONG_MEDIA).withContainer(new JDialog()), LONG_MEDIA} 51 | }; 52 | } 53 | 54 | @DataProvider(name = "wrongMedia") 55 | public Object[][] createPlayerWithWrongMedia() { 56 | return new Object[][] { 57 | {new FfmpegBuilder().withMedia(WRONG_MEDIA).withContainer(new JDialog()), WRONG_MEDIA} 58 | }; 59 | } 60 | 61 | @Test(dataProvider = "shortMedia") 62 | public void testReadyState(Builder builder, MediaInformation mediaInformation) { 63 | logger.debug("******** Test Ready State ********"); 64 | super.testReadyState(builder, mediaInformation); 65 | } 66 | 67 | @Test(dataProvider = "shortMedia") 68 | public void testPlayingState(Builder builder, MediaInformation mediaInformation) { 69 | logger.debug("******** Test Playing State ********"); 70 | super.testPlayingState(builder, mediaInformation); 71 | } 72 | 73 | @Test(dataProvider = "shortMedia") 74 | public void testStoppedState(Builder builder, MediaInformation mediaInformation) { 75 | logger.debug("******** Test Stopped State ********"); 76 | super.testStoppedState(builder, mediaInformation); 77 | } 78 | 79 | @Test(dataProvider = "shortMedia") 80 | public void testPausedState(Builder builder, MediaInformation mediaInformation) { 81 | logger.debug("******** Test Paused State ********"); 82 | super.testPausedState(builder, mediaInformation); 83 | } 84 | 85 | @Test(dataProvider = "shortMedia") 86 | public void testMetadata(Builder builder, MediaInformation mediaInformation) { 87 | super.testMetadata(builder, mediaInformation); 88 | } 89 | 90 | @Test(dataProvider = "wrongMedia", expectedExceptions = MediaException.class) 91 | public void testWrongFilename(Builder builder, MediaInformation mediaInformation) { 92 | super.testWrongFile(builder, mediaInformation); 93 | } 94 | 95 | @Test(dataProvider = "shortMedia") 96 | public void testTimeAtStart(Builder builder, MediaInformation mediaInformation) { 97 | super.testTimeAtStart(builder, mediaInformation); 98 | } 99 | 100 | @Test(dataProvider = "shortMedia") 101 | public void testSeek(Builder builder, MediaInformation mediaInformation) { 102 | super.testSeek(builder, mediaInformation); 103 | } 104 | 105 | @Test(dataProvider = "shortMedia") 106 | public void testSeekAtStart(Builder builder, MediaInformation mediaInformation) { 107 | super.testSeekAtStart(builder, mediaInformation); 108 | } 109 | 110 | @Test(dataProvider = "shortMedia") 111 | public void testStepForward(Builder builder, MediaInformation mediaInformation) { 112 | super.testStepForward(builder, mediaInformation); 113 | } 114 | 115 | @Test(dataProvider = "shortMedia") 116 | public void testStepForwardAtEnd(Builder builder, MediaInformation mediaInformation) { 117 | super.testStepForwardAtEnd(builder, mediaInformation); 118 | } 119 | 120 | @Test(dataProvider = "shortMedia") 121 | public void testStepBackward(Builder builder, MediaInformation mediaInformation) { 122 | super.testStepBackward(builder, mediaInformation); 123 | } 124 | 125 | @Test(dataProvider = "shortMedia") 126 | public void testStepBackwardAtStart(Builder builder, MediaInformation mediaInformation) { 127 | super.testStepBackwardAtStart(builder, mediaInformation); 128 | } 129 | 130 | @Test(dataProvider = "longMedia") 131 | public void testRates(Builder builder, MediaInformation mediaInformation) { 132 | super.testRates(builder, mediaInformation); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/main/cpp/FfmpegSdlMediaPlayer.xcodeproj/xcshareddata/xcschemes/MediaPlayerWorkspace.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 65 | 66 | 67 | 68 | 70 | 76 | 77 | 78 | 79 | 80 | 90 | 92 | 98 | 99 | 100 | 101 | 107 | 108 | 114 | 115 | 116 | 117 | 119 | 120 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/PlaybackRateController.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class PlaybackRateController { 7 | 8 | // Defines the rate symbols with mapping to the float value 9 | public enum Rate { 10 | UNKNOWN(Float.NaN), 11 | MINUS_32(-32f), 12 | MINUS_16(-16f), 13 | MINUS_8(-8f), 14 | MINUS_4(-4f), 15 | MINUS_2(-2f), 16 | MINUS_1(-1f), 17 | MINUS_1_DIV_2(-1f / 2f), 18 | MINUS_1_DIV_4(-1f / 4f), 19 | MINUS_1_DIV_8(-1f / 8f), 20 | MINUS_1_DIV_16(-1f / 16f), 21 | MINUS_1_DIV_32(-1f / 32f), 22 | ZERO(+0f), 23 | PLUS_1_DIV_32(+1f / 32f), 24 | PLUS_1_DIV_16(+1f / 16f), 25 | PLUS_1_DIV_8(+1f / 8f), 26 | PLUS_1_DIV_4(+1f / 4f), 27 | PLUS_1_DIV_2(+1f / 2f), 28 | PLUS_1(+1f), 29 | PLUS_2(+2f), 30 | PLUS_4(+4f), 31 | PLUS_8(+8f), 32 | PLUS_16(+16f), 33 | PLUS_32(+32f); 34 | 35 | Rate(float value) { 36 | this.value = value; 37 | } 38 | 39 | private final float value; 40 | 41 | private static final Map VALUE_TO_RATE = 42 | new HashMap() { 43 | { 44 | put(MINUS_32.getValue(), MINUS_32); 45 | put(MINUS_16.getValue(), MINUS_16); 46 | put(MINUS_8.getValue(), MINUS_8); 47 | put(MINUS_4.getValue(), MINUS_4); 48 | put(MINUS_2.getValue(), MINUS_2); 49 | put(MINUS_1.getValue(), MINUS_1); 50 | put(MINUS_1_DIV_2.getValue(), MINUS_1_DIV_2); 51 | put(MINUS_1_DIV_4.getValue(), MINUS_1_DIV_4); 52 | put(MINUS_1_DIV_8.getValue(), MINUS_1_DIV_8); 53 | put(MINUS_1_DIV_16.getValue(), MINUS_1_DIV_16); 54 | put(MINUS_1_DIV_32.getValue(), MINUS_1_DIV_32); 55 | put(ZERO.getValue(), ZERO); 56 | put(PLUS_1_DIV_32.getValue(), PLUS_1_DIV_32); 57 | put(PLUS_1_DIV_16.getValue(), PLUS_1_DIV_16); 58 | put(PLUS_1_DIV_8.getValue(), PLUS_1_DIV_8); 59 | put(PLUS_1_DIV_4.getValue(), PLUS_1_DIV_4); 60 | put(PLUS_1_DIV_2.getValue(), PLUS_1_DIV_2); 61 | put(PLUS_1.getValue(), PLUS_1); 62 | put(PLUS_2.getValue(), PLUS_2); 63 | put(PLUS_4.getValue(), PLUS_4); 64 | put(PLUS_8.getValue(), PLUS_8); 65 | put(PLUS_16.getValue(), PLUS_16); 66 | put(PLUS_32.getValue(), PLUS_32); 67 | } 68 | }; 69 | 70 | // Maps to next upper rate 71 | private static final Map NEXT_UPPER = 72 | new HashMap() { 73 | { 74 | put(MINUS_32, MINUS_16); 75 | put(MINUS_16, MINUS_8); 76 | put(MINUS_8, MINUS_4); 77 | put(MINUS_4, MINUS_2); 78 | put(MINUS_2, MINUS_1); 79 | put(MINUS_1, MINUS_1_DIV_2); 80 | put(MINUS_1_DIV_2, MINUS_1_DIV_4); 81 | put(MINUS_1_DIV_4, MINUS_1_DIV_8); 82 | put(MINUS_1_DIV_8, MINUS_1_DIV_16); 83 | put(MINUS_1_DIV_16, MINUS_1_DIV_32); 84 | put(MINUS_1_DIV_32, ZERO); 85 | put(ZERO, PLUS_1_DIV_32); 86 | put(PLUS_1_DIV_32, PLUS_1_DIV_16); 87 | put(PLUS_1_DIV_16, PLUS_1_DIV_8); 88 | put(PLUS_1_DIV_8, PLUS_1_DIV_4); 89 | put(PLUS_1_DIV_4, PLUS_1_DIV_2); 90 | put(PLUS_1_DIV_2, PLUS_1); 91 | put(PLUS_1, PLUS_2); 92 | put(PLUS_2, PLUS_4); 93 | put(PLUS_4, PLUS_8); 94 | put(PLUS_8, PLUS_16); 95 | put(PLUS_16, PLUS_32); 96 | put(PLUS_32, UNKNOWN); 97 | } 98 | }; 99 | 100 | // Maps to the next lower rate 101 | private static final Map NEXT_LOWER = 102 | new HashMap() { 103 | { 104 | put(MINUS_32, UNKNOWN); 105 | put(MINUS_16, MINUS_32); 106 | put(MINUS_8, MINUS_16); 107 | put(MINUS_4, MINUS_8); 108 | put(MINUS_2, MINUS_4); 109 | put(MINUS_1, MINUS_2); 110 | put(MINUS_1_DIV_2, MINUS_1); 111 | put(MINUS_1_DIV_4, MINUS_1_DIV_2); 112 | put(MINUS_1_DIV_8, MINUS_1_DIV_4); 113 | put(MINUS_1_DIV_16, MINUS_1_DIV_8); 114 | put(MINUS_1_DIV_32, MINUS_1_DIV_16); 115 | put(ZERO, MINUS_1_DIV_32); 116 | put(PLUS_1_DIV_32, ZERO); 117 | put(PLUS_1_DIV_16, PLUS_1_DIV_32); 118 | put(PLUS_1_DIV_8, PLUS_1_DIV_16); 119 | put(PLUS_1_DIV_4, PLUS_1_DIV_8); 120 | put(PLUS_1_DIV_2, PLUS_1_DIV_4); 121 | put(PLUS_1, PLUS_1_DIV_2); 122 | put(PLUS_2, PLUS_1); 123 | put(PLUS_4, PLUS_2); 124 | put(PLUS_8, PLUS_4); 125 | put(PLUS_16, PLUS_8); 126 | put(PLUS_32, PLUS_16); 127 | } 128 | }; 129 | 130 | public static Rate getRate(Float value) { 131 | return VALUE_TO_RATE.get(value); 132 | } 133 | 134 | public Rate getNextLower() { 135 | Rate next = NEXT_LOWER.get(this); 136 | return next == UNKNOWN ? this : next; 137 | } 138 | 139 | public Rate getNextUpper() { 140 | Rate next = NEXT_UPPER.get(this); 141 | return next == UNKNOWN ? this : next; 142 | } 143 | 144 | public Float getValue() { 145 | return value; 146 | } 147 | } 148 | 149 | public static Float stepToFaster(float value) { 150 | return Rate.getRate(value).getNextUpper().getValue(); 151 | } 152 | 153 | public static Float stepToSlower(float value) { 154 | return Rate.getRate(value).getNextLower().getValue(); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/DatavyuMediaPlayer.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins; 2 | 3 | import org.datavyu.util.LibraryLoader; 4 | 5 | import java.net.URI; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.ListIterator; 9 | 10 | public abstract class DatavyuMediaPlayer extends NativeMediaPlayer implements MediaPlayerWindow { 11 | 12 | protected float mutedVolume = 1.0f; // last volume before mute 13 | protected boolean muteEnabled = false; 14 | 15 | /** Library dependencies for ffmpeg */ 16 | protected static final List FFMPEG_DEPENDENCIES = 17 | new ArrayList() { 18 | { 19 | add(new LibraryLoader.LibraryDependency("avutil", "56")); 20 | add(new LibraryLoader.LibraryDependency("swscale", "5")); 21 | add(new LibraryLoader.LibraryDependency("swresample", "3")); 22 | add(new LibraryLoader.LibraryDependency("avcodec", "58")); 23 | add(new LibraryLoader.LibraryDependency("avformat", "58")); 24 | add(new LibraryLoader.LibraryDependency("avfilter", "7")); 25 | add(new LibraryLoader.LibraryDependency("avdevice", "58")); 26 | add(new LibraryLoader.LibraryDependency("postproc", "55")); 27 | } 28 | }; 29 | 30 | protected DatavyuMediaPlayer(URI mediaPath) { 31 | super(mediaPath); 32 | } 33 | 34 | protected void throwMediaErrorException(int code, Throwable cause) throws MediaException { 35 | MediaError me = MediaError.getFromCode(code); 36 | throw new MediaException(me.description(), cause, me); 37 | } 38 | 39 | @Override 40 | protected boolean playerGetMute() throws MediaException { 41 | return muteEnabled; 42 | } 43 | 44 | @Override 45 | protected synchronized void playerSetMute(boolean enable) throws MediaException { 46 | if (enable != muteEnabled) { 47 | if (enable) { 48 | // Cache the current volume. 49 | float currentVolume = getVolume(); 50 | 51 | // Set the volume to zero. 52 | playerSetVolume(0); 53 | 54 | // Set the mute flag. It is necessary to do this after 55 | // calling setVolume() as otherwise the volume will not 56 | // be set to zero. 57 | muteEnabled = true; 58 | 59 | // Save the pre-mute volume. 60 | mutedVolume = currentVolume; 61 | } else { 62 | // Unset the mute flag. It is necessary to do this before 63 | // calling setVolume() as otherwise the volume will not 64 | // be set to the cached value. 65 | muteEnabled = false; 66 | 67 | // Set the volume to the cached value. 68 | playerSetVolume(mutedVolume); 69 | } 70 | } 71 | } 72 | @Override 73 | public void showWindow() { 74 | if (disposeLock.tryLock()) { 75 | try { 76 | playerShowWindow(); 77 | setMute(false); 78 | } catch (MediaException me) { 79 | sendPlayerEvent(new MediaErrorEvent(this, me.getMediaError())); 80 | } finally{ 81 | disposeLock.unlock(); 82 | } 83 | } 84 | } 85 | 86 | @Override 87 | public void hideWindow() { 88 | if (disposeLock.tryLock()) { 89 | try { 90 | playerHideWindow(); 91 | setMute(true); 92 | } catch (MediaException me) { 93 | sendPlayerEvent(new MediaErrorEvent(this, me.getMediaError())); 94 | } finally{ 95 | disposeLock.unlock(); 96 | } 97 | } 98 | } 99 | 100 | @Override 101 | public boolean isVisible() { 102 | if (disposeLock.tryLock()) { 103 | try { 104 | return playerIsVisible(); 105 | } catch (MediaException me) { 106 | sendPlayerEvent(new MediaErrorEvent(this, me.getMediaError())); 107 | } finally{ 108 | disposeLock.unlock(); 109 | } 110 | } 111 | 112 | return false; 113 | } 114 | 115 | @Override 116 | public int getWindowHeight() { 117 | if (disposeLock.tryLock()) { 118 | try { 119 | if (!isDisposed) { 120 | return playerGetWindowHeight(); 121 | } 122 | } catch (MediaException me) { 123 | sendPlayerEvent(new MediaErrorEvent(this, me.getMediaError())); 124 | } finally{ 125 | disposeLock.unlock(); 126 | } 127 | } 128 | return -1; 129 | } 130 | 131 | @Override 132 | public int getWindowWidth() { 133 | if (disposeLock.tryLock()) { 134 | try { 135 | if (!isDisposed) { 136 | return playerGetWindowWidth(); 137 | } 138 | } catch (MediaException me) { 139 | sendPlayerEvent(new MediaErrorEvent(this, me.getMediaError())); 140 | } finally{ 141 | disposeLock.unlock(); 142 | } 143 | } 144 | return -1; 145 | } 146 | 147 | @Override 148 | public void setWindowSize(final int width, final int height) { 149 | if (disposeLock.tryLock()) { 150 | try { 151 | playerSetWindowSize(width, height); 152 | } catch (MediaException me) { 153 | sendPlayerEvent(new MediaErrorEvent(this, me.getMediaError())); 154 | } finally{ 155 | disposeLock.unlock(); 156 | } 157 | } 158 | } 159 | 160 | protected abstract int playerGetWindowWidth() throws MediaException; 161 | 162 | protected abstract int playerGetWindowHeight() throws MediaException; 163 | 164 | protected abstract void playerSetWindowSize(int width, int height) throws MediaException; 165 | 166 | protected abstract void playerShowWindow() throws MediaException; 167 | 168 | protected abstract void playerHideWindow() throws MediaException; 169 | 170 | protected abstract boolean playerIsVisible() throws MediaException; 171 | } 172 | -------------------------------------------------------------------------------- /src/main/cpp/MediaPlayerErrors.h: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT -- MACHINE GENERATED 2 | #ifndef _MEDIA_PLAYER_ERRORS_H_ 3 | #define _MEDIA_PLAYER_ERRORS_H_ 4 | 5 | #define ERROR_NONE 0 6 | #define ERROR_MEDIA_BASE 256 7 | #define ERROR_MEDIA_NULL 257 8 | #define ERROR_MEDIA_CREATION 258 9 | #define ERROR_MEDIA_INVALID 260 10 | #define ERROR_PIPELINE_BASE 768 11 | #define ERROR_PIPELINE_NULL 769 12 | #define ERROR_PIPELINE_CREATION 770 13 | #define ERROR_PLAYBACK_BASE 1792 14 | #define ERROR_PLAYBACK_NULL 1793 15 | #define ERROR_MPV_BASE 1900 16 | #define ERROR_MPV_EVENT_QUEUE_FULL 1901 17 | #define ERROR_MPV_NOMEM 1902 18 | #define ERROR_MPV_UNINITIALIZED 1903 19 | #define ERROR_MPV_INVALID_PARAMETER 1904 20 | #define ERROR_MPV_OPTION_NOT_FOUND 1905 21 | #define ERROR_MPV_OPTION_FORMAT 1906 22 | #define ERROR_MPV_OPTION_ERROR 1907 23 | #define ERROR_MPV_PROPERTY_NOT_FOUND 1908 24 | #define ERROR_MPV_PROPERTY_FORMAT 1909 25 | #define ERROR_MPV_PROPERTY_UNAVAILABLE 1910 26 | #define ERROR_MPV_PROPERTY_ERROR 1911 27 | #define ERROR_MPV_COMMAND 1912 28 | #define ERROR_MPV_LOADING_FAILED 1913 29 | #define ERROR_MPV_AO_INIT_FAILED 1914 30 | #define ERROR_MPV_VO_INIT_FAILED 1915 31 | #define ERROR_MPV_NOTHING_TO_PLAY 1916 32 | #define ERROR_MPV_UNKNOWN_FORMAT 1917 33 | #define ERROR_MPV_UNSUPPORTED 1918 34 | #define ERROR_MPV_NOT_IMPLEMENTED 1919 35 | #define ERROR_MPV_GENERIC 1920 36 | #define ERROR_FFMPEG_BASE 2304 37 | #define ERROR_FFMPEG_BSF_NOT_FOUND 2305 38 | #define ERROR_FFMPEG_BUG 2306 39 | #define ERROR_FFMPEG_BUFFER_TOO_SMALL 2307 40 | #define ERROR_FFMPEG_DECODER_NOT_FOUND 2308 41 | #define ERROR_FFMPEG_DEMUXER_NOT_FOUND 2309 42 | #define ERROR_FFMPEG_ENCODER_NOT_FOUND 2310 43 | #define ERROR_FFMPEG_EOF 2311 44 | #define ERROR_FFMPEG_EXIT 2312 45 | #define ERROR_FFMPEG_EXTERNAL 2313 46 | #define ERROR_FFMPEG_FILTER_NOT_FOUND 2314 47 | #define ERROR_FFMPEG_INVALIDDATA 2315 48 | #define ERROR_FFMPEG_MUXER_NOT_FOUND 2316 49 | #define ERROR_FFMPEG_OPTION_NOT_FOUND 2317 50 | #define ERROR_FFMPEG_PATCHWELCOME 2318 51 | #define ERROR_FFMPEG_PROTOCOL_NOT_FOUND 2319 52 | #define ERROR_FFMPEG_STREAM_NOT_FOUND 2320 53 | #define ERROR_FFMPEG_BUG2 2321 54 | #define ERROR_FFMPEG_UNKNOWN 2322 55 | #define ERROR_FFMPEG_EXPERIMENTAL 2323 56 | #define ERROR_FFMPEG_INPUT_CHANGED 2324 57 | #define ERROR_FFMPEG_OUTPUT_CHANGED 2325 58 | #define ERROR_FFMPEG_HTTP_BAD_REQUEST 2326 59 | #define ERROR_FFMPEG_HTTP_UNAUTHORIZED 2327 60 | #define ERROR_FFMPEG_HTTP_FORBIDDEN 2328 61 | #define ERROR_FFMPEG_HTTP_NOT_FOUND 2329 62 | #define ERROR_FFMPEG_HTTP_OTHER_4XX 2330 63 | #define ERROR_FFMPEG_HTTP_SERVER_ERROR 2331 64 | #define ERROR_FFMPEG_AUDIO_FORMAT_NULL 2332 65 | #define ERROR_FFMPEG_AUDIO_FORMAT_ENCODING_NULL 2333 66 | #define ERROR_FFMPEG_AUDIO_FORMAT_ENCODING_ID_NULL 2334 67 | #define ERROR_FFMPEG_AUDIO_FORMAT_ENCODING_CLASS_NULL 2335 68 | #define ERROR_FFMPEG_AUDIO_FORMAT_ENCODING_NAME_ID_NULL 2336 69 | #define ERROR_FFMPEG_AUDIO_FORMAT_ENDIAN_ID_NULL 2337 70 | #define ERROR_FFMPEG_AUDIO_FORMAT_SAMPLE_RATE_ID_NULL 2338 71 | #define ERROR_FFMPEG_AUDIO_FORMAT_SAMPLE_SIZE_IN_BITS_ID_NULL 2339 72 | #define ERROR_FFMPEG_AUDIO_FORMAT_CHANNELS_ID_NULL 2340 73 | #define ERROR_FFMPEG_AUDIO_FORMAT_FRAME_SIZE_ID_NULL 2341 74 | #define ERROR_FFMPEG_AUDIO_FORMAT_FRAME_RATE_ID_NULL 2342 75 | #define ERROR_FFMPEG_COLOR_SPACE_NULL 2343 76 | #define ERROR_FFMPEG_COLOR_SPACE_TYPE_NULL 2344 77 | #define ERROR_FFMPEG_COLOR_SPACE_NUM_COMPONENT_NULL 2345 78 | #define ERROR_FFMPEG_AUDIO_LINE_UNAVAILABLE 2346 79 | #define ERROR_SYSTEM_BASE 2560 80 | #define ERROR_SYSTEM_EPERM 2565 81 | #define ERROR_SYSTEM_ENOENT 2566 82 | #define ERROR_SYSTEM_ESRCH 2567 83 | #define ERROR_SYSTEM_EINTR 2568 84 | #define ERROR_SYSTEM_EIO 2569 85 | #define ERROR_SYSTEM_ENXIO 2570 86 | #define ERROR_SYSTEM_E2BIG 2571 87 | #define ERROR_SYSTEM_ENOEXEC 2572 88 | #define ERROR_SYSTEM_EBADF 2573 89 | #define ERROR_SYSTEM_ECHILD 2574 90 | #define ERROR_SYSTEM_EAGAIN 2575 91 | #define ERROR_SYSTEM_ENOMEM 2576 92 | #define ERROR_SYSTEM_EACCES 2577 93 | #define ERROR_SYSTEM_EFAULT 2578 94 | #define ERROR_SYSTEM_EBUSY 2580 95 | #define ERROR_SYSTEM_EEXIST 2581 96 | #define ERROR_SYSTEM_EXDEV 2582 97 | #define ERROR_SYSTEM_ENODEV 2583 98 | #define ERROR_SYSTEM_ENOTDIR 2584 99 | #define ERROR_SYSTEM_EISDIR 2585 100 | #define ERROR_SYSTEM_EINVAL 2586 101 | #define ERROR_SYSTEM_ENFILE 2587 102 | #define ERROR_SYSTEM_EMFILE 2588 103 | #define ERROR_SYSTEM_ENOTTY 2589 104 | #define ERROR_SYSTEM_EFBIG 2591 105 | #define ERROR_SYSTEM_ENOSPC 2592 106 | #define ERROR_SYSTEM_ESPIPE 2593 107 | #define ERROR_SYSTEM_EROFS 2594 108 | #define ERROR_SYSTEM_EMLINK 2595 109 | #define ERROR_SYSTEM_EPIPE 2596 110 | #define ERROR_SYSTEM_EDOM 2597 111 | #define ERROR_SYSTEM_ERANGE 2598 112 | #define ERROR_SYSTEM_EDEADLK 2599 113 | #define ERROR_SYSTEM_ENAMETOOLONG 2600 114 | #define ERROR_SYSTEM_ENOLCK 2601 115 | #define ERROR_SYSTEM_ENOSYS 2602 116 | #define ERROR_SYSTEM_ENOTEMPTY 2603 117 | #define ERROR_FUNCTION_BASE 2816 118 | #define ERROR_FUNCTION_PARAM 2817 119 | #define ERROR_FUNCTION_PARAM_NULL 2818 120 | #define ERROR_JNI_BASE 3072 121 | #define ERROR_JNI_SEND_PLAYER_MEDIA_ERROR_EVENT 3073 122 | #define ERROR_JNI_SEND_PLAYER_HALT_EVENT 3074 123 | #define ERROR_JNI_SEND_PLAYER_STATE_EVENT 3075 124 | #define ERROR_JNI_SEND_NEW_FRAME_EVENT 3076 125 | #define ERROR_JNI_SEND_FRAME_SIZE_CHANGED_EVENT 3077 126 | #define ERROR_JNI_SEND_END_OF_MEDIA_EVENT 3078 127 | #define ERROR_JNI_SEND_AUDIO_TRACK_EVENT 3079 128 | #define ERROR_JNI_SEND_VIDEO_TRACK_EVENT 3080 129 | #define ERROR_JNI_SEND_METADATA_EVENT 3081 130 | #define ERROR_JNI_SEND_MARKER_EVENT 3082 131 | #define ERROR_JNI_SEND_BUFFER_PROGRESS_EVENT 3083 132 | #define ERROR_JNI_SEND_STOP_REACHED_EVENT 3084 133 | #define ERROR_JNI_SEND_DURATION_UPDATE_EVENT 3085 134 | #define ERROR_JNI_SEND_AUDIO_SPECTRUM_EVENT 3086 135 | 136 | #endif // _MEDIA_PLAYER_ERRORS_H_ 137 | -------------------------------------------------------------------------------- /NativeOSXCanvas/src/java/com/apple/dts/samplecode/jawtexample/JAWTExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | File: JAWTExample.java 3 | Abstract: Simple Java app that uses native drawing. 4 | Version: 2.0 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2011 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | package com.apple.dts.samplecode.jawtexample; 49 | 50 | import java.awt.*; 51 | import java.lang.*; 52 | 53 | import javax.swing.JFrame; 54 | 55 | public class JAWTExample { 56 | 57 | private static LayerBackedCanvas layerBackedCanvas; 58 | 59 | public static void main(final String args[]) { 60 | EventQueue.invokeLater(new Runnable() { 61 | public void run() { 62 | final JAWTFrame frame = new JAWTFrame("JAWTExample"); 63 | frame.setBackground(Color.white); 64 | frame.setLayout(new BorderLayout(10, 20)); 65 | frame.setLocation(50, 50); 66 | frame.addNotify(); 67 | frame.pack(); 68 | frame.setVisible(true); 69 | 70 | } 71 | }); 72 | 73 | EventQueue.invokeLater(new Runnable() { 74 | public void run() { 75 | System.out.println("HEIGHT: " + layerBackedCanvas.getMovieHeight()); 76 | System.out.println("WIDTH: " + layerBackedCanvas.getMovieWidth()); 77 | System.out.println("DURATION: " + layerBackedCanvas.getDuration()); 78 | System.out.println("FPS: " + layerBackedCanvas.getFPS()); 79 | 80 | } 81 | }); 82 | 83 | 84 | EventQueue.invokeLater(new Runnable() { 85 | public void run() { 86 | layerBackedCanvas.setVolume(0f); 87 | } 88 | }); 89 | 90 | 91 | EventQueue.invokeLater(new Runnable() { 92 | public void run() { 93 | layerBackedCanvas.play(); 94 | } 95 | }); 96 | 97 | try { 98 | Thread.sleep(1000); 99 | } catch (Exception e) { 100 | 101 | } 102 | 103 | EventQueue.invokeLater(new Runnable() { 104 | public void run() { 105 | layerBackedCanvas.setTime(15000L); 106 | System.out.println(layerBackedCanvas.getCurrentTime()); 107 | } 108 | }); 109 | 110 | EventQueue.invokeLater(new Runnable() { 111 | public void run() { 112 | layerBackedCanvas.release(); 113 | } 114 | }); 115 | } 116 | 117 | static class JAWTFrame extends JFrame { 118 | public JAWTFrame(final String title) { 119 | super(title); 120 | } 121 | 122 | public void addNotify() { 123 | super.addNotify(); // ensures native component hierarchy is setup 124 | 125 | // add the NSView-based drawing demo canvas 126 | // final NativeDrawnCanvas nativeDrawingCanvas = new NativeDrawnCanvas(); 127 | // nativeDrawingCanvas.setPreferredSize(new Dimension(100, 100)); 128 | // add(nativeDrawingCanvas, BorderLayout.NORTH); 129 | 130 | // add the CoreAnimation layer-backed demo canvas 131 | layerBackedCanvas = new LayerBackedCanvas(); 132 | layerBackedCanvas.setPreferredSize(new Dimension(400, 200)); 133 | add(layerBackedCanvas, BorderLayout.CENTER); 134 | 135 | System.out.println("CREATED STUFF"); 136 | 137 | invalidate(); 138 | 139 | } 140 | } 141 | } -------------------------------------------------------------------------------- /src/test/java/org/datavyu/plugins/ffmpeg/FfmpegSdlMediaPlayerTest.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins.ffmpeg; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | import org.datavyu.plugins.MediaException; 6 | import org.datavyu.plugins.MediaPlayer; 7 | import org.testng.annotations.DataProvider; 8 | import org.testng.annotations.Test; 9 | 10 | /** Tests the ffmpeg player using an AWT window for display */ 11 | public class FfmpegSdlMediaPlayerTest extends MediaPlayerTest { 12 | private static final Logger logger = LogManager.getFormatterLogger(FfmpegSdlMediaPlayerTest.class); 13 | 14 | public static class FfmpegBuilder implements Builder { 15 | private MediaInformation mediaInformation; 16 | 17 | FfmpegBuilder() {} 18 | 19 | FfmpegBuilder withMedia(MediaInformation mediaInformation) { 20 | this.mediaInformation = mediaInformation; 21 | return this; 22 | } 23 | 24 | @Override 25 | public MediaPlayerSync build() { 26 | MediaPlayer mediaPlayer = 27 | new FfmpegSdlMediaPlayer(mediaInformation.getLocalPath()); 28 | return MediaPlayerSync.createMediaPlayerSync(mediaPlayer); 29 | } 30 | } 31 | 32 | @DataProvider(name = "shortMedia") 33 | public Object[][] createPlayerWithShortMedia() { 34 | return new Object[][] { 35 | {new FfmpegBuilder().withMedia(SHORT_MEDIA), SHORT_MEDIA} 36 | }; 37 | } 38 | 39 | @DataProvider(name = "longMedia") 40 | public Object[][] createPlayerWithLongMedia() { 41 | return new Object[][] { 42 | {new FfmpegBuilder().withMedia(LONG_MEDIA), LONG_MEDIA} 43 | }; 44 | } 45 | 46 | @DataProvider(name = "wrongMedia") 47 | public Object[][] createPlayerWithWrongMedia() { 48 | return new Object[][] { 49 | {new FfmpegBuilder().withMedia(WRONG_MEDIA), WRONG_MEDIA} 50 | }; 51 | } 52 | 53 | @Test(dataProvider = "shortMedia") 54 | public void testReadyState(Builder builder, MediaInformation mediaInformation) { 55 | logger.debug("******** Test Ready State ********"); 56 | super.testReadyState(builder, mediaInformation); 57 | } 58 | 59 | @Test(dataProvider = "shortMedia") 60 | public void testPlayingState(Builder builder, MediaInformation mediaInformation) { 61 | logger.debug("******** Test Playing State ********"); 62 | super.testPlayingState(builder, mediaInformation); 63 | } 64 | 65 | @Test(dataProvider = "shortMedia") 66 | public void testStoppedState(Builder builder, MediaInformation mediaInformation) { 67 | logger.debug("******** Test Stopped State ********"); 68 | super.testStoppedState(builder, mediaInformation); 69 | } 70 | 71 | @Test(dataProvider = "shortMedia") 72 | public void testPausedState(Builder builder, MediaInformation mediaInformation) { 73 | logger.debug("******** Test Paused State ********"); 74 | super.testPausedState(builder, mediaInformation); 75 | } 76 | 77 | @Test(dataProvider = "shortMedia") 78 | public void testMetadata(Builder builder, MediaInformation mediaInformation) { 79 | logger.debug("******** Test Metadata ********"); 80 | super.testMetadata(builder, mediaInformation); 81 | } 82 | 83 | @Test(dataProvider = "wrongMedia", expectedExceptions = MediaException.class) 84 | public void testWrongFilename(Builder builder, MediaInformation mediaInformation) { 85 | logger.debug("******** Test Wrong File Path ********"); 86 | super.testWrongFile(builder, mediaInformation); 87 | } 88 | 89 | @Test(dataProvider = "shortMedia") 90 | public void testTimeAtStart(Builder builder, MediaInformation mediaInformation) { 91 | logger.debug("******** Test Time At Start ********"); 92 | super.testTimeAtStart(builder, mediaInformation); 93 | } 94 | 95 | @Test(dataProvider = "longMedia") 96 | public void testSeek(Builder builder, MediaInformation mediaInformation) { 97 | logger.debug("******** Test Seek ********"); 98 | super.testSeek(builder, mediaInformation); 99 | } 100 | 101 | @Test(dataProvider = "shortMedia") 102 | public void testSeekAtStart(Builder builder, MediaInformation mediaInformation) { 103 | logger.debug("******** Test Seek At Start ********"); 104 | super.testSeekAtStart(builder, mediaInformation); 105 | } 106 | 107 | @Test(dataProvider = "shortMedia") 108 | public void testStepForward(Builder builder, MediaInformation mediaInformation) { 109 | logger.debug("******** Test Step Forward ********"); 110 | super.testStepForward(builder, mediaInformation); 111 | } 112 | 113 | @Test(dataProvider = "shortMedia") 114 | public void testStepForwardAtEnd(Builder builder, MediaInformation mediaInformation) { 115 | logger.debug("******** Test Step Forward At End ********"); 116 | super.testStepForwardAtEnd(builder, mediaInformation); 117 | } 118 | 119 | @Test(dataProvider = "shortMedia") 120 | public void testStepBackward(Builder builder, MediaInformation mediaInformation) { 121 | logger.debug("******** Test Step Backward At Start ********"); 122 | super.testStepBackward(builder, mediaInformation); 123 | } 124 | 125 | @Test(dataProvider = "shortMedia") 126 | public void testStepBackwardAtStart(Builder builder, MediaInformation mediaInformation) { 127 | logger.debug("******** Test Step Backward At Start ********"); 128 | super.testStepBackwardAtStart(builder, mediaInformation); 129 | } 130 | 131 | @Test(dataProvider = "shortMedia") 132 | public void testRateAtPlay(Builder builder, MediaInformation mediaInformation) { 133 | logger.debug("******** Test Rates at Play ********"); 134 | super.testRateAtPlay(builder, mediaInformation); 135 | } 136 | 137 | @Test(dataProvider = "longMedia") 138 | public void testRates(Builder builder, MediaInformation mediaInformation) { 139 | logger.debug("******** Test Rates ********"); 140 | super.testRates(builder, mediaInformation); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/org/datavyu/plugins/nativeosx/AVFoundationMediaPlayer.java: -------------------------------------------------------------------------------- 1 | package org.datavyu.plugins.nativeosx; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | 6 | import org.datavyu.plugins.*; 7 | import org.datavyu.plugins.ffmpeg.FfmpegSdlMediaPlayer; 8 | 9 | import java.awt.*; 10 | import java.io.File; 11 | import java.net.URI; 12 | 13 | public class AVFoundationMediaPlayer extends NativeOSXMediaPlayer { 14 | 15 | private static Logger logger = LogManager.getLogger(AVFoundationMediaPlayer.class); 16 | 17 | private Container container; 18 | private final Object readyLock = new Object(); 19 | 20 | private PlayerStateListener stateListener; 21 | 22 | private long startInitTime; 23 | private long endInitTime; 24 | 25 | public AVFoundationMediaPlayer(URI mediaPath, Container container) { 26 | super(mediaPath); 27 | this.stateListener = new PlayerStateListenerImpl(); 28 | this.addMediaPlayerStateListener(stateListener); 29 | this.container = container; 30 | } 31 | 32 | @Override 33 | public void init() { 34 | logger.info("Initializing " + this.getClass().getName()); 35 | 36 | startInitTime = System.currentTimeMillis(); 37 | 38 | initNative(); 39 | 40 | // Test if the file exists 41 | File mediaFile = new File(mediaPath); 42 | if (!mediaFile.exists()) { 43 | throwMediaErrorException(MediaError.ERROR_MEDIA_INVALID.code(), null); 44 | } 45 | 46 | container.addNotify(); 47 | container.add(mediaPlayer, BorderLayout.CENTER); 48 | container.setBackground(Color.BLACK); 49 | 50 | Runnable waitForReady = 51 | () -> { 52 | //TODO(Reda): Timeout this loop and throw an exception 53 | while (playerGetFps() <= 0 && Float.compare((float) playerGetDuration(),0) < 0) { 54 | try { 55 | Thread.sleep(100); 56 | } catch (InterruptedException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | logger.debug("Sending Ready State"); 61 | sendPlayerStateEvent(eventPlayerReady, 0); 62 | }; 63 | 64 | new Thread(waitForReady).start(); 65 | 66 | synchronized (readyLock) { 67 | try { 68 | logger.debug("Waiting for Ready state"); 69 | readyLock.wait(); 70 | // Always increment the player count after creating an instance 71 | // Important: don't decrement the player count when releasing resources 72 | incPlayerCount(); 73 | endInitTime = System.currentTimeMillis(); 74 | logger.debug("Time to initialize : " + (endInitTime - startInitTime) + " ms"); 75 | } catch (InterruptedException e) { 76 | logger.error(e.getMessage()); 77 | } 78 | } 79 | } 80 | 81 | @Override 82 | protected void playerSeek(double streamTime, int flags) throws MediaException { 83 | switch (flags) { 84 | case NORMAL_SEEK_FLAG: 85 | EventQueue.invokeLater(() -> mediaPlayer.setTime((long) streamTime, id)); 86 | break; 87 | case PRECISE_SEEK_FLAG: 88 | EventQueue.invokeLater(() -> mediaPlayer.setTimePrecise((long) streamTime, id)); 89 | break; 90 | case MODERATE_SEEK_FLAG: 91 | EventQueue.invokeLater(() -> mediaPlayer.setTimeModerate((long) streamTime, id)); 92 | break; 93 | } 94 | } 95 | 96 | @Override 97 | protected int playerGetWindowWidth() throws MediaException { 98 | return this.container.getWidth(); 99 | } 100 | 101 | @Override 102 | protected int playerGetWindowHeight() throws MediaException { 103 | return this.container.getHeight(); 104 | } 105 | 106 | @Override 107 | protected void playerSetWindowSize(int width, int height) throws MediaException { 108 | this.container.setSize(width, height); 109 | } 110 | 111 | @Override 112 | protected void playerShowWindow() throws MediaException { 113 | this.container.setVisible(true); 114 | } 115 | 116 | @Override 117 | protected void playerHideWindow() throws MediaException { 118 | this.container.setVisible(false); 119 | } 120 | 121 | @Override 122 | protected boolean playerIsVisible() throws MediaException { 123 | return this.container.isVisible(); 124 | } 125 | 126 | @Override 127 | protected void HandleSdlKeyEvents(FfmpegSdlMediaPlayer.SdlPlayerKeyEvent evt) { 128 | throw new IllegalArgumentException(); 129 | } 130 | 131 | 132 | @Override 133 | public void addSdlKeyEventListener(SdlKeyEventListener listener) { 134 | throw new IllegalArgumentException(); 135 | } 136 | 137 | @Override 138 | public void removeSdlKeyEventListener(SdlKeyEventListener listener) { 139 | throw new IllegalArgumentException(); 140 | } 141 | 142 | private class PlayerStateListenerImpl implements PlayerStateListener { 143 | 144 | @Override 145 | public void onReady(PlayerStateEvent evt) { 146 | synchronized (readyLock) { 147 | container.setSize(getImageWidth(), getImageHeight()); 148 | container.setVisible(true); 149 | startTime = getPresentationTime(); 150 | readyLock.notify(); 151 | logger.debug("Player is Ready - FPS " + playerGetFps() + " - Duration " + playerGetDuration()); 152 | } 153 | } 154 | 155 | @Override 156 | public void onPlaying(PlayerStateEvent evt) { 157 | logger.info("Player is Playing"); 158 | } 159 | 160 | @Override 161 | public void onPause(PlayerStateEvent evt) { 162 | logger.info("Player is Paused"); 163 | } 164 | 165 | @Override 166 | public void onStop(PlayerStateEvent evt) { 167 | logger.info("Player is Stopped"); 168 | } 169 | 170 | @Override 171 | public void onStall(PlayerStateEvent evt) {} 172 | 173 | @Override 174 | public void onFinish(PlayerStateEvent evt) {} 175 | 176 | @Override 177 | public void onHalt(PlayerStateEvent evt) {} 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /NativeOSXCanvas/src/native/DrawingCanvas.m: -------------------------------------------------------------------------------- 1 | /* 2 | File: DrawingCanvas.m 3 | Abstract: Native code that draws into an AWT Canvas. 4 | Version: 2.0 5 | 6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple 7 | Inc. ("Apple") in consideration of your agreement to the following 8 | terms, and your use, installation, modification or redistribution of 9 | this Apple software constitutes acceptance of these terms. If you do 10 | not agree with these terms, please do not use, install, modify or 11 | redistribute this Apple software. 12 | 13 | In consideration of your agreement to abide by the following terms, and 14 | subject to these terms, Apple grants you a personal, non-exclusive 15 | license, under Apple's copyrights in this original Apple software (the 16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple 17 | Software, with or without modifications, in source and/or binary forms; 18 | provided that if you redistribute the Apple Software in its entirety and 19 | without modifications, you must retain this notice and the following 20 | text and disclaimers in all such redistributions of the Apple Software. 21 | Neither the name, trademarks, service marks or logos of Apple Inc. may 22 | be used to endorse or promote products derived from the Apple Software 23 | without specific prior written permission from Apple. Except as 24 | expressly stated in this notice, no other rights or licenses, express or 25 | implied, are granted by Apple herein, including but not limited to any 26 | patent rights that may be infringed by your derivative works or by other 27 | works in which the Apple Software may be incorporated. 28 | 29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE 30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION 31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS 32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND 33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. 34 | 35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL 36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, 39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED 40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), 41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE 42 | POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2011 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | #import 49 | #import 50 | #import 51 | 52 | #include "com_apple_dts_samplecode_jawtexample_NativeDrawnCanvas.h" 53 | 54 | 55 | /* 56 | * Class: com_apple_dts_samplecode_jawtexample_NativeDrawnCanvas 57 | * Method: nativePaintOnCanvas 58 | * Signature: ()V 59 | */ 60 | JNIEXPORT void JNICALL Java_com_apple_dts_samplecode_jawtexample_NativeDrawnCanvas_nativePaintOnCanvas 61 | (JNIEnv *env, jobject canvas) { 62 | JNF_COCOA_ENTER(env); 63 | 64 | // get the AWT 65 | JAWT awt; 66 | awt.version = JAWT_VERSION_1_4; 67 | jboolean result = JAWT_GetAWT(env, &awt); 68 | JNF_CHECK_AND_RETHROW_EXCEPTION(env); 69 | if (result == JNI_FALSE) return; // NSView access unsupported in future versions of Java for Mac OS X 70 | 71 | // get the drawing surface 72 | JAWT_DrawingSurface *ds = awt.GetDrawingSurface(env, canvas); 73 | JNF_CHECK_AND_RETHROW_EXCEPTION(env); 74 | assert(ds != NULL); 75 | 76 | // lock the drawing surface - must lock EACH TIME before drawing 77 | jint lock = ds->Lock(ds); 78 | JNF_CHECK_AND_RETHROW_EXCEPTION(env); 79 | assert((lock & JAWT_LOCK_ERROR) == 0); 80 | 81 | // get the drawing surface info 82 | JAWT_DrawingSurfaceInfo *dsi = ds->GetDrawingSurfaceInfo(ds); 83 | JNF_CHECK_AND_RETHROW_EXCEPTION(env); 84 | 85 | // // Check DrawingSurfaceInfo. This can be NULL on Mac OS X if the native 86 | // // component heirachy has not been made visible yet on the AppKit thread. 87 | // if (dsi != NULL) { 88 | // // Get the platform-specific drawing info 89 | // // This is used to get at Cocoa and CoreGraphics 90 | // // See 91 | // JAWT_MacOSXDrawingSurfaceInfo *dsi_mac = (JAWT_MacOSXDrawingSurfaceInfo*)dsi->platformInfo; 92 | // 93 | // // This drawing does not stictly need to be done on the AppKit thread, 94 | // // but concurrent AppKit drawing may produce unexpected results as this 95 | // // Java thread and the AppKit thread race each other. 96 | // { 97 | // // Get the corresponding peer from the caller canvas 98 | // NSView *view = dsi_mac->cocoaViewRef; 99 | // NSWindow *window = [view window]; 100 | // 101 | // // Get the CoreGraphics context from the videoController window - DO NOT CACHE 102 | // CGContextRef cg = [[NSGraphicsContext graphicsContextWithWindow:window] graphicsPort]; 103 | // 104 | // // Match Java's ctm 105 | // NSRect windowRect = [[window contentView] frame]; 106 | // CGContextConcatCTM(cg, CGAffineTransformMake(1, 0, 0, -1, dsi->bounds.x, windowRect.size.height - dsi->bounds.y)); 107 | // 108 | // // Draw a pattern using CoreGraphics 109 | // CGContextSetRGBFillColor(cg, 1.0f, 0.0f, 0.0f, 1.0f); 110 | // CGContextFillRect(cg, CGRectMake(15, 15, 70, 70)); 111 | // } 112 | // 113 | // // Free the DrawingSurfaceInfo 114 | // ds->FreeDrawingSurfaceInfo(dsi); 115 | // JNF_CHECK_AND_RETHROW_EXCEPTION(env); 116 | // } 117 | 118 | // Unlock the drawing surface - must unlock EACH TIME when done drawing 119 | ds->Unlock(ds); 120 | JNF_CHECK_AND_RETHROW_EXCEPTION(env); 121 | 122 | // Free the drawing surface (if not caching it) 123 | awt.FreeDrawingSurface(ds); 124 | JNF_CHECK_AND_RETHROW_EXCEPTION(env); 125 | 126 | JNF_COCOA_EXIT(env); 127 | } 128 | --------------------------------------------------------------------------------