reading rtmp streaming using OpenCV in java - java

objective:
translate a python code that makes use of opencv into java.
issue:
inability to capture rtmp stream in the java version
details:
it's a drone control base code for a 4G drone that streams its camera feed to a nodejs rtmp server. the following is its code:
const { NodeMediaCluster } = require('node-media-server');
const numCPUs = require('os').cpus().length;
const config = {
rtmp: {
port: 1935,
chunk_size: 600000,
gop_cache: false,
ping: 60,
ping_timeout: 30
},
http: {
port: 8000,
allow_origin: '*'
},
cluster: {
num: numCPUs
}
};
var nmcs = new NodeMediaCluster(config)
nmcs.run();
then the stream is captured by the control base (for further operations involving opencv functionalities)
in the python version code, i used
cap = cv2.VideoCapture('rtmp://192.168.1.12:1935/live/STREAM_NAME')
to read from the server on test local network.
in java , i downloaded the official opencv tutorial sample app located here. it's a tutorial for how to use VideoCapture objects to read from one's webcam.
like i did before in python, i replaced the argument 0 (for first cam) to the rtmp url :
//private static int cameraId = 0;
String cameraId = "rtmp://192.168.1.12:1935/live/STREAM_NAME";
/**
* The action triggered by pushing the button on the GUI
*
* #param event
* the push button event
*/
#FXML
protected void startCamera(ActionEvent event)
{
if (!this.cameraActive)
{
// start the video capture
this.capture.open(cameraId);
this.capture.isOpened() returns false.
and no connection attempt is made to the server
can you kindly point out where did i go wrong ?

it took me a couple of hours to realize what is wrong. the issue has been already addressed and solved here

Related

How to let a sound play once in Processing?

import processing.serial.*;
import processing.sound.*;
SoundFile file;
Serial myPort; // Create object from Serial class
String val; // Data received from the serial port
//String antwoord = "A";
void setup()
{
size(300,300);
// I know that the first port in the serial list on my mac
// is Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
}
void draw()
{
if ( myPort.available() > 0)
{ // If data is available,
val = trim( myPort.readStringUntil(ENTER) );
// read it and store it in val
}
//println(val); //print it out in the console
file = new SoundFile(this,"Promise.mp3");
if ("A".equals(val) == true && file.isPlaying() == false) {
file.play();
file.amp(0.2);}
else{
ellipse(40,40,40,40);
}
}
I got this code, but I want the sound to keep playing as long as the signal 'A' is given. Now it starts playing constantly, which leads to a weird static noise. How can I make it just play steadidly?
You're creating a new SoundFile in every run of draw. So file.isPlaying() will always return false. Only create a new SoundFile if you haven't already. The simplest solution is probably to move file = new SoundFile(this,"Promise.mp3"); into setup
Or you check or remember if you already loaded the file.
I am sorry if it is a bit disconnected but I recommend using minim or a different sound library instead of the processing one, since it causes a lot of problems in exporting (at least it had done so consistently for me).

Why is GetExternalFileDirs not working in android?

I am working on a sample project in unity android where application reads a textfile in an OTG pen drive connected to the android phone, the problem is my code works fine in some devices but it doesn't work in some devices. I am unable to figure out the main cause even through the logcat extreme as it doesn't throw any error at all that specifies code error.
I tried adding text logs to print text in between the code to see which texts are not printed, which would further tell me that after which line code stopped working but all the texts are printed.
This is my code that detects the USB and returns true if a text file is present in USB:
public void LocateFile()
{
textfileData = null;
using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
using (AndroidJavaObject context = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
{
// Get all available external file directories (emulated and USBdrives)
AndroidJavaObject[] externalFilesDirectories = context.Call<AndroidJavaObject[]>("getExternalFilesDirs", (object)null);
AndroidJavaObject emulated = null;
AndroidJavaObject USBdrive = null;
for (int i = 0; i < externalFilesDirectories.Length; i++)
{
AndroidJavaObject directory = externalFilesDirectories[i];
using (AndroidJavaClass environment = new AndroidJavaClass("android.os.Environment"))
{
bool isRemovable = environment.CallStatic<bool>("isExternalStorageRemovable", directory);
bool isEmulated = environment.CallStatic<bool>("isExternalStorageEmulated", directory);
if (isEmulated)
{
emulated = directory;
}
else if (isRemovable && isEmulated == false)
{
USBdrive = directory;
}
}
}
// Return the USBdrive if available
if (USBdrive != null)
{
if (File.Exists(USBdrive.Call<string>("getAbsolutePath") + "/serial.txt"))
{
textfileData = File.ReadAllText(USBdrive.Call<string>("getAbsolutePath") + "/serial.txt");
}
}
}
}}
This code works on my android phone and returns true after detecting the file present in pendrive.
Can anyone tell me what could be the issue and point me in the right direction, I will greatly appreciate your support on this.
This locateFile() function is called on Update().
Update: I tried to debug the number of storage found in mobile and code is not reading the USB. It reads internal and SD storage perfectly.
Nokia 5 is the only phone the code has worked on so far but in 99% android devices GetExternalFilesDir is not reading usb storage.
Please someone tell me an alternate or how do I get this to work, it is very important.

Create OBD2 MUT scanner by using Java FTDI lib - jd2xx - openport1.3 usb cable

I am trying to create a Java obd2 scanner app for my mitsubishi lancer mx 1997 which use MUTII protocol over OBD2. Can anybody help me to read MUT request codes using jd2xx library.
I have tried the below program, but it didn read engine RPM.
package lancerscan;
import jd2xx.JD2XX;
public class Test2 {
public static void main(String[] args) throws Exception {
JD2XX jd = new JD2XX();
jd.open(0);
jd.setBaudRate(38400);
jd.setDataCharacteristics(
8, JD2XX.STOP_BITS_1, JD2XX.PARITY_NONE);
jd.setFlowControl(
JD2XX.FLOW_NONE, 0, 0);
jd.setTimeouts(1000, 1000);
String msg = "21";
int ret = jd.write(msg.getBytes());
System.out.println(ret + " bytes sent.");
int rd = jd.read();
System.out.println(">>>" + rd);
int status = jd.getQueueStatus();
byte[] data = new byte[(int) status];
long lngBytesReturned = jd.read(data, 0, data.length);
System.out.println("======= " + lngBytesReturned);
}
}
MUT request code for Engine RPM is 0x21
more MUT request codes can be found here
similar C programs which works fine is here; main prjct files are here
Thanks,
harsha
First your using a different baud rate to that in the example. The example uses 15625 baud but you are using 38400 baud.
Secondly you are missing some of the setup commands. I am not sure if this will make a difference but its something that is different between your code and the example.
Mitsubishi require you to set the car ECU into diagnostic mode by sending 0x00 at a rate of 5 baud on one of the pins. On the OpenPort 1.3D cable this translates to setting the break to on for 1800 ms and then turning it off. You can see this is done with the ftdimut_init() command from the libftdimut.c file.
printf("Sending 0x00 at 5 baud\n");
printf("Break on......\n");
ftStatus = FT_SetBreakOn(ftdimut_ftHandle);
if(ftStatus != FT_OK) return ftStatus;
ftdimut_msleep(1800);
printf("Break off......\n");
ftStatus = FT_SetBreakOff(ftdimut_ftHandle);
if(ftStatus != FT_OK) return ftStatus;
The car ECU will then send you 4 bytes containing the ECU ID. This can then be used to check the ECU correctly entered diagnostic mode. You can see this in libftdimut.c.
ftStatus = FT_Read(ftdimut_ftHandle, buf, 4, &bytesRead);
if(ftStatus != FT_OK) return ftStatus;
if(bytesRead == 4) {
return FT_OK;
}
Now assuming that you got the 4 bytes back you can start to send the diagnostic codes such as 0x17 or 0x21.
I just saw your post on my blog, niallm answer is correct, you need to do a 5 baud init first which involves driving the KLine, you can use something like the 5 baud init posted in that answer, more info about the protocol:
http://evoecu.logic.net/wiki/MUT_Protocol
After getting a 4 byte response you can start sending requests at 15625 baud (I'm communicating with a 94 3000GT so the CEL light stops blinking), also in my case I send the converted values (0x21 = 33 decimal) as a byte array.

Correct using VLCj

I try to use VLCj to get access to web-cameras. I am using this code:
public static void main(String[] args) {
// Create player.
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory();
DirectMediaPlayer mediaPlayer = mediaPlayerFactory.newDirectMediaPlayer(
320, 240,
new RenderCallback() {
#Override
public void display(Memory arg0) {
// Do nothing.
}
});
// Options setup.
String[] options = new String[]{};
String mrl = "v4l2:///dev/video0"; // Linux
// Start preocessing.
mediaPlayer.startMedia(mrl, options);
BufferedImage bufImg;
for (int i = 0; i < 1000; ++i) {
bufImg = mediaPlayer.getSnapshot();
// Do something with BufferedImage...
// ...
}
// Stop precessing.
mediaPlayer.stop();
mediaPlayer = null;
System.out.println("Finish!");
}
And this code partially works -- I can get and work with BufferedImage, but:
I got an error in to output: [0x7f0a4c001268] main vout display error: Failed to set on top
When main loop is finished and camera was disabled program don't finished! I see Finish! message, but program not return control into IDE or console.
UPD:
I am using openSUSE 12.2 x64, VLC 2.0.3 installed and working properly for all video files, library VLCj 2.1.0.
This code working properly:
public static void main(String[] args) {
// Configure player factory.
String[] VLC_ARGS = {
"--intf", "dummy", // no interface
"--vout", "dummy", // we don't want video (output)
"--no-audio", // we don't want audio (decoding)
"--no-video-title-show", // nor the filename displayed
"--no-stats", // no stats
"--no-sub-autodetect-file", // we don't want subtitles
"--no-inhibit", // we don't want interfaces
"--no-disable-screensaver", // we don't want interfaces
"--no-snapshot-preview", // no blending in dummy vout
};
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory(VLC_ARGS);
// Create player.
HeadlessMediaPlayer mediaPlayer = mediaPlayerFactory.newHeadlessMediaPlayer();
// Select input device.
String mrl = "v4l2:///dev/video0"; // Linux
// Start processing.
mediaPlayer.startMedia(mrl);
BufferedImage bufImg;
for (int i = 0; i < 1000; ++i) {
bufImg = mediaPlayer.getSnapshot();
// Do something with BufferedImage...
// ...
}
// Stop processing.
mediaPlayer.stop();
// Finish program.
mediaPlayer.release();
mediaPlayerFactory.release();
}
Re your native window: VLCj opens a shared instance to the VLC library.
A headless media palyer is NOT intended to have a video or audio output!
In fact, if you need anything to play (and not to stream to anywhere else) you need to create either an output window or use a direct media player (may be much more complicated)
So, if a headless player needs to play something it opens a native window to perform the playback!
Source: http://www.capricasoftware.co.uk/wiki/index.php?title=Vlcj_Media_Players
Re the error: the video display component MUST be the top component of the panel, window or whereever it is added to. Otherwise it will throw the error
main vout display error: Failed to set on top
Furthermore, if you put anything over the component it will destroy the video output which won't work anymore!
Anyway, I don't know how the DirectMediaPlayer works in detail but VLCj has some weird behaviour... Maybe getSnapshot() needs a video display component but I'm not sure.
Re your not finishing program: you join to finish your own thread. This can't work because your thread "sleeps" until the other thread who is waited for has been terminated but as this is your own thread it "sleeps" and won't terminate.
You can test this behaviour with this short code in a main method:
System.out.println("Test start");
Thread.currentThread().join();
System.out.println("Test stop");
You will NEVER reach the "Test stop" statement.

Efficiently streaming audio samples retrieved from a java object in Gecko (firefox extension)

I am writing a firefox extension which needs to play a certain PCM stream. The samples are retrieved from a java module over LiveConnect:
Java code:
public class Synthesizer
{
...
public
float[] synthesizeFloats(int[] symbols)
{
// Some code to generate 32bit float PCM samples
...
return floatSamples;
}
...
}
Javascript code:
scream: function(samples)
{
var start = 0;
var elapsed = 0;
start = (new Date()).getTime();
var floatSamples = new Float32Array(samples);
elapsed = (new Date()).getTime() - start;
Firebug.Console.log("Converting array (2) - Elapsed time in ms " + elapsed);
var modulationProperties = this.defaultModulationProperties();
var audio = new Audio();
audio.mozSetup(1, modulationProperties.sampleFrequency);
var written = 0;
while (written < floatSamples.length) {
written += audio.mozWriteAudio(floatSamples.subarray(written));
}
},
// Synthesizer class was loaded and instantiaded over LiveConnect
var samples = synthesizer.synthesizeFloats(symbols);
scream(samples);
The above code works but very slowly. It appears that converting the java byte array into a Float32Array is quite expensive. The conversion is necessary as one can't pass a java byte array to the mozWriteAudio function.
My questions are:
Is there a way to do the conversion more efficiently?
Is there a way to make the java code return a Javascript Float32Array object instead a java object?
Is there a java implementation that allows playing PCM audio that may be used in a firefox extension? Using that java implementation from withing the javascript code will not necessitate the above conversion.
Any other ideas / directions would be appreciated.

Categories