commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Edgar H <kaotix...@gmail.com>
Subject Re: [exec] Misconcepting PumpStreamHandler's way of working with streams?
Date Thu, 09 Feb 2017 11:05:22 GMT
Perfect, I'll modify my current project later with the changes you made.

Thank you so much for dedicating a little bit of your time looking for the
issue.

All the best,
Edgar

2017-02-09 0:54 GMT+01:00 Raymond DeCampo <ray@decampo.org>:

> 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