commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Raymond DeCampo <...@decampo.org>
Subject Re: [exec] Misconcepting PumpStreamHandler's way of working with streams?
Date Wed, 08 Feb 2017 23:54:29 GMT
OK, Edgar I pared your example down a bunch and got to a working demo.  I
submitted it as a pull request against the repo you created.  I think the
key thing was not re-using the executors.

This should be enough for you to start modifying it back into what you
needed it to be.

HTH,
Ray

On Mon, Feb 6, 2017 at 12:00 PM, Edgar H <kaotixpro@gmail.com> wrote:

> Completly forgot about ffmpeg being Windows compilation, sorry for that.
>
> I've already updated the git project, even though ffmpeg and Icecast still
> there (I don't really know why...) the new classes don't use them anymore.
>
>
> 2017-02-06 13:43 GMT+01:00 Raymond DeCampo <ray@decampo.org>:
>
> > Well, we are still going to run into issues when I try it on my Linux
> > machine.
> >
> > I'd suggest just leaving ffmpeg out of it.  Make a pair of simple Java
> > classes which take a file and output to standard out and then one which
> > reads from standard in and writes to a file; then a main class which
> starts
> > processes for the other two and hooks them up.
> >
> >
> > On Sun, Feb 5, 2017 at 7:04 PM, Edgar H <kaotixpro@gmail.com> wrote:
> >
> > > There it goes, here is the link for the git repo.
> > >
> > > https://github.com/turbobrick/exec_dmo
> > >
> > > I've included ffmpeg and also Icecast so you can start the server in
> your
> > > machine via console and see if the mount "/stream" is active at
> > > 127.0.0.1:8000 once you start streaming audio from the system via the
> > test
> > > app. An already compiled .jar from the SecondApp class has already been
> > > generated, and it is inside /bin folder in /ffmpeg. Everything should
> be
> > > ready to go.
> > >
> > > Thanks for helping, really appreciated.
> > >
> > > 2017-02-05 22:51 GMT+01:00 Raymond DeCampo <ray@decampo.org>:
> > >
> > > > If I were to try to run this on my system, it would fail because
> there
> > is
> > > > no ffmpeg.exe file on my machine.
> > > >
> > > > You need to make it easier for me to help you by making a truly
> > > > self-contained minimal example of the issue (see
> > > > http://www.catb.org/~esr/faqs/smart-questions.html#code for more
> > details
> > > > on
> > > > this).  Preferably the example will contain a pom.xml so it can be
> > built
> > > > easily and maybe put in on a gist in github so it can be downloaded
> > > easily.
> > > >
> > > >
> > > >
> > > > On Sun, Feb 5, 2017 at 3:46 PM, Edgar H <kaotixpro@gmail.com> wrote:
> > > >
> > > > > Sure, here's a minimal example.
> > > > >
> > > > > The following code belongs to a "MainApp" class, which is the
> > basically
> > > > the
> > > > > application which starts the .jar responsible of capturing live
> audio
> > > > data
> > > > > from the system and sending it live to FFMPEG, which streams to an
> > > > Icecast
> > > > > Server, like a continuous stream using pipes.
> > > > >
> > > > > public class MainApp {
> > > > >
> > > > >     public static void main(String[] args) {
> > > > >         initStream("Path to FFMPEG bin folder, which should include
> > the
> > > > > .jar of the second application that you need to copy and paste.");
> > > > >     }
> > > > >
> > > > >     public static void initStream(String path) {
> > > > >         File file = new File(path);
> > > > >         for (File s : file.listFiles()) {
> > > > >             if (s.getName().equals("ffmpeg.exe")) {
> > > > >                 try {
> > > > >                     DefaultExecutor executor = new
> DefaultExecutor();
> > > > >                     executor.setWorkingDirectory(file);
> > > > >
> > > > >                     CommandLine commandLine = new
> > > > > CommandLine(s.getParentFile().getAbsolutePath());
> > > > >                     System.out.println("Path: " +
> > > > commandLine.toString());
> > > > >
> > > > >                     String executeMe = "java -jar secondapp.jar";
> //
> > > > > Execute "SecondApp" .jar to start sending sound bytes to stdout.
> > > > >                     commandLine = CommandLine.parse(executeMe);
> > > > >
> > > > >                     PipedOutputStream output = new
> > PipedOutputStream();
> > > > //
> > > > > Fill this with bytes.
> > > > >                     PipedInputStream input = new
> PipedInputStream();
> > > > >                     output.connect(input); // Send audio bytes from
> > > > output
> > > > > to this input stream.
> > > > >
> > > > >                     executor.setStreamHandler(new
> > > > PumpStreamHandler(output,
> > > > > null)); // Stream all the bytes to the output.
> > > > >                     executor.execute(commandLine, new
> > > > > DefaultExecuteResultHandler()); // Execute APP2 (The one which
> > > captures
> > > > > the
> > > > > live audio bytes).
> > > > >
> > > > >                     String feedMe = "ffmpeg -f s16le -ar 48000 -ac
> 2
> > > -i -
> > > > > -f ogg -content_type application/ogg icecast://source:hackme@
> > localhost
> > > > > :8000/stream";
> > > > >                     commandLine = CommandLine.parse(feedMe);
> > > > >
> > > > >                     executor.setStreamHandler(new
> > > PumpStreamHandler(null,
> > > > > null, input)); // Send the bytes being received in real time to
> > FFMPEG.
> > > > >                     executor.execute(commandLine, new
> > > > > DefaultExecuteResultHandler()); // Execute FFMPEG.
> > > > >                 } catch (IOException e) {
> > > > >                     e.printStackTrace();
> > > > >                 }
> > > > >             }
> > > > >         }
> > > > >     }
> > > > > }
> > > > >
> > > > > Now, this is the code for the executable .jar which is the class
> > > > > "SecondApp". This one just sends bytes to the Standard Output and
> > it's
> > > > > started by "MainApp".
> > > > >
> > > > > public class SecondApp {
> > > > >
> > > > >     public static void main(String[] args) throws
> > > ClassNotFoundException,
> > > > > IOException {
> > > > >         Mixer mixer =
> > > > > AudioSystem.getMixer(AudioSystem.getMixerInfo()[
> > > > > Integer.parseInt(args[0])]);
> > > > >         AudioFormat af = new AudioFormat(Encoding.PCM_SIGNED,
> > 48000f,
> > > > 16,
> > > > > 2, 4, 48000f, false);
> > > > >
> > > > >         TargetDataLine line;
> > > > >         DataLine.Info info = new DataLine.Info(TargetDataLine.
> class,
> > > > af);
> > > > >         if (!AudioSystem.isLineSupported(info))
> > > > >             System.out.println("Line is not supported.");
> > > > >
> > > > >         try {
> > > > >             line = (TargetDataLine) mixer.getLine(info);
> > > > >             line.open(af);
> > > > >
> > > > >             int bytesRead, CHUNK_SIZE = 4096;
> > > > >             byte[] data = new byte[line.getBufferSize() / 5];
> > > > >
> > > > >             line.start();
> > > > >
> > > > >             while (true) {
> > > > >                 bytesRead = line.read(data, 0, CHUNK_SIZE);
> > > > >                 System.out.write(data, 0, bytesRead);
> > > > >                 System.out.flush();
> > > > >             }
> > > > >
> > > > >         } catch (LineUnavailableException ex) {
> > > > >             System.out.println("Line is unavailable.");
> > > > >             ex.printStackTrace();
> > > > >         }
> > > > >     }
> > > > > }
> > > > >
> > > > > 2017-02-05 16:31 GMT+01:00 Raymond DeCampo <ray@decampo.org>:
> > > > >
> > > > > > Edgar, I didn't see anything obvious wrong with what you posted.
> > If
> > > > you
> > > > > > can distill it down to a minimal self-contained example that
> > > reproduces
> > > > > the
> > > > > > behavior I can take a closer look.
> > > > > >
> > > > > > On Sat, Feb 4, 2017 at 1:47 PM, Edgar H <kaotixpro@gmail.com>
> > wrote:
> > > > > >
> > > > > > > I've been struggling with this problem for quite some time
now
> as
> > > > it's
> > > > > my
> > > > > > > very first time doing an application related to streaming
and I
> > > just
> > > > > > can't
> > > > > > > figure out why. Here's the problem...
> > > > > > >
> > > > > > > What I'm trying to achieve is to send a command's output
as an
> > > input
> > > > > for
> > > > > > > the next one, which is basically what the pipe operator
does.
> As
> > I
> > > > knew
> > > > > > > this couldn't be executed directly with Exec library from
> Apache
> > > > > Commons
> > > > > > I
> > > > > > > started looking for ways to solve this. I've seen quite
a few
> > > > examples
> > > > > of
> > > > > > > similar things to this but none of them covers my situation:
> > > > > > >
> > > > > > > I have two Java applications separated, one is the main
> > application
> > > > and
> > > > > > the
> > > > > > > second one is initialized by the first one. This second
> > > applications
> > > > > > sends
> > > > > > > to the Standard Output bytes, which FFMPEG should receive.
> > > > > > >
> > > > > > > The code that I have so far is the following one...
> > > > > > >
> > > > > > > public void initStream(String path) {
> > > > > > >     File file = new File(path);
> > > > > > >     for (File s : file.listFiles()) {
> > > > > > >         if (s.getName().equals("ffmpeg.exe")) {
> > > > > > >             try {
> > > > > > >
> > > > > > >                 // Second app, supposedly, writes here.
> > > > > > >                 PipedOutputStream output = new
> > PipedOutputStream();
> > > > > > >
> > > > > > >                 DefaultExecutor executor = new
> DefaultExecutor();
> > > > > > >                 //DefaultExecutor executorFFMPEG = new
> > > > > DefaultExecutor();
> > > > > > >                 executor.setWorkingDirectory(file);
> > > > > > >                 //executor.setWorkingDirectory(file);
> > > > > > >
> > > > > > >                 CommandLine commandLine = new
> > > > > > > CommandLine(s.getParentFile().getAbsolutePath());
> > > > > > >                 System.out.println("Path: " +
> > > > commandLine.toString());
> > > > > > >
> > > > > > >                 String executeMe = "java -jar streamer.jar";
> > > > > > >                 commandLine = CommandLine.parse(executeMe);
> > > > > > >
> > > > > > >                 System.out.println("[testing] streamer
about to
> > > > > > launch.");
> > > > > > >                 executor.setStreamHandler(new
> > > > PumpStreamHandler(output,
> > > > > > > null));
> > > > > > >                 executor.execute(commandLine, new
> > > > > > > DefaultExecuteResultHandler());
> > > > > > >                 System.out.println("[testing] streamer
> > started.");
> > > > > > >
> > > > > > >                 PipedInputStream input = new
> PipedInputStream();
> > > > > > >                 output.connect(input);
> > > > > > >
> > > > > > >                 String feedMe = "ffmpeg"; // more attributes
> here
> > > > > > >                 commandLine = CommandLine.parse(feedMe);
> > > > > > >
> > > > > > >                 System.out.println("[testing] ffmpeg about
to
> > > > > launch.");
> > > > > > >                 executor.setStreamHandler(new
> > > PumpStreamHandler(null,
> > > > > > > null, input));
> > > > > > >                 executor.execute(commandLine, new
> > > > > > > DefaultExecuteResultHandler());
> > > > > > >                 System.out.println("[testing] ffmpeg
> started.");
> > > > > > >
> > > > > > >             } catch (IOException e) {
> > > > > > >                 e.printStackTrace();
> > > > > > >             }
> > > > > > >         }
> > > > > > >     }}
> > > > > > >
> > > > > > > And the code for the second application (the zone where
I send
> > data
> > > > to
> > > > > > > the stdout) is the following one.
> > > > > > >
> > > > > > > static OutputStream stdout = System.out;
> > > > > > >
> > > > > > > (more code and other things around here)
> > > > > > >
> > > > > > > try {
> > > > > > >         line = (TargetDataLine) mixer.getLine(info);
> > > > > > >         line.open(format);
> > > > > > >
> > > > > > >         int bytesRead, CHUNK_SIZE = 4096;
> > > > > > >         byte[] data = new byte[line.getBufferSize() / 5];
> > > > > > >
> > > > > > >         line.start();
> > > > > > >
> > > > > > >         while (true) {
> > > > > > >             bytesRead = line.read(data, 0, CHUNK_SIZE);
> > > > > > >             stdout.write(data, 0, bytesRead);
> > > > > > >             stdout.flush();
> > > > > > >         }
> > > > > > >
> > > > > > >     } catch (LineUnavailableException ex) {
> > > > > > >         System.out.println("Line is unavailable.");
> > > > > > >         ex.printStackTrace();
> > > > > > >     }
> > > > > > >
> > > > > > > At the moment, no communication seems to be made between
both
> > > > commands
> > > > > as
> > > > > > > ffmpeg isn't receiving anything.
> > > > > > >
> > > > > > > Hope you guys can tell what I'm missing out, or if I'm
> > incorrectly
> > > > > > working
> > > > > > > with the library thinking it works in a way when it works
in
> > > another
> > > > > one.
> > > > > > >
> > > > > >
> > > > >
> > > >
> > >
> >
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message