summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2011-08-14 13:50:26 +0200
committerKlaus Schmidinger <vdr@tvdr.de>2011-08-14 13:50:26 +0200
commitc13d6e6070d895dd33f82e80b5d045cbb417bc6c (patch)
treec5b2a1cc93137e50c95da713504af997afe9a3f4
parent5e2f8e761343f72ed0c491c6b2caa64637a04f54 (diff)
downloadvdr-c13d6e6070d895dd33f82e80b5d045cbb417bc6c.tar.gz
vdr-c13d6e6070d895dd33f82e80b5d045cbb417bc6c.tar.bz2
The pic2mpg script of the 'pictures' plugin now generates HD images
-rw-r--r--CONTRIBUTORS1
-rw-r--r--HISTORY5
-rw-r--r--PLUGINS/src/pictures/HISTORY6
-rwxr-xr-xPLUGINS/src/pictures/pic2mpg90
-rwxr-xr-xPLUGINS/src/pictures/pic2mpg-sd193
5 files changed, 226 insertions, 69 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 4764d5b3..eb47d58b 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -2153,6 +2153,7 @@ André Weidemann <Andre.Weidemann@web.de>
recording if Setup.UseDolbyDigital is true
for suggesting that the primary device should only be avoided for recording if
it is an old SD full featured card
+ for his support in using convert/ffmpeg in the pic2mpg script of the 'pictures' plugin
Jürgen Schilling <juergen_schilling@web.de>
for reporting that color buttons were displayed in the recording info menu if it
diff --git a/HISTORY b/HISTORY
index e52e7841..f1af119c 100644
--- a/HISTORY
+++ b/HISTORY
@@ -6650,7 +6650,7 @@ Video Disk Recorder Revision History
- Added support for "content identifier descriptor" and "default authority descriptor"
to 'libsi' (thanks to Dave Pickles).
-2011-08-13: Version 1.7.20
+2011-08-14: Version 1.7.20
- Added some missing 'const' to tChannelID (reported by Sundararaj Reel).
- The isnumber() function now checks the given pointer for NULL (thanks to Holger
@@ -6683,3 +6683,6 @@ Video Disk Recorder Revision History
by a call to cIndexFile::GetLength() (suggested by Christoph Haubrich).
- Fixed some crashes in subtitle display (thanks to Rolf Ahrenberg).
- Made DELETENULL() thread safe (reported by Rolf Ahrenberg).
+- The pic2mpg script of the 'pictures' plugin now generates HD images (thanks to
+ Andre Weidemann for his support in using convert/ffmpeg). The old SD version is
+ still available as pic2mpg-sd.
diff --git a/PLUGINS/src/pictures/HISTORY b/PLUGINS/src/pictures/HISTORY
index b67bbaca..7e82a3c7 100644
--- a/PLUGINS/src/pictures/HISTORY
+++ b/PLUGINS/src/pictures/HISTORY
@@ -49,3 +49,9 @@ VDR Plugin 'pictures' Revision History
2011-07-23:
- Now rotating images according to the EXIF 'Orientation' parameter.
+
+2011-08-14:
+
+- The pic2mpg script now generates HD images (thanks to Andre Weidemann for his
+ support in using convert/ffmpeg). The old SD version is still available as
+ pic2mpg-sd.
diff --git a/PLUGINS/src/pictures/pic2mpg b/PLUGINS/src/pictures/pic2mpg
index 6213091e..190ec260 100755
--- a/PLUGINS/src/pictures/pic2mpg
+++ b/PLUGINS/src/pictures/pic2mpg
@@ -7,63 +7,45 @@
#
# See the README file for copyright information and how to reach the author.
#
-# $Id: pic2mpg 2.1 2011/07/23 14:23:59 kls Exp $
-
-## TODO implement HDTV (1920 x 1080)
+# $Id: pic2mpg 2.2 2011/08/14 13:34:15 kls Exp $
use File::Path;
use File::Spec;
use Getopt::Std;
use Image::ExifTool qw(:Public);
-use Image::Size;
$Usage = qq{
Usage: $0 [options] picture-dir mpeg-dir
$0 [options] picture-file mpeg-file
-Options: -a Aspect ratio 4:3 (default is 16:9)
- -f Force conversion
+Options: -f Force conversion
-h print Help
- -i Ignore unknown file types
- -n NTSC (default is PAL)
+ -s size Screen size (WIDTHxHEIGHT, default is 1920x1080)
-v num Verbose (0=none, 1=list files, 2=detailed)
- -x percent X overscan in percent
- -y percent Y overscan in percent
};
-getopts("afhinv:x:y:") || die $Usage;
+getopts("fhs:v:") || die $Usage;
die $Usage if $opt_h;
-$Aspect = $opt_a;
$Force = $opt_f;
-$Ignore = $opt_i;
-$NTSC = $opt_n;
+$Size = $opt_s || "1920x1080";
$Verbose = $opt_v;
-$OverscanX = $opt_x;
-$OverscanY = $opt_y;
$ListFiles = $Verbose >= 1;
$Detailed = $Verbose >= 2;
-# Screen size:
-
-$SW = $NTSC ? 720 : 720;
-$SH = $NTSC ? 480 : 576;
-
-$ScreenRatio = $Aspect ? 4 / 3 : 16 / 9;
-
-# Converter programs:
-
-%PNMCONV = (
- bmp => "bmptopnm",
- gif => "giftopnm",
- jpeg => "jpegtopnm",
- jpg => "jpegtopnm",
- png => "pngtopnm",
- pnm => "cat",
- tif => "tifftopnm",
- tiff => "tifftopnm",
+# Supported picture types:
+
+%PICTYPES = (
+ bmp => 1,
+ gif => 1,
+ jpeg => 1,
+ jpg => 1,
+ png => 1,
+ pnm => 1,
+ tif => 1,
+ tiff => 1,
);
# Command options:
@@ -72,13 +54,6 @@ die "$0: missing parameter\n" unless $ARGV[0] && $ARGV[1];
die "$0: file or directory not found: $ARGV[0]\n" unless -e $ARGV[0];
die "$0: source and destination must be different\n" if $ARGV[0] eq $ARGV[1];
-$verbose1 = $Detailed ? "--verbose" : "";
-$verbose2 = $Detailed ? "-v 2" : "-v 0";
-$system1 = $NTSC ? "" : "--pal";
-$system2 = $NTSC ? "n" : "p";
-$framerate = $NTSC ? "30000:1001" : "25:1";
-$aspect = $Aspect ? "2" : "3";
-
# Convert a single file:
if (-f $ARGV[0]) {
@@ -96,7 +71,7 @@ $MPGDIR = File::Spec->rel2abs($ARGV[1]);
chdir($PICDIR) || die "$PICDIR: $!\n";
-@Pictures = `find -type f`;
+@Pictures = `find -type f | sort`;
chomp(@Pictures);
for $pic (@Pictures) {
@@ -146,39 +121,18 @@ sub ConvertFile
{
my ($Pict, $Mpeg) = @_;
(my $Type) = lc($Pict) =~ /\.([^\.]*)$/;
- if (!defined $PNMCONV{$Type}) {
- return if ($Ignore);
- die "unknown file type '$Type': '$Pict'\n";
- }
- my ($w, $h) = imgsize($Pict);
- print "image size is $w x $h\n" if ($Detailed);
+ return if (!defined $PICTYPES{$Type});
my $Exif = ImageInfo($Pict);
my $Orientation = $$Exif{"Orientation"};
my ($Degrees) = $Orientation =~ /Rotate ([0-9]+) /;
- my $Rotate = "-null";
- $Rotate = "-cw" if $Degrees eq "90";
- $Rotate = "-ccw" if $Degrees eq "270";
- $Rotate = "-r180" if $Degrees eq "180";
+ my $Rotate = $Degrees ? "-rotate $Degrees" : "";
print "orientation = '$Orientation' -> rotation = $Rotate\n" if ($Detailed);
- ($w, $h) = ($h, $w) if ($Degrees eq "90" || $Degrees eq "270");
- if ($w / $h <= $ScreenRatio) {
- $w = $h * $ScreenRatio;
- }
- else {
- $h = $w / $ScreenRatio;
- }
- my $ScaleW = $SW / $w * (100 - 2 * $OverscanX) / 100;
- my $ScaleH = $SH / $h * (100 - 2 * $OverscanY) / 100;
$Pict = EscapeMeta($Pict);
$Mpeg = EscapeMeta($Mpeg);
print "$Pict -> $Mpeg $Rotate\n" if $ListFiles;
- my $Cmd = "$PNMCONV{$Type} $Pict 2> /dev/null |"
- . "pamflip $verbose1 $Rotate |"
- . "pnmscale $verbose1 --xscale=$ScaleW --yscale=$ScaleH |"
- . "pnmpad $verbose1 --black --width $SW --height $SH |"
- . "ppmntsc $verbose1 $system1 |"
- . "ppmtoy4m $verbose2 -F $framerate -I p -S 420mpeg2 |"
- . "mpeg2enc $verbose2 -f 3 -b 12500 -a $aspect -q 1 -n $system2 -o $Mpeg";
+ my $Cmd = "convert $Pict -background '#000000' $Rotate -resize $Size -gravity center -extent $Size ppm:- | "
+ . "ffmpeg -f image2pipe -vcodec ppm -i pipe:0 -an -vcodec libx264 -vpre baseline -s $Size -qscale 2 -f mpegts -y $Mpeg "
+ . ($Detailed ? "" : "2>/dev/null");
!system($Cmd) || die "$Cmd: $!\n";
$Cmd = "touch -r $Pict $Mpeg";
!system($Cmd) || die "$Cmd: $!\n";
diff --git a/PLUGINS/src/pictures/pic2mpg-sd b/PLUGINS/src/pictures/pic2mpg-sd
new file mode 100755
index 00000000..15549dcd
--- /dev/null
+++ b/PLUGINS/src/pictures/pic2mpg-sd
@@ -0,0 +1,193 @@
+#!/usr/bin/perl
+
+# pic2mpg: Convert picture files to MPEG still frames
+#
+# Converts either a single picture file or all files in a
+# given directory (recursively) to MPEG still frames.
+#
+# See the README file for copyright information and how to reach the author.
+#
+# $Id: pic2mpg-sd 2.1 2011/07/23 14:23:59 kls Exp $
+
+## TODO implement HDTV (1920 x 1080)
+
+use File::Path;
+use File::Spec;
+use Getopt::Std;
+use Image::ExifTool qw(:Public);
+use Image::Size;
+
+$Usage = qq{
+Usage: $0 [options] picture-dir mpeg-dir
+ $0 [options] picture-file mpeg-file
+
+Options: -a Aspect ratio 4:3 (default is 16:9)
+ -f Force conversion
+ -h print Help
+ -i Ignore unknown file types
+ -n NTSC (default is PAL)
+ -v num Verbose (0=none, 1=list files, 2=detailed)
+ -x percent X overscan in percent
+ -y percent Y overscan in percent
+};
+
+getopts("afhinv:x:y:") || die $Usage;
+
+die $Usage if $opt_h;
+
+$Aspect = $opt_a;
+$Force = $opt_f;
+$Ignore = $opt_i;
+$NTSC = $opt_n;
+$Verbose = $opt_v;
+$OverscanX = $opt_x;
+$OverscanY = $opt_y;
+
+$ListFiles = $Verbose >= 1;
+$Detailed = $Verbose >= 2;
+
+# Screen size:
+
+$SW = $NTSC ? 720 : 720;
+$SH = $NTSC ? 480 : 576;
+
+$ScreenRatio = $Aspect ? 4 / 3 : 16 / 9;
+
+# Converter programs:
+
+%PNMCONV = (
+ bmp => "bmptopnm",
+ gif => "giftopnm",
+ jpeg => "jpegtopnm",
+ jpg => "jpegtopnm",
+ png => "pngtopnm",
+ pnm => "cat",
+ tif => "tifftopnm",
+ tiff => "tifftopnm",
+ );
+
+# Command options:
+
+die "$0: missing parameter\n" unless $ARGV[0] && $ARGV[1];
+die "$0: file or directory not found: $ARGV[0]\n" unless -e $ARGV[0];
+die "$0: source and destination must be different\n" if $ARGV[0] eq $ARGV[1];
+
+$verbose1 = $Detailed ? "--verbose" : "";
+$verbose2 = $Detailed ? "-v 2" : "-v 0";
+$system1 = $NTSC ? "" : "--pal";
+$system2 = $NTSC ? "n" : "p";
+$framerate = $NTSC ? "30000:1001" : "25:1";
+$aspect = $Aspect ? "2" : "3";
+
+# Convert a single file:
+
+if (-f $ARGV[0]) {
+ die "$0: mixed file and directory ('$ARGV[0]' <-> '$ARGV[1]')\n" unless !-e $ARGV[1] || -f $ARGV[1];
+ ConvertFile($ARGV[0], $ARGV[1]);
+ exit;
+ }
+
+die "$0: mixed directory and file ('$ARGV[0]' <-> '$ARGV[1]')\n" unless !-e $ARGV[1] || -d $ARGV[1];
+
+$PICDIR = File::Spec->rel2abs($ARGV[0]);
+$MPGDIR = File::Spec->rel2abs($ARGV[1]);
+
+# Convert pictures to mpegs:
+
+chdir($PICDIR) || die "$PICDIR: $!\n";
+
+@Pictures = `find -type f`;
+chomp(@Pictures);
+
+for $pic (@Pictures) {
+ my $mpg = "$MPGDIR/$pic.mpg";
+ if ($Force || !-e $mpg || -M $mpg > -M $pic) {
+ (my $dir = $mpg) =~ s/\/[^\/]*$//;
+ mkpath($dir);
+ ConvertFile($pic, $mpg);
+ }
+ }
+
+# Remove mpegs without pictures:
+
+chdir($MPGDIR) || die "$MPGDIR: $!\n";
+
+@Mpegs = `find -type f`;
+chomp(@Mpegs);
+
+for $mpg (@Mpegs) {
+ my $pic = "$PICDIR/$mpg";
+ $pic =~ s/\.mpg$//;
+ if (!-e $pic) {
+ print "removing $mpg\n";
+ unlink($mpg);
+ }
+ }
+
+# Remove empty directories:
+
+chdir($MPGDIR) || die "$MPGDIR: $!\n";
+
+for ($i = 0; $i < 10; $i++) { # dirs might become empty when removing empty subdirs
+ @Dirs = `find -type d -empty`;
+ chomp(@Dirs);
+ last unless @Dirs;
+
+ for $dir (@Dirs) {
+ $dir = EscapeMeta($dir);
+ print "removing $dir\n";
+ !system("rm -rf $dir") || die "$dir: $!\n";
+ }
+ }
+
+# Actual file conversion:
+
+sub ConvertFile
+{
+ my ($Pict, $Mpeg) = @_;
+ (my $Type) = lc($Pict) =~ /\.([^\.]*)$/;
+ if (!defined $PNMCONV{$Type}) {
+ return if ($Ignore);
+ die "unknown file type '$Type': '$Pict'\n";
+ }
+ my ($w, $h) = imgsize($Pict);
+ print "image size is $w x $h\n" if ($Detailed);
+ my $Exif = ImageInfo($Pict);
+ my $Orientation = $$Exif{"Orientation"};
+ my ($Degrees) = $Orientation =~ /Rotate ([0-9]+) /;
+ my $Rotate = "-null";
+ $Rotate = "-cw" if $Degrees eq "90";
+ $Rotate = "-ccw" if $Degrees eq "270";
+ $Rotate = "-r180" if $Degrees eq "180";
+ print "orientation = '$Orientation' -> rotation = $Rotate\n" if ($Detailed);
+ ($w, $h) = ($h, $w) if ($Degrees eq "90" || $Degrees eq "270");
+ if ($w / $h <= $ScreenRatio) {
+ $w = $h * $ScreenRatio;
+ }
+ else {
+ $h = $w / $ScreenRatio;
+ }
+ my $ScaleW = $SW / $w * (100 - 2 * $OverscanX) / 100;
+ my $ScaleH = $SH / $h * (100 - 2 * $OverscanY) / 100;
+ $Pict = EscapeMeta($Pict);
+ $Mpeg = EscapeMeta($Mpeg);
+ print "$Pict -> $Mpeg $Rotate\n" if $ListFiles;
+ my $Cmd = "$PNMCONV{$Type} $Pict 2> /dev/null |"
+ . "pamflip $verbose1 $Rotate |"
+ . "pnmscale $verbose1 --xscale=$ScaleW --yscale=$ScaleH |"
+ . "pnmpad $verbose1 --black --width $SW --height $SH |"
+ . "ppmntsc $verbose1 $system1 |"
+ . "ppmtoy4m $verbose2 -F $framerate -I p -S 420mpeg2 |"
+ . "mpeg2enc $verbose2 -f 3 -b 12500 -a $aspect -q 1 -n $system2 -o $Mpeg";
+ !system($Cmd) || die "$Cmd: $!\n";
+ $Cmd = "touch -r $Pict $Mpeg";
+ !system($Cmd) || die "$Cmd: $!\n";
+}
+
+sub EscapeMeta
+{
+ my $META = ' !"#$%&\'()*;<>?[\\]`{|}~';
+ my $s = shift;
+ $s =~ s/([$META])/\\$1/g;
+ return $s;
+}