Linux tee command with multiple fifo. fifo blocks tee - linux

I am trying to develope one program to play and record some rtmp streames. The program is developed in Qt.
i am using the rtmpdump and mplayer. since both are running in seperate process, i am using a fifo to pass the stream from rtmpdump to mplayer. I need seperate process because mplayer need to be controlled by user. so mplayer is runnig in slave mode.
this is working fine for playing the stream.
now i want to record the stream to another file. i know that i can use the mplayer to do that. but using a single mplayer it is not possible as it supports only either playing or recording. so thought of using the tee command to split the stream and use 2 mplayer process, one for recording and one for playing.
now the stream flows like this
rtmpdump | tee fifo_for_playing fifo_for recording
one mplayer is reading the fifo_for_playing and another is reading fifo_for_recording.
now the problem is, since mplayer which supposed to record will start only when the user press record button, fifo_for_recording will block the tee as it is not opened. so playing also will not start.
can anybody suggest a solution or better way to achieve this? what i am trying to do is tee with non blocking fifo. so even if one fifo is not opened for reading, it will not block the tee..

Fifos do not have a buffer (or if they have one it is very small). If you write to it and no one is reading you block, as you're finding out.
You could write a little program to read the fifo and buffer it in memory or to disk. Maybe the dd program can do that?
Or you could call with rtmpdump with the -stop option in a loop, and have it write its output to a file. Then process the files the old fashioned way without the fifo.

Related

How can I select() (ie, simultaneously read from) standard input *and* a file in bash?

I have a program that accepts input on one FIFO and emits output to another FIFO. I want to write a small script to control this program. The script needs to listen both to standard input (so I can input commands to adjust things in real time) and the program's output FIFO (so it can respond to events happening there as well).
Essentially my control program needs to select between standard input and a file (my FIFO).
I like learning how to figure out how to develop simple and elegant bash-based solutions to complex problems, and after a little headscratching I remembered that that tail -f will happily select on multiple files and tell you when one of them changes in real time, so I initially tried
tail -f <(od -An -vtd1 -w1) <(cat fifo)
to read both standard input (I'd previously run stty icanon min 1; this od invocation shows each stdin character on a separate line alongside its ASCII code, and is great for escape sequence parsing) and my FIFO. This failed epically (as does cat <(cat)): od gets run here as a backgrounded task, so it doesn't get access to the controlling TTY, and fails with a cryptic "I/O error" that was explained incredibly well here.
So now I'm a bit stumped. I realize that I can use any scripting language like Perl/Python/Ruby/Tcl to solve this; my compsci/engineering question is whether/how I might be able to solve this using (Linux) shell scripting.

How can I concatenate ATSC streams from DVB card?

I'm trying to make a simple "TV viewer" using a Linux DVB video capture card. Currently I watch TV using the following process (I'm on a Raspberry Pi):
Tune to a channel using azap -r TV_CHANNEL_HERE. This will supply bytes to
device /dev/dvb/adapter0/dvr0.
Open OMXPlayer omxplayer /dev/dvb/adapter0/dvr0
Watch TV!
The problem comes when I try to change channels. Even if I set the player to cache incoming bytes (tried with MPlayer also), the player can't withstand a channel change (by restarting azap with a new channel.
I'm thinking this is because of changes in the MPEG TS stream metadata.
Looking for a C library that would let me do the following:
Pull cache_size * mpeg_ts_packet_size from DVR device.
Evaluate each packet and rewrite metadata (PID, etc) as needed.
Populate FIFO with resulting packet.
Set {OMXPlayer,MPlayer} to read from FIFO.
The other thing I was thinking would be to use a program that converts MPEG TS into MPEG PS and concatenate the bytes that way.
Thoughts?
Indeed, when you want to tune on an other channel, some metadata can potentially change and invalid previously cached data.
Unfortunately I'm not familiar with the tools you are using but your point 2. makes me raise an eyebrow: you will waste your time trying to rewrite Transport Stream data.
I would rather suggest to stop and restart process on zapping since it seems to work fine at start.
P.S.:
Here are some tools that can help. Also, I'm not sure at which level your problem is but VLC can be installed on Raspberry PI and it handles TS gracefully.

How to create artificial microphone input in Linux?

I'm working on an audio recognition project.
For testing, I'd like to be able to have a program:
load audio data from a file
provide it to the Linux kernel, as if it were coming from a microphone
have any user-space program sampling the microphone be obtaining data sourced
from my file.
Is that possible in Linux without having to write a new kernel module?
EDIT: i guess that solution won't work .. but see my comment below.
this shoud be simple under linux.
here are the steps:
make a named pipe with mkfifo (mkfifo ~/audio_out.pipe)
cat the audiofile into this pipe (cat test.wav > ~/audio_out.pipe)
get the program you want to listen, to get input from this pipe. maybe you have to make a symlink for programs not flexible enough to read from any device.
I hope I got your question right.

Syncing two files when one is still being written to

I have an application (video stream capture) which constantly writes its data to a single file. Application typically runs for several hours, creating ~1 gigabyte file. Soon (in a matter of several seconds) after it quits, I'd like to have 2 copies of file it was writing - let's say, one in /mnt/disk1, another in /mnt/disk2 (the latter is an USB flash drive with FAT32 filesystem).
I don't really like an idea of modifying the application to write 2 copies simulatenously, so I though of:
Application starts and begins to write the file (let's call it /mnt/disk1/file.mkv)
Some utility starts, copies what's already there in /mnt/disk1/file.mkv to /mnt/disk2/file.mkv
After getting initial sync state, it continues to follow a written file in a manner like tail -f does, copying everything it gets from /mnt/disk1/file.mkv to /mnt/disk2/file.mkv
Several hours pass
Application quits, we stop our syncing utility
Afterwards, we run a quick rsync /mnt/disk1/file.mkv /mnt/disk2/file.mkv just to make sure they're the same. In case if they're the same, it should just run a quick check and quit fairly soon.
What is the best approach for syncing 2 files, preferably using simple Linux shell-available utilities? May be I could use some clever trick with FUSE / md device / tee / tail -f?
Solution
The best possible solution for my case seems to be
mencoder ... -o >(
tee /mnt/disk1/file.mkv |
tee /mnt/disk2/file.mkv |
mplayer -
)
This one uses bash/zsh-specific magic named "process substitution" thus eliminating the need to make named pipes manually using mkfifo, and displays what's being encoded, as a bonus :)
Hmmm... the file is not usable while it's being written, so why don't you "trick" your program into writing through a pipe/fifo and use a 2nd, very simple program, to create 2 copies?
This way, you have your two copies as soon as the original process ends.
Read the manual page on tee(1).

How to screen capture screenshots or movies on the Linux framebuffer

How can the linux frame buffer, on Cell Linux, be captured to obtain either screen shots or movies?
Is there a tool to do this for a running program, or must the program writing to, and presumably controlling, the frame buffer also handle capture and recording? If so, how would the program do so?
Many tools for doing so, for example FBGrab and fbdump; look at the sources for those two, it would be pretty easy to extend either one or write your own which captures video instead of just snapshots.
However, I would recommend that the program writing to the framebuffer be the one recording as well, in order to synchronize capturing frames between writing them (and not partially through a write, or skipping, or ...)
you could use ffmpeg or avconv (eg. avconv -f fbdev -i /dev/fb0 mymovie.flv).

Resources