mkrufky / libdvbtee

dvbtee: a digital television streamer / parser / service information aggregator supporting various interfaces including telnet CLI & http control
GNU Lesser General Public License v2.1
79 stars 31 forks source link

Failed to open stdin #28

Closed YugoCode closed 7 years ago

YugoCode commented 7 years ago

I'm trying to use dvbtee inside a node.js application. I have a tuner module which gives me access to a MPEG-2 transport stream from a DVB-T stick.

Earlier I piped the output to a file record.ts and started dvbtee with the file as its input, which worked. Now I would like to pipe the stream directly to dvbtee. Therefore I'm starting dvbtee without arguments, which works fine on a linux shell but inside node.js will give me this error:

Stderr: reading from STDIN
failed to open stdin!

This is the code:

  var exec = require('child_process').exec;

  // both work
  //var command = "cat record.ts | dvbtee";
  //var command ="dvbtee < record.ts";

  // doesn't work
  var command = "dvbtee";
  var dvbtee = exec(command, function(error, stdout, stderr) {

    console.log("Stdout:", stdout);
    console.log("Stderr:", stderr);

  });

I was thinking it would wait for input from stdin, but it seems it doesn't. Why can it not open stdin?

Later I would do this:

tuner.pipe(dvbtee.stdin);

What could be the problem here?

Thank you for any help!

mkrufky commented 7 years ago

@YugoCode I added a hack in a test branch called start-stdin-retry-200ms#28 that will retry freopen(NULL, "rb", stdin) until a success. This shouldn't cause any regressions under normal operation, and will hopefully solve your problem.

Please let me know if this works for you, and then I'll merge it (or something similar) to the master branch.

mkrufky commented 7 years ago

@YugoCode just curious, where does your tuner component come from? I have been working on writing some node.js bindings for libdvbtee, but I need to finish refactoring the input feed pipeline first. Once it's done, it will be easy to create tuner input objects etc from within node.js with built-in parsing and event callbacks.

YugoCode commented 7 years ago

@mkrufky Thanks for your quick fix!

Unfortunately it is not working. When I tried to pipe the output of the tuner to the dvbtee process the tuner said "buffer is consumed to slowly" and when I checked the buffer wasn't consumed at all.

The only output I get from dvbtee is reading from STDIN.

I wondered if it has to to do with the tuner, so I created this test, which doesn't require a tuner:

  1. Start a process X and put the content of record.ts to stdout
  2. Start dvbtee without arguments
  3. Pipe stdout of process X to stdin of dvbtee process

The code:

  var exec = require('child_process').exec;

  //var print = exec("tail -c +1 -F record.ts");
  var print = exec("cat record.ts");

  // works 
  //var dvbtee = exec("dvbtee -F record.ts");

  var dvbtee = exec("dvbtee");

  print.stdout.pipe(dvbtee.stdin);

  dvbtee.stdout.on("data",function(data) {
  console.log("dvbtee stdout: " + data);
  });

  dvbtee.stderr.on("data", function (data) {
   console.log("dvbtee stderr: " + data);
  });

  dvbtee.on("exit", function (code) {
    console.log("dvbtee terminated with code " + code);
  });

But again the only output I get is reading from STDIN.

I also checked if the print process is working correctly, and it is.

As this test case doesn't require a tuner, could you test if it works for you?

–––––––––– The tuner module was provided to us for a university project and is unfortunately proprietary till now :(

mkrufky commented 7 years ago

I'm still digging into this. You might be better off with my node addon module -- I'll try to clean things up soon and put it to github. In the meanwhile, have you considered trying to use spawn rather than exec ?

YugoCode commented 7 years ago

Can't wait for the node module!

I tested now spawn on the master and the test branch.

For the master I get the same output as in my inital post:

Stderr: reading from STDIN
failed to open stdin!

For the test branch it's the same as before with exec:

reading from STDIN and nothing more.

Here is the code:

  var spawn = require('child_process').spawn;

  var print = spawn("cat", ["record.ts"]);

  var dvbtee = spawn("dvbtee", []);

  // again only output is: reading from STDIN
  //tuner.pipe(dvbtee.stdin);

  print.stdout.pipe(dvbtee.stdin);

  dvbtee.stdout.on("data",function(data) {
  console.log("dvbtee stdout: " + data);
  });

  dvbtee.stderr.on("data", function (data) {
   console.log("dvbtee stderr: " + data);
  });

  dvbtee.on("exit", function (code) {
    console.log("dvbtee terminated with code " + code);
  });

Thanks again Michael!

mkrufky commented 7 years ago

There, I've published the first build of the node module: https://www.npmjs.com/package/dvbtee and here: https://github.com/mkrufky/node-dvbtee

You can be my first tester, @YugoCode :-)

I'd like to fix this stdin issue sometime, but this might work better for you, depending on your needs.

YugoCode commented 7 years ago

Hey Michael, thanks for the module!!!

As you know we are not using a file but a stream from a fifo (named pipe). So we cannot apply your code from the API documentation, because we don't have a normal file.

Therefore our code looks like this:

function init_fifo() {
    try {
        if (fs.lstatSync('fifo-copy').isFIFO()) {
            // We open the FIFO file called "fifo" in the working directory
            fifo = fs.createReadStream('fifo-copy');

            fifo.on('data', function(data) {
                parser.feed(data, data.length, function(err, status) {
                });
                // Do something here, for example, sending the line to an IRC connection or eval()'ing the code.
            });

            // When putting a line with some commands, such as 'echo "line" > fifo', an EOF will be written in the fifo
            // and the stream will be closed. So, we reopen the fifo.
            fifo.once('end', init_fifo);
        }
    }
    // Here, you can handle the case when the fifo doesn't exist (for example, creating the fifo)
    catch (e) {}
}

We are feeding the parser continuously with data from the fifo, which itself is getting the data from the dvb-t stick. And at some point our electron application crashes at HD channels. Is the capacity of the parser limited? Are we maybe overflowing any array? Any thoughts?

Really appreciate it.

mkrufky commented 7 years ago

@YugoCode node-dvbtee now inherits stream. You can pipe to it like any other stream instead of trying to send it large buffers. There shouldn't be any capacity limit to the parser other than your own system memory, but if you stream using pipe(), then it should be no problem.

How about something like this instead:

function init_fifo() {
    try {
        if (fs.lstatSync('fifo-copy').isFIFO()) {
            // When putting a line with some commands, such as 'echo "line" > fifo', an EOF will be written in the fifo
            // and the stream will be closed. So, we reopen the fifo.
            parser.once('end', init_fifo);

            parser.on('data', function (data) {
                // Do something here, for example, sending the line to an IRC connection or eval()'ing the code.
            }

            // We open the FIFO file called "fifo" in the working directory
            fifo = fs.createReadStream('fifo-copy').pipe(parser);
        }
    }
    // Here, you can handle the case when the fifo doesn't exist (for example, creating the fifo)
    catch (e) {}
}

(you'll need version 0.1.x of node-dvbtee - I recommend grabbing version 0.1.8 that I released last night)

mkrufky commented 7 years ago

If you're still having a crash in your application after converting to node-dvbtee's pipe / stream method, it could be a garbage collection issue. If you're running Node.js version 7, there might be a scope local handle leak that I have fixed, but haven't yet published.

What version of Node.js are you running, @YugoCode ?

mkrufky commented 7 years ago

I confirmed there was definitely a garbage collection issue with a leaked handle, which is fixed now in version 2.0.4 of native-json, another module that I wrote which node-dvbtee depends on. If you grab the latest version that should be fixed for you.

YugoCode commented 7 years ago

It is working now Michael! :)

Thank you very much for your help!!!

YugoCode commented 7 years ago

I noticed two times this error now:

error

The app is nevertheless working properly.

I don't know what the cause is. It happened occasional. We adjusted our code like you suggested.

mkrufky commented 7 years ago

I think this is a packet remaining in the buffer from before the fifo was closed and repened with init_fifo

You're probably losing some data, there... The app seems to work properly regardless because broadcast transport streams always have repeat redundant copies of the data.