VLCJ dynamically modify frames while streaming - java

My project has two parts. First one is to stream a video and second is to capture streamed video and analyze it. it's been done the capture and analyze side.
While i'm doing this, I've made a workaround for my question; i convert video into BufferedImages and saved to image files. Then i edit images files and convert back to video again. Finally i can stream edited video and do the other capture and analyze part.
But since this workaround is a long-timed process and frame edits must be done simultaneously and dynamically according to my real-life use, i must interfere just before the frames are being streamed.
I made lots of searching but maybe i'm not familiar with streaming and its terms and couldn't find a way to do it with vlcj and java. Actually, to solve this problem, I don't necessarily have to stick with java and vlcj. If vlcj doesn't provide a solution, all other suggestions are will be fine.
And here is the code i use to stream from a video file below;
private void Stream () throws InterruptedException {
String media = "C:\\someVideo.mp4";
String options = formatRtpStream("127.0.0.1", 5555);
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory();
EmbeddedMediaPlayer mediaPlayer = mediaPlayerFactory.mediaPlayers().newEmbeddedMediaPlayer();
mediaPlayer.media().prepare(media,
options,
":no-sout-rtp-sap",
":no-sout-standard-sap",
":sout-all",
":sout-keep"
);
}
private static String formatRtpStream(String serverAddress, int serverPort) {
StringBuilder sb = new StringBuilder(200);
sb.append(":sout=");
sb.append("#transcode{vcodec=h264,vb=1000,fps=25,scale=1,noaudio}");
sb.append(":rtp{dst=");
sb.append(serverAddress);
sb.append(",port=");
sb.append(serverPort);
sb.append(",mux=ts}");
return sb.toString();
}

Related

Encoding Images Into Video with JCodec Errors

I need to encode multiple images (Of which I have the complete path) into a video of a certain FPS on android.
Trials:
How to create a video from an array of images in Android?
Why I couldn't get it to work:
I added the Jcodec Dependecy to gradle file (
compile 'org.jcodec:jcodec:0.2.3'
compile 'org.jcodec:jcodec-android:0.2.2'
)
I then pasted the code into a function and this is what I get:
As You can see I managed to import SequenceEncoder (import org.jcodec.api.SequenceEncoder;)
But it doesn't recognize Buffered Image (I think it's because I have to use Bitmap)
And it gives me an error in the SequenceEncoder.
Also doesn't recognize the encodeImage Method.
Then I tried with the code I found on JCodec webSite:
SeekableByteChannel out = null;
try {
out = NIOUtils.writableFileChannel("/tmp/output.mp4");
// for Android use: AndroidSequenceEncoder
AWTSequenceEncoder encoder = new AWTSequenceEncoder(out, Rational.R(25, 1));
for (...) {
// Generate the image, for Android use Bitmap
BufferedImage image = ...;
// Encode the image
encoder.encodeImage(image);
}
// Finalize the encoding, i.e. clear the buffers, write the header, etc.
encoder.finish();
} finally {
NIOUtils.closeQuietly(out);
}
But it doesn't recognize AWTSequenceEncoder and thus the methods encodeImage and finish.
What am I doing wrong?
Ok, I found the Answer to the problem, technically it is in the answers of this question:
How to create a video from an array of images in Android?
But has only two votes, despite being the only one that worked for me and for what I found out the only one that should work. You cannot use BufferedImages in android, while the most voted quesion do and the SequenceEncoder that I didn't find is replaced with AndroidSequenceEncoder.

Passing buffer from SuperpoweredAndroidIO to Java InputStream / Android NDK

I am using the amazing Superpowered library (SuperpoweredAndroidAudioIO) for low-latency recording of audio. While the basic concepts are clear to me, I want to pass the recorded audio (which arrives in a buffer) back to an InputStream in Java (without recording to a file), from which I can then read the recorded audio and process it.
I guess this question could also be more generally asked - how to feed an InputStream in Java from a periodically updated buffer in C++?
Well, the suggestion I received in a comment turned out to be a simple and working solution:
Creation of pipe in C++:
if (pipe(pipefd) == -1) {
__android_log_print(ANDROID_LOG_VERBOSE, "C++", "Error creating pipe");
}
...
Passing file descriptor to Java:
...
return pipefd[0];
...
Then in Java/Android:
private ParcelFileDescriptor.AutoCloseInputStream underlyingStream;
ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(getFD());
underlyingStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
Worked well for me, but of course I'm still happy to receive other suggestions.

How to analyze a photo sent through JSON

I have a Web Service that takes a photo through a POST statement and returns a modified copy of that photo back. We are making changes to the way it processes the photo, and I want to verify that the photo at least has different properties coming back than it did before our changes went into effect.
The photo is being returned as a byte stream inside one of the fields of a JSON object. I can analyze the JSON object pretty easily, but I'm trying to figure out how to get the byte stream into an Java image object so that I can get its dimensions.
Possible duplicate of this question
... I'm trying to figure out how to get the byte stream into an Java image object so that i can get its dimensions.
I'd suggest using a BufferedImage in the following format/snippet. Note: I load my image in from disk for the example and use try-with-resources (which you may revert to 1.6-prior if needed).
String fp = "C:\\Users\\Nick\\Desktop\\test.png";
try (FileInputStream fis = new FileInputStream(new File(fp));
BufferedInputStream bis = new BufferedInputStream(fis)) {
BufferedImage img = ImageIO.read(bis);
final int w = img.getWidth(null);
final int h = img.getHeight(null);
}
You can use:
OS Process Sampler and 3rd-party tool like ImageMagick
JSR223 Test Elements, to wit
JSR223 PreProcessor to get information on the photo, you're trying to upload
JSR223 PostProcessor to get information on the photo, returned by the Web Service
JSR223 Assertion to compare two photos
Depending on what parameters you need to compare you can use ImageIO API (out of the box, bundled with JDK), Commons Imaging, ImageJ and so on.

ZXing library can't decode Datamatrix barcode

I'm trying to use ZXing library to decode Datamatrix barcode. Here are my code sample:
BufferedImage bi = img.getBufferedImage();
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
LuminanceSource source = new BufferedImageLuminanceSource(bi);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
DataMatrixReader dataMatrixReader = new DataMatrixReader();
try {
Result res = dataMatrixReader.decode(bitmap,hints);
System.out.println("resultText = "+res.getText());
} catch (Exception e) {
System.out.println("failed to get resultText");
e.printStackTrace();
}
I've seen almost the same samples many times accross https://stackoverflow.com/ and other sites, but this approach does not working for me in this form.
As a source I'm using images grabbed from IR-camera. Here are example image:
As you see, the barcode is almost exactly at the center of an image, as Sean Owen recommended here and here. If I programmatically convert this image to black&white and crop image to bound barcode with some white space around it only, then ZXing works perfectly with images like this. But the problem is that barcode in real could have little deformations, so my simple algorythm can't help me to crop image properly. More over barcode could be placed not exactly in the center of an image and cold have a little bit different brightness. I saw threads mentioning OpenCV capabilities to find out placement of speciects objects on the image, like this one, but they are quite old. Is something changed since then? And what should i yet certainly consider to write 100% reliable datamatrix decoder (and detector) in my specific situation?
I decided to supply LuminanceSource and BinaryBitmap images made of .toString() text output of correcponding objects for reference:
http://s28.postimg.org/l53sykhx9/Binary_Bitmap.png
and /65z0vlbpl/Luminance_Source.png (at the same domain). They are looking good and ready for decoding, but what is wrong with decoding then.
After all this image and similar ones recognized and decoded very well with smartphone software and i'm just wanted achieve same results.
you need to enable it from settings programmatically or manually.
in class DecodeThread.java you can see the line that enables data matrix encoding
decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);

What library can I use to encode video in a Java Applet?

I would like to record the user's interaction in my Java Applet as a video to send (potentially stream) to my server with the intention of uploading to Youtube (or similar). A high frame-rate is not required (a couple frames per second is sufficient).
Minimizing the bandwidth used is preferred, so sending jpeg snapshots to the server and encoding server-side is my last resort.
Are there any lightweight Java video encoding libraries available that don't require native code?
I'm new to java so don't take this to seriously :)
I guess a good start with video encoding in java is Java Media Framework.
I haven't tried it, so I don't know what's they're support on flv encoding.
Since Flash Media Server is commercial, couldn't you use Red5 ?
You would have a swf, not an applet, but you will get a broader percentage of viewers since Flash Player is pretty wide spreaded.
And Alex has a good point, since you need to upload the video to youtube, why not use they're API ?
hth
Xuggler can be used to encode pretty much any format from Java, but it requires a native component to be installed with it. There isn't an applet version available in the easy to use download, but some users have built custom versions of FFmpeg and Xuggler that they have used in downloadable applications. Try asking on the xuggler-users user group to see if others will help.
You can encode your images into H.264/MP4 this way it would be immediately good for web streaming. To upload it in parallel to recording you can break up your sequence into small chunks, let's say 25-100 images each and upload each chunk as a separate movie.
You can do it in pure Java without any native code, just use JCodec ( http://jcodec.org ). Here's a handy class that you can use:
public class SequenceEncoder {
private SeekableByteChannel ch;
private Picture toEncode;
private RgbToYuv420 transform;
private H264Encoder encoder;
private ArrayList<ByteBuffer> spsList;
private ArrayList<ByteBuffer> ppsList;
private CompressedTrack outTrack;
private ByteBuffer _out;
private int frameNo;
private MP4Muxer muxer;
public SequenceEncoder(File out) throws IOException {
this.ch = NIOUtils.writableFileChannel(out);
// Transform to convert between RGB and YUV
transform = new RgbToYuv420(0, 0);
// Muxer that will store the encoded frames
muxer = new MP4Muxer(ch, Brand.MP4);
// Add video track to muxer
outTrack = muxer.addTrackForCompressed(TrackType.VIDEO, 25);
// Allocate a buffer big enough to hold output frames
_out = ByteBuffer.allocate(1920 * 1080 * 6);
// Create an instance of encoder
encoder = new H264Encoder();
// Encoder extra data ( SPS, PPS ) to be stored in a special place of
// MP4
spsList = new ArrayList<ByteBuffer>();
ppsList = new ArrayList<ByteBuffer>();
}
public void encodeImage(BufferedImage bi) throws IOException {
if (toEncode == null) {
toEncode = Picture.create(bi.getWidth(), bi.getHeight(), ColorSpace.YUV420);
}
// Perform conversion
transform.transform(AWTUtil.fromBufferedImage(bi), toEncode);
// Encode image into H.264 frame, the result is stored in '_out' buffer
_out.clear();
ByteBuffer result = encoder.encodeFrame(_out, toEncode);
// Based on the frame above form correct MP4 packet
spsList.clear();
ppsList.clear();
H264Utils.encodeMOVPacket(result, spsList, ppsList);
// Add packet to video track
outTrack.addFrame(new MP4Packet(result, frameNo, 25, 1, frameNo, true, null, frameNo, 0));
frameNo++;
}
public void finish() throws IOException {
// Push saved SPS/PPS to a special storage in MP4
outTrack.addSampleEntry(H264Utils.createMOVSampleEntry(spsList, ppsList));
// Write MP4 header and finalize recording
muxer.writeHeader();
NIOUtils.closeQuietly(ch);
}
}
Why do you need to send the images or video form directly? Sounds like a big bandwidth expense. Just serialize and send the stream of UI events with timestamps, and reconstruct what the user should be seeing on your server later (some visual details may depend on the user's machine/setup, but your applet ain't gonna be able to get to them decently anyway).

Categories

Resources