1 | #!/usr/bin/perl |
---|
2 | # |
---|
3 | # MythWeb Streaming/Download module |
---|
4 | # |
---|
5 | # @url $URL: http://svn.mythtv.org/svn/tags/release-0-23/mythplugins/mythweb/modules/stream/stream_flv.pl $ |
---|
6 | # @date $Date: 2009-10-29 17:58:53 -0700 (Thu, 29 Oct 2009) $ |
---|
7 | # @version $Revision: 22646 $ |
---|
8 | # @author $Author: kormoc $ |
---|
9 | # |
---|
10 | |
---|
11 | use Math::Round qw(nearest_floor); |
---|
12 | |
---|
13 | our $ffmpeg_pid; |
---|
14 | |
---|
15 | # Shutdown cleanup, of various types |
---|
16 | $SIG{'TERM'} = \&shutdown_handler; |
---|
17 | $SIG{'PIPE'} = \&shutdown_handler; |
---|
18 | END { |
---|
19 | shutdown_handler(); |
---|
20 | } |
---|
21 | sub shutdown_handler { |
---|
22 | kill(1, $ffmpeg_pid) if ($ffmpeg_pid); |
---|
23 | } |
---|
24 | |
---|
25 | # Find ffmpeg |
---|
26 | $ffmpeg = ''; |
---|
27 | foreach my $path (split(/:/, $ENV{'PATH'}.':/usr/local/bin:/usr/bin'), '.') { |
---|
28 | if (-e "$path/ffmpeg") { |
---|
29 | $ffmpeg = "$path/ffmpeg"; |
---|
30 | last; |
---|
31 | } |
---|
32 | elsif ($^O eq 'darwin' && -e "$path/ffmpeg.app") { |
---|
33 | $ffmpeg = "$path/ffmpeg.app"; |
---|
34 | last; |
---|
35 | } |
---|
36 | } |
---|
37 | |
---|
38 | # Load some conversion settings from the database |
---|
39 | $sh = $dbh->prepare('SELECT data FROM settings WHERE value=? AND hostname IS NULL'); |
---|
40 | $sh->execute('WebFLV_w'); |
---|
41 | my ($width) = $sh->fetchrow_array; |
---|
42 | $sh->execute('WebFLV_vb'); |
---|
43 | my ($vbitrate) = $sh->fetchrow_array; |
---|
44 | $sh->execute('WebFLV_ab'); |
---|
45 | my ($abitrate) = $sh->fetchrow_array; |
---|
46 | $sh->finish(); |
---|
47 | # auto-detect height based on aspect ratio |
---|
48 | $sh = $dbh->prepare('SELECT data FROM recordedmarkup WHERE chanid=? AND starttime=FROM_UNIXTIME(?) AND data IS NOT NULL ORDER BY data DESC'); |
---|
49 | $sh->execute($chanid,$starttime); |
---|
50 | $x = $sh->fetchrow_array; |
---|
51 | $y = $sh->fetchrow_array if ($x); |
---|
52 | $width = nearest_floor(2,$width); |
---|
53 | |
---|
54 | $height1=$height; |
---|
55 | if ($x && $y) { |
---|
56 | $height = nearest_floor(2,$width * ($y/$x)); |
---|
57 | } else { |
---|
58 | $height = nearest_floor(2,$width * 3/4); |
---|
59 | } |
---|
60 | $sh->finish(); |
---|
61 | $height2=$height; |
---|
62 | $width = 320 unless ($width && $width > 1); |
---|
63 | $height = 240 unless ($height && $height > 1); |
---|
64 | $vbitrate = 256 unless ($vbitrate && $vbitrate > 1); |
---|
65 | $abitrate = 64 unless ($abitrate && $abitrate > 1); |
---|
66 | $height3=$height; |
---|
67 | my $ffmpeg_command = $ffmpeg |
---|
68 | .' -y' |
---|
69 | .' -i '.shell_escape($filename) |
---|
70 | .' -s '.shell_escape("${width}x${height}") |
---|
71 | .' -g 30' |
---|
72 | .' -r 24' |
---|
73 | .' -f flv' |
---|
74 | .' -deinterlace' |
---|
75 | .' -ac 2' |
---|
76 | .' -ar 11025' |
---|
77 | .' -ab '.shell_escape("${abitrate}k") |
---|
78 | .' -b '.shell_escape("${vbitrate}k") |
---|
79 | .' /dev/stdout 2>/dev/null |'; |
---|
80 | |
---|
81 | |
---|
82 | # Print the movie |
---|
83 | $ffmpeg_pid = open(DATA, $ffmpeg_command); |
---|
84 | unless ($ffmpeg_pid) { |
---|
85 | print header(), |
---|
86 | "Can't do ffmpeg: $!\n${ffmpeg_command}"; |
---|
87 | exit; |
---|
88 | } |
---|
89 | print header(-type => 'video/x-flv'); |
---|
90 | my $buffer; |
---|
91 | while (read DATA, $buffer, 262144) { |
---|
92 | print $buffer; |
---|
93 | } |
---|
94 | close DATA; |
---|
95 | |
---|
96 | 1; |
---|