Update:
Since the media side of JFX has been open sourced, I've looked into this myself and it is indeed possible, but requires changing and rebuilding the JFX source (both Java and C parts.) The process is described here for anyone that wants to have a go - I add MKV support in that example, but it should be very similar for other plugins.
The remainder of the question is thus mainly historical, but I'll leave it here for reference.
Background
I've been using VLCJ thus far for playing video in my application. It works, but if possible I'd like to see if I can achieve a similar level of support for common codecs by migrating to JavaFX and saving myself a lot of hassle with multiple VMs and suchlike that VLCJ needs to play multiple videos reliably. I won't go into it here but see my answer to this question if you're interested in the details. There's also the issue of cross-platform compatibility, it works on Mac and Linux ok but I haven't worked out how to get it to show on Mac yet (I believe there's some security in place to prevent one process gaining access to another's native components, but again that's beyond the scope of this question.)
It boils down to the fact that while it works, it's a lot of maintenance and hassle working with multiple VMs and bridging them stably if there's another solution that would be easier. VLC does have a pretty legendary level of support for playing pretty much anything which is why I've gone with it thus far, and I'd be interested to see if I can get a similar result in JavaFX - or at least if it can provide the means for doing so in a cross platform manner.
Research
JavaFX 2.0 supports video - great! But at the moment the official line is it supports "FLV containing VP6 video and MP3 audio". Is there a way to extend this to add in support for more codecs? There's no hard codec that I'd like to support, it's more a case of as many as I can so I'm looking for an extensible method to go about the above.
I wondered if it would play video for codecs installed natively on the machine and that it just doesn't advertise itself as such (because that functionality obviously is machine dependant and not cross-platform.) But no dice, I've tried a number of common formats and it really does refuse to play anything other than what it states.
From looking at JavaFX 1.3 it also supports other platform dependant codecs depending on where it's installed. Is there a way to get this behaviour with JavaFX 2? Or is it planned at all for a subsequent release? I haven't been able to find any information on it on the roadmap or any comment from Oracle about it.
Only thing I could find from searching extensively is here which implies that it may be possible but no-one seems to know how. I'd also be interested to know if it's based on GStreamer why all the formats supported by GStreamer aren't included by default either?
In terms of playing DVDs with JavaFX I've got absolutely nowhere, so I'm assuming that's just a no-go at the moment. If anyone does have any ideas or information though, I'm all ears.
Other approaches
One approach which I was half wondering may be possible is crowbarring the JMC jar out of the old JavaFX as described here and trying to get that working alongside JavaFX 2. I don't suppose anyone has had any luck with that approach or something similar?
All things failing, if anyone has any information or links on if / when support for additional codecs will be supported out of the box, then I'd be interested to hear that also. Or if anyone has any contact details for someone at Oracle I could ask that would also be appreciated! I've been longing for decent video support in Java for some time, and I guess what this boils down to is trying to figure out if JavaFX is the answer to this, or just another half hearted attempt that will never play more than what it does at the moment! I'm hoping it's not the latter, but I've yet to see much to show that's the case.
Believe me, I feel and know your frustration. I have pondered this for a while, but I had to use un-straight means of solving my issues.
There are many ways around this, each with limitations but depends on what works for you:
Docs say WebView works with HTML5, which plays videos supported on the platform (Though sadly not flash). If using a webview to play video works for you, you can try this out. You can even draw over it with other nodes.
Portable VLC Player! If maybe you're developing some sort of projector/director app and you want fullscreen video, you can have portable VLC player play the video in fullscreen in one screen with it's controls in the other. Used this solution and it works quite well for mac and windows. :)
Only thing is you can't draw nodes on the video as it's an external app, with just the illusion of fullscreen video of your app.
If you ever need to utilize the power of flash within your javafx 2.0 application, then use a swt-based browser(or something Like the DJ Project if you're a Swinger) as they support all features of your native browser.
I've now managed to compile MKV support into JavaFX successfully, and it does take some, but not a great deal of effort on the native layer also. See here for the discussion surrounding it, and here for the result submitted as a patch / JIRA ticket.
I've written a much more comprehensive guide on the process here which may be of interest to anyone else looking to go down this route.
What follows is my brief investigation before I actually seriously looked at compiling other media support in, though I'll leave it here for reference.
Now that JFX8 has been released and is completely open source, I've spent a bit of time looking at how this could be done, and whether it could be done without patching the JFX source. Unfortunately the answer to that latter point is an almost definite no, at least not without horrible bytecode manipulation hacks. I may look into this more practically at a later date, but I'll document what I've worked out so far from the source available.
The magic starts from the Media constructor, which is ultimately where the MediaException pops out from (with the MEDIA_UNSUPPORTED flag if you try to play an unsupported format.) From there it creates the Locator, whose constructor ensures that the URL is one that's supported. It's init() method is then called in a separate thread, which performs some sanity checking on the URL string, reads the file, then proceeds to try to work out what the format is.
The relevant code for this part of the method is thus:
if (scheme.equals("file") || scheme.equals("jar")) {
InputStream stream = getInputStream(uri);
stream.close();
isConnected = true;
contentType = MediaUtils.filenameToContentType(uriString); // We need to provide at least something
}
if (isConnected) {
// Check whether content may be played.
// For WAV use file signature, since it can detect audio format
// and we can fail sooner, then doing it at runtime.
// This is important for AudioClip.
if (MediaUtils.CONTENT_TYPE_WAV.equals(contentType)) {
contentType = getContentTypeFromFileSignature(uri);
if (!MediaManager.canPlayContentType(contentType)) {
isMediaSupported = false;
}
} else {
if (contentType == null || !MediaManager.canPlayContentType(contentType)) {
// Try content based on file name.
contentType = MediaUtils.filenameToContentType(uriString);
if (Locator.DEFAULT_CONTENT_TYPE.equals(contentType)) {
// Try content based on file signature.
contentType = getContentTypeFromFileSignature(uri);
}
if (!MediaManager.canPlayContentType(contentType)) {
isMediaSupported = false;
}
}
}
// Break as connection has been made and media type checked.
break;
}
From this we can see a first "dumb" attempt is made to grab the file content based on its name (this is what MediaUtils.filenameToContentType() does.) There's then some special cases for checking for different types of wav file, but if that fails then we fall back on a cleverer check which looks at the actual file signature. Both these checks are in MediaUtils. This latter check is much more extensive, and looks at the first few bytes of the file to see if it can work out a format that way. If it can't, then it bails out and throws the exception that then pops out as our dreaded MEDIA_UNSUPPORTED flag.
If the type is identified correctly though, there's still another hurdle to go through - it has to be supported by the current platform. Some platforms are loaded dynamically depending on the environment, however the GSTPlatform always exists, thus we would need to put any additional (universal) formats here. This is relatively simple, a CONTENT_TYPES array exists which just holds the array of supported formats.
Unfortunately cloning the JavaFX repo seems to be failing for me at the moment, otherwise I'd attempt to put some of this in practice. But in lieu of the above, what actually needs to happen to add support for further formats? It actually doesn't seem hugely difficult.
In MediaUtils, support needs to be added to the filenameToContentType() method to handle the new file extension. This is trivial.
In the same class, support needs to be added to the fileSignatureToContentType() method to work out the file type based on its signature. This is a tad more complex, but still not too bad. This may even be optional, since the current code only seems to use this as a fallback if the format isn't identified correctly (or at all) from the file extension. A comprehensive list of file signatures for different formats can be found here which should help with this task.
In GSTPlatform, the new content type needs to be added to the list of supported content types.
On the Java side of things, this appears to be all that's necessary to get it to accept the content type and at least attempt to pass it down to the native Gstreamer layer.
However, I'm no expert in GStreamer, so while I'm aware there's many more formats that it can handle and play that JavaFX currently refuses, I'm unsure as to how exactly they've removed this capacity. They've definitely done it in the Java layer above, but they may have also done it on the native GStreamer level - at this point I'm unsure.
I assume they've made some changes to GStreamer for JFX8 - but at the present time they're not listed on the relevant project page, so it's quite hard to work out exactly what they've changed for this version.
The next step would be to grab the JFX8 source, build with the above proposed changes for a new content type, and then see what errors (if any) occur on the native level, then take it from there.
The API design does not appear to have support for rolling your own codecs. Pretty much all of the classes are final (e.g. VideoTrack, Media, MediaPlayer etc). I assume that the actual video decoding is done with internal classes at present, meaning there is no way to override them.
There is a plan to Open Source JavaFX 2.0, I suspect as we approach the release of JDK8. Hopefully when they do this we can see how they resolve their codecs from the Media(String source) constructor and see if we can hook into this somehow.
And now, Javafx2.1 finally supports mp4 H.264 so you should now be good to go without the above posted stunts. :)
Current open feature requests for this in the JavaFX bug tracking system:
JDK-8091656 Wishlist for more media format support
JDK-8091755 Media should support InputStream
Read the linked feature requests and the associated comments on them to understand their current status (or lack thereof ;-) for the JavaFX distribution version that you are using.
Note, for the InputStream based Media API, one of the later comments by a JavaFX developer is "I propose we consider this for JDK 10", so I guess it may be a possibility in the future...
Also note, if you are not sure if JavaFX currently has in-built support for a given encoding type or not, a comprehensive overview of supported media encodings and media container types is provided in the javadoc for the javafx.media package (just ensure that you review the version of the javadoc which matches your version of JavaFX).
Those who may be interested in other solutions to at least get a video to play from JavaFX, even if it is a media type not natively supported by JavaFX and you don't want to hack the native JavaFX media support just to get your video to play, can also see my answer to the related question:
Playing h265 HEVC in a JavaFX client
Related
I'm not sure if this question is entirely appropriate for SO but it seemed to work better here than in SuperUser so apologies if its in the wrong place. Happy to move it if so.
I'm trying to figure out how I'd automate the input of data into a system that didn't accept data uploads, but rather used forms put up on a screen. Use cases are e.g. where an enterprise wide system does accept uploads but the user lacks admin rights to fill in data she is required to populate, or with very old and specialized legacy systems where the functionality just doesn't exist and a serial input-review-rollback-commit cycle is enforced.
I'm not a programmer by trade so this is partly thought experiment but also to answer a question that has arisen at a business that I'm involved in.
I'm reasonably familiar with python and java if libraries for keyboard emulation exist but would be happy interpreting a pseudo code response too.
Responses that point to existing providers of such functionality that is embeddable or that tell me if I'm barking up the wrong tree also gratefully accepted.
Once again apologies as I know this isnt intuitively the best spot for this. Please do point me to a better location if you know of one.
Thanks
Possible solutions exist but they're all pretty bad
Is it a desktop application or a web application? If it's a web application you can use ghost.py to automate the interaction and submission of new records/entries. This work will be a glorious bundle of fun for the lucky code jockey who draws the short straw.
If it's a desktop application, it will be a great deal more difficult. Is it on Windows? Linux? MacOSX? Is the software written in Java? Using the Swing toolkit? AWT? SWT?
If it is a native Windows application you might be able to use Autohotkey to automate desktop interaction. This can be as basic as automatic clicks in pre-recorded parts of the screen, automating TAB keypresses to move around the input cells and reading input text from a data file and writing that out into the input cells. This will be even more entertaining than the web-solution mentioned earlier: truly the necessary ingredients for an authentic war story worthy of the annals of internet lore.
This is likely to be a lot of intricate work, error-prone, and subject to failure in the future if the UI of the software is changed; and such changes are very likely. It would be a lot easier to help if you could add more detail to the question.
Before embarking down this road, if I were you I would beg and plead with the software vendor to either provide me with an upload API; I would even offer to pay the vendor to upload my data for me. I cannot imagine either of the solutions I mentioned will be any cheaper, unless the work time of your developers has no value.
Good luck.
I have a need to be able to programmatically convert a PNG file that has been optimized for an iOS application and remove the optimizations. A number of posts reveal the mechanism for doing this, but I was hoping there was some Java code already out there for doing this before I go do this on my own.
Does anyone know of a Java converter for CgBI images to RGBA?
I got interested on the topic and made some research on the area. On one related page on PNG conversions I ended up to a jar package type of converter which may be something that you'd be pleased of. I suppose it to be some sort of Open Source solution, because the source was announced to be found from the same place.
I wrote a command line C program that does the same. In addition to the other converters (I have yet to test the online one), mine can handle multiple IDAT chunks, Adam7 interlacing, and all row filter types -- the latter is necessary to de-multiply color pixels with their alpha. All of this leads to, AFAIK, the very same image that got fried.
See my website for the full C source code.
When I run FreeTTS examples, I get this error:
LINE UNAVAILABLE: Format is pcm_signed 16000.0 Hz 16 bits 1 channel big endian
In this post, Freetts problem in Java
someone claims it's a known Linux/Java sound bug and has a workaround,
linking to http://forums.sun.com/thread.jspa?threadID=5189363 .
But this link does not work anymore since Oracle screwed it.
Archive.org seems not to have this page archived.
Does anyone have the workaround / patch for FreeTTS?
Thanks,
Ondra
Linux's ALSA is one large, complex API. OpenJDK and Sun's JDK seem to use it differently. Most modern Linux distributions also use PulseAudio, which virtualizes ALSA so that all audio goes through PulseAudio for software mixing before going to ALSA for playback.
When nothing is accessing the sound card, and Java is the only user, it tends to work. However when something else has the sound card open, Java apps quickly break with both your error and "javax.sound.sampled.LineUnavailableException: Audio Device Unavailable".
One potential workaround is to enumerate all mixers in the system with AudioSystem.getMixerInfo(), then try to open the line with AudioSystem.getSourceDataLine(format, mixerInfo) for the mixers you want. Some will work better than others. In particular the "Java Sound Audio Engine" and the "default [default]" mixers, if they exist, tend to work.
The only solution if you don't want to modify the FreeTTS source code though, is to install pulse-java. This registers a special PulseAudio sound provider, which bypasses the ALSA virtualization and goes directly to PulseAudio. Ubuntu installs this as part of its OpenJDK package.
Someone should really patch Java Sound to play with ALSA in a friendlier way. For one ALSA device names should be prefixed with plug: to get ALSA to convert sound formats and sample rates on the fly. And the other rules for safe ALSA subset should also be followed.
Hmm, I had better luck googling after asking the question, so...:
http://workorhobby.blogspot.com/2011/02/java-audio-freetts-line-unavailable.html
A big thanks to the author.
Update: Actually, this is not a nice workaround since it will keep FreeTTS on hold until the line is free.
FWIU, the mentioned patch had better solution - not demanding exclusive access or such.
Update: I've compiled a FreeTTS troubleshooting page.
A program based on FreeTTS, the free text-to-speech engine for Java, was getting occasional errors
"LINE UNAVAILABLE: Format is ..."
Turns out there is no Java Exception or other mechanism to detect this error that occurs inside the FreeTTS library. All you get is the message on System.out, so there is no good way to react programatically.
Workaround: Configure the FreeTTS audio player to attempt accessing the audio device more than once until it succeeds. In this example, a short delay of 0.1 seconds is used to not miss an opportunity to grab the audio device; we keep trying for 30 seconds:
System.setProperty("com.sun.speech.freetts.audio.AudioPlayer.openFailDelayMs", "100");
System.setProperty("com.sun.speech.freetts.audio.AudioPlayer.totalOpenFailDelayMs", "30000");
If the audio device is permanently used by another program, there is of course no way to get access. Under Linux, this command will display the ID of the process that is currently holding the audio device, so you can then try to get rid of the offending program:
/sbin/fuser /dev/dsp
Regarding the link screwed by Oracle - given that older SO answer you refer mentions horrendous java linux sound bug that is still not fixed and suggests to check the third post, it is likely that lost thread was migrated to:
https://forums.oracle.com/forums/thread.jspa?threadID=2206163
above thread starts with reference to JMF Bug 4352921 at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4352921_
third post in the thread says "Yes, according to the API docs it's a "catastrophic" error from which no player can return safely. Which is why it's so strange to be able to trigger it so easily..."
workaround to the problem discussed is described in the sixth post as follows:
I stumbled upon a blog post that suggested that Java needs to be told to use the OSS libraries as it's not yet up to ALSA. The command to use was "padsp" which forces the application to use OSS. So if I call "padsp jmstudio", it now plays and mixes the audio just fine. I tried it with my application also, which prefetches a number of players in the same JVM, and they all prefetched perfectly. So it would seem, for now, JMF applications on Linux may need to be called through padsp.
I would have thought that this would be an easy thing to do, but no amount of googling around has turned up any solutions.
I have written an application for a client that runs in full screen and allows the user to page through educational books in order to help teach kids to read. So far so good. Some phrases from the displayed materials are read back to the user and, again, so far so good. Normally, these sounds are read at the system volume. (ie, at whatever volume any other system sound would be played.)
The client, however, now wants the user to be able to adjust the volume in program. I have the UI and processing end of that working, but I'm having a hard time adjusting the volume of the clips being played in a meaningful way. Right now I have a funky setup that involves reading the original gain of the clip and then adjusting that up or down for each clip. While this does adjust the volume, it does not seem to do it relative to the system volume -- all of the sounds are much quieter than the system volume.
So, my question really is: how do you suggest controlling sound volume within a program? All of my research has turned up nothing meaningful, which implies to me that it's kind of hard or even impossible, but that just doesn't seem right.
Oh, details: I'm reading in WAVs as AudioInputStreams and playing them as java.sound.sampled.Clip. I'm controlling the gain using FloatControl.Type.MASTER_GAIN. (FloatControl.Type.VOLUME is not supported.) I'm stuck using Java 1.4.
You might also look to see if there is an older version of the Java Media Framework (JMF) that will support Java 1.4... it might provide you with a more rich environment for working with audio.
Other than that, you say you are stuck in 1.4... you might see if there is any way you can get upgraded to Java 5 or 6, though you may want to test either of these first on your local machine to see if they actually help any.
I guess one last suggestion is to find some Java game development sites and post your question there; I would think they would have figured out ways around it... though you could also get a lot of 'upgrade your jvm' responses there too. :-)
Good luck.
This is an OS-specific thing to do, and you'll have to use either JNI or J/Invoke or JNIWrapper or jna or...
I am trying to make an application in which one component captures the screen of the user (for screen casting). I am aware that there are two options to achieve the same using a Java applet (please correct me if I am wrong). First is to use the java applet to take screen shots continuously and convert it into a video and upload it as a video file. And second is to create a java vnc server and record it as a .fbs file and play it using a player like: http://www.wizhelp.com/flashlight-vnc/index.html
I would like to know the best solution in terms of video quality, file size, cross-platform compatibility (windows and mac), firewall problems and finally ease of implementation.
I am very new to Java. Please tell me whats the best solution for my problem. Also, is it easy enough for me to program it on my own or should I get it developed via a freelancer. I have tons of programming experience (5+ years in LAMP) but none in Java.
Thank you very much.
I agree that this is pretty hard. I implemented those two solutions (VNC and onboard screen capture) plus a third (capture from an external VGA source via an Epiphan grabber) for a former employer. I had the best bandwidth-to-quality ratio with VNC, but I got higher framerate with VGA capture. In all three cases, I reduced the frames + capture times to PNGs and sequenced them in a QuickTime reference movie. Then I made flattened video (MPEG4 or SWF) of the results. In my case, I then synchronized the screen video with a DV stream.
In the end the technology worked (see a sample of the output) but our business model failed.
From what I know, the older versions of applet had security restrictions that may not allow for screen capture. Instead, a java application may be feasible.
Regarding the build-it-yourself vs the fire-a-coder, it depends on how you value your time compared to what you can find on a freelancer site.
I think you can find someone from India/Romania/Poland/Other countries that can make it for an affordable price
Given your Java knowledge and the difficulty of the task, have you considered taking an alternative approach? For example, how about a native VNC server for the end-user, which is just a small download and then they click "Run." And that native server is programmed to capture the screen and send it straight to your web server, which has a client like vnc2swf or other means of converting the VNC stream to a video or .fbs file? Does all that make sense?
Admittedly, without Java, you have to prepare one executable program per platform you want to support, however, I don't know. That still sounds easier to me. Consider Copilot.com. They are doing VNC but they still use small native apps for each platform.
Sorry but this seems the kind of job that requires a lot of experience. Even if you find code snippets all around the net to fix this and that, the overall result may be way worse than simply hiring an experienced Java programmer.