I'm using BufferedImage to capture the screen images and then JpegImagesToMovie class to convert it to .mov, which I found online.
When I run the output file, it's at a super speed and not the original speed I recorded at. Can someone tell me what need to do in order to get a real-time speed video?
You probably need to put in Thread.sleep(1 / fps). Try to see if that works.
You are possibly using the Oracle's example to convert images to .mov. The problem is that the size of the file generated is very very large. You need to move to something more efficient and something with a little bit more abstraction. How about using Xuggler for making screen recorder ?
Now, to the question of making the movie slower. You need to reduce the frame rate. If you have need 60 fps, your 1 second will need to be shared by 60 frames. So for n fps, you need to have (1/n) sleep duration for your thread.
Related
I'm using MediaExtractor/MediaCodec to decode a video and render it to a TextureView. As a template, I've used the code from: https://github.com/vecio/MediaCodecDemo/blob/master/src/io/vec/demo/mediacodec/DecodeActivity.java
I'd like to be able to playback the video at 2x speed. Luckily, the media encoding/decoding is fast enough so that I can accomplish this by letting the MediaCodec decode every frame, and then only render every other frame to the screen. However this doesn't feel like a great solution, particularly if you want to increase playback by an arbitrary value. For example, at 10x speeds, the Codec is not able to decode frames fast enough to playback every 10th frame at 30 fps.
So instead I'd like control playback by calling MediaExtractor.advance() multiple times to skip frames that don't need to be decoded. For example:
...
mDecoder.queueInputBuffer(inIndex, 0, sampleSize, mExtractor.getSampleTime(), 0);
for (i = 0; i < playbackSpeedIncrease; i++) {
mExtractor.advance();
}
...
With this code, in theory the extractor should only extract every nth frame, where n is defined by the variable 'playbackSpeedIncrease'. For example, if n = 5, this should advance past frames 1-4 and only extract frame 5.
However, this does not work in practice. When I run this code, the image rendered to the screen is distorted:
Does anyone know why this is? Any suggestions for better ways to playback videos at an arbitrary speed increase?
You can't generally do this with AVC video.
The encoded video has "key" (or "sync" or "I") frames that hold full images, but the frames between key frames hold "diffs" from the previous frames. You can find some articles at wikipedia about video encoding methods, e.g. this one. You're getting nasty video because you skipped a key frame and now the diffs are being computed against the wrong image.
If you've ever seen video fast-forward smoothly but fast-reverse clunkily, e.g. on a TiVo, this is why: the video decoder plays forward quickly, but in reverse it just plays the I-frames, holding them on screen long enough to get the desired rate. At "faster" forward/reverse it evens out because the device is just playing I-frames. You can do something similar by watching for the SAMPLE_FLAG_SYNC flag on the frames you get from MediaExtractor.
In general you're limited to either playing the video as fast as the device can decode it, or playing just the key frames. (If you know enough about the layout of a specific video in a specific encoding you may be able to do better, e.g. play the I and P but not the B, but I'm not sure that's even possible in AVC.)
The frequency of I frames is determined by the video encoder. It tends to be one or two per second, but if you get videos from different sources then you can expect the GOP size (group-of-pictures, i.e. how many frames there are between I-frames) to vary.
How to -
1.get the current frame position of an audio/video track ??
2.how to go to a specific frame position of a track ??
using vlcj sdk .
any code snippets would be highly appreciated !
Actually you can do this with a little math. It's not the cleanest way but it is kind of easy to understand.
VLCj allows you to get the length of your media using .getLength(). However, note that this returns the length of the media in milliseconds. Moreover, you can get the frames/second of your media using .getFPS().
So now you can get the total number of frames as:
total_frames = .getFPS * .getLength() /1000;
Then you can use .getPosition() to find out where you currently are in milliseconds, you can then translate that to a frame. This returns as a percentage.
current_frame = .getPosition() * total_frames;
Now, if you want to go to a specific frame let's call that desired_frame. You can use the .setPosition() which takes in a percentage. So you need to determine the percentage of the total that represents the frame you want to jump to.
.setPosition((float)desired_frame/total_frames);
VLCJ isn't really set up for this kind of frame by frame access directly - you can use setTime() and getTime() on the mediaplayer object, but that will return time from the beginning in milliseconds rather than the frame. Of course, if you know the frame rate it's then relatively trivial to convert from one to the other.
If you need lower level operations than VLCJ provides, then you may want to have a look at Xuggler.
I would like to control the speed of an animated GIF in a Java applet. Is there a way to do this? If not, is there a way to access the data of an animated GIF so the applet can draw the animation image by image on its own?
I think that the frame rate is embedded into the GIF. You could somehow extract the images from the GIF, but that's harder than starting with the individual images and animating them in JS, which is harder than recreating the GIF with your preferred frame rate.
If you're going to use the GIF only once and the frame rate isn't going to change, just recreate the GIF. If you need to change the speed based on inputs from your applet, you could use the approach here. It alternates between two gifs, but there's nothing stopping you from loading in PNGs and alternating through an Array of those.
The animated GIF format is consists of data for each frame along with a delay value (how long to show that frame). The delay is separate for each frame, and is stored as two bytes and measures as hundred's of a second.
Netscape (back when it was the web), couldn't show the frames faster than 10 per second. So lots of tools just said screw it, and set delay for all the frames to 0. Lots of old gifs and old tools, have keep these screwed up frame delay times around.
With faster computers and browsers, they worked around this by checking if any of the frames had a delay <= 50ms (20+ fps). IF they did, the delay was increased to 100ms (10fps).
In principle, the best solution would be to just fix the GIF you're using to have accurate frame delays in them. If that isn't viable, use that same old workaround. Break the frames out of the animated GIF and do the animation yourself, defaults to a 100ms delay if the specified delay is <= 50ms. This will give you the same behavior as what you see in most web browsers.
Read about this a while ago. Think most of the details on mentioned on wikipedia (including the animated GIF format and the per frame delays). If it you really want some solid references, I can dig them for you.
This is a bit of a followup to my last question: Canvas is drawing too slowly
Now that I can draw images more quickly, the problem I am faced with is that the actual loading of the images takes far too long.
In the app I am working on, the user is able to play back video frames (jpegs) in succession, as though he is viewing the video in realtime. I have been using BitmapFactory.decodeFile() to load each jpeg in a Bitmap. I'm unable to load all images at once since there are about 240 of them, and that would use up all of my heap space. What I have been doing is preloading up to 6 at a time into an array by way of a separate thread in order to cut down on the time it takes for each image to display.
Unfortunately, it takes somewhere between 50 and 90ms to load an image, and I need to show an image every 42ms. Is there a faster way to load images possibly?
For clarification, these images are in a folder on the SD card, and they are all 720x480 jpegs. I am sampling them at half that size to cut down on memory usage.
I ended up doing this quite a bit differently than I had originally envisioned. There was quite a bit to it, but here's the gist of how I achieved my goal:
All images are stored on SD card and written to one file (each image takes up X bytes in the file)
Use native code to read from and write to the image file
When requesting an image, I pass the index of the image in the list and a bitmap object (RGB_565) to the native code using a JNI wrapper
The native code locks the bitmap surface, writes pixel data (as a uint8_t**) directly to the bitmap, then unlocks it
The image is rendered to the screen
By doing it this way, I only needed to store one image in memory at a time, and I was able to bypass garbage collection (since the bitmap was only created once and then repopulated natively). I hope someone else might find this strategy useful.
Guess you already tried all methods in this tutorial http://www.higherpass.com/Android/Tutorials/Working-With-Images-In-Android/2/ and chosen the fastest. Maybe tweaking resizing can decrease loading time.
Best of all would of course be if you didn't have to resize the images at all. If you have full control of the images maybe you could try to pack them as sprites, see article http://www.droidnova.com/2d-sprite-animation-in-android,471.html
I need to an algorithm, to write frames (Pictures) into a file, which can be read by some Video-Cutting/Producing-Software to work with.
So I got frames, and I want to give them a input into a function/Method.
Let's do i in Java.
How can I do this?
Is there a simple way, I can write videofiles without using any systemcodecs?
I just need a uncompressed video with a constant Framerate (25 fps or 50 fps)
that will take my true-Color pictures (2D-arrays of Colors), so that I can use that video in my Videoprogramm to work with.
I never found any fileformat that fits to that.
Can You help me?
Greetings from Austria, and thanks. Flo.
Depending on the program you want to use to further process your movie you can also simply create PNGs (or TGAs or BMPs) for the single frames. VirtualDub e.g. can use images as frames for a movie.
The AVI container format can contain streams of uncompressed video, of which there are many types to choose from. Have a look here http://fourcc.org/ at the RGB and YUV formats, and here http://www.alexander-noe.com/video/documentation/avi.pdf for details on the AVI file format.