[mythtv] mythmkmovie patch for cutlists in mpeg files (PVR-[23]50)
Russ Southern
russ.southern at cox.net
Tue Aug 19 00:27:02 EDT 2003
Here is a patch for mythmkmovie to support cutlists with mpeg files, as
produced by the Hauppauge PVR-250. It requires the "transcode" package to
be installed.
There should be no difference in usage or command-line options. If you have
a cutlist, the script autodetects an mpeg file and behaves accordingly.
With no cutlist, it uses the original codepath (using mencoder only).
I have been using this code for about two weeks, and am pleased with its
workings. Comments/flames are welcome.
Russ
-------------- next part --------------
--- mkmovie 2003-08-03 20:36:58.000000000 -0700
+++ mkmovie.russ 2003-08-03 22:32:41.000000000 -0700
@@ -243 +243 @@ use strict;
-my ($versionnum) = "1.0rc2";
+my ($versionnum) = "1.0rc3";
@@ -513 +513 @@ sub getFrameCount {
- my ($dbh, $input, $stoprun) = @_;
+ my ($dbh, $input, $stoprun, $mpeg) = @_;
@@ -517,6 +517,23 @@ sub getFrameCount {
- $command = "mythframes " . $input;
- $finstring = `$command`;
- if ($? and $stoprun) {
- setError($dbh, $input, "mythframes FAILURE");\
- die ("ERROR: mythframes FAILURE!\n") if ($? and $stoprun);
- return (0);
+ print '(counting frames in mpeg files is currently slow)' if $mpeg;
+
+ if ($mpeg){
+ # Yes, it is wasteful to capture all this (noisy) output...
+ $finstring = `tcscan -x mpeg -i $input 2>&1 >/dev/null`;
+ if ($? and $stoprun) {
+ setError($dbh, $input, "tcscan FAILURE");\
+ die ("ERROR: tcscan FAILURE!\n") if ($? and $stoprun);
+ return (0);
+ }
+ # and just as wasteful to regex the whole string
+ $finstring =~ /detected a total of .* and (\d{1,}) sequence/;
+ $framecount = $1;
+ } else {
+ $command = "mythframes " . $input;
+ $finstring = `$command`;
+ if ($? and $stoprun) {
+ setError($dbh, $input, "mythframes FAILURE");\
+ die ("ERROR: mythframes FAILURE!\n") if ($? and $stoprun);
+ return (0);
+ }
+ $finstring =~ /^Total Frames: (\d+)\s*$/;
+ $framecount = $1;
@@ -524,2 +540,0 @@ sub getFrameCount {
- $finstring =~ /^Total Frames: (\d+)\s*$/;
- $framecount = $1;
@@ -600 +614,0 @@ sub getIncList {
- my ($cutrange, $start, $end, $i);
@@ -605,2 +619,2 @@ sub getIncList {
- foreach $cutrange (@cutlist) {
- ($start, $end) = split(/\-/, $cutrange);
+ foreach my $cutrange (@cutlist) {
+ my ($start, $end) = split(/\-/, $cutrange);
@@ -608 +622 @@ sub getIncList {
- $inclist[0] = $end-1;
+ $inclist[0] = $end+1;
@@ -611,2 +625,2 @@ sub getIncList {
- if ($end >= $inclist[$#inclist]) {
- $inclist[$#inclist] = $start+1;
+ if ($end >= $inclist[-1]) {
+ $inclist[-1] = $start-1;
@@ -615,2 +629,2 @@ sub getIncList {
- $start++;
- $end--;
+ $start--;
+ $end++;
@@ -619 +633 @@ sub getIncList {
- $i=0;
+ my $i=0;
@@ -621,2 +635 @@ sub getIncList {
- @temp = splice(@inclist, $i);
- @inclist = (@inclist, $start, $end, @temp);
+ splice(@inclist, $i, 0, ($start, $end));
@@ -945 +958,2 @@ sub clearError {
-# steps necessary to produce the output .avi file.
+# steps necessary to produce the output .avi file. If it detects an mpeg
+# input file, it will use a separate codepath to process the files.
@@ -952,0 +967 @@ sub doshow {
+ my $mpeg = 0;
@@ -983,2 +997,0 @@ sub doshow {
- $framecount = getFrameCount($dbh, $input, $stoprun);
- return if (getError($dbh, $input));
@@ -986,0 +1000,11 @@ sub doshow {
+
+ # If we have a cutlist, autodetect MPEG format input files
+ $mpeg = (`mplayer -identify $input 2>/dev/null` =~ /MPEG.*? file format detected/)
+ if @cutlist;
+
+ # Confirm we have transcode installed if needed
+ die 'transcode package not installed, or not in your PATH'
+ if $mpeg and system('transcode -version') != 0;
+
+ $framecount = getFrameCount($dbh, $input, $stoprun, $mpeg);
+ return if (getError($dbh, $input));
@@ -989,0 +1014 @@ sub doshow {
+
@@ -1000,5 +1025,43 @@ sub doshow {
- $files = makesegments($dbh, $input, $vbr, $keyint, $abr, $pause, $stoprun,
- $transcode, $skiperrors, $autotrans, @inclist);
- return if (getError($dbh, $input));
- makevideo($dbh, $input, $files, $output, $remove, $pause, $stoprun, $skiperrors);
- return if (getError($dbh, $input));
+
+ # If this is an MPEG file from a Hardware Encoder, use a combination of
+ # mencoder and the transcode package (mplayer/mencoder does not handle
+ # VBR, so cannot seek correctly)
+
+ if ($mpeg){
+ # Myth and tcscan seem to disagree on the number of frames.
+ # If the last segment is less than 1 second (30 frames),
+ # discard it (I know, this is bad, but...)
+ if ($inclist[-1] - $inclist[-2] < 30){
+ pop @inclist for ('last', 'segment');
+ }
+ my $Includes = '';
+ $Includes .= ',' . join('-', shift(@inclist), shift(@inclist))
+ while @inclist;
+ my $KeyIntArg = $keyint ? ":keyint=$keyint" : '';
+ my $VBRArg = $vbr ? ":vbitrate=$vbr" : '';
+
+ # Why use both mencoder and transcode?
+ # Why video with one and audio with the other? In short,
+ # because I could not make it work any other way. mencoder does
+ # not seek correctly in Variable Bit Rate files (like MPEG), so
+ # cutlists won't work with mencoder. transcode seems unwilling
+ # to just do passthrough from mpeg to mpeg without encoding
+ # *something*. So, until mythtranscode works, or mplayer2
+ # is finished...this works. -- Russ (russ (at) undef.us)
+ my $BaseMencoder = 'mencoder -oac copy -ovc lavc -lavcopts vcodec=mpeg4:vstrict=1:vhq';
+
+ my $BaseTranscode = 'transcode -xdivx -yraw -P1';
+ my $ABRArg = $abr ? "-b$abr" : '';
+ my $IncludeArg = $Includes ? "-c$Includes" : '';
+ print qq{About to run $BaseMencoder$KeyIntArg$VBRArg -o $output.tmp $input\n} if $verbose;
+ print qq{ followed by $BaseTranscode $ABRArg $IncludeArg -i $output.tmp -o $output\n} if $verbose;
+ system(qq{$BaseMencoder$KeyIntArg$VBRArg -o $output.tmp $input}) and die "mencoder failed";
+ system(qq{$BaseTranscode $ABRArg $IncludeArg -i $output.tmp -o $output}) and die "transcode failed";
+ unlink "$output.tmp" || die "failed to remove temp file" if $remove;
+ } else {
+ $files = makesegments($dbh, $input, $vbr, $keyint, $abr, $pause, $stoprun,
+ $transcode, $skiperrors, $autotrans, @inclist);
+ return if (getError($dbh, $input));
+ makevideo($dbh, $input, $files, $output, $remove, $pause, $stoprun, $skiperrors);
+ return if (getError($dbh, $input));
+ }
@@ -1020,5 +1083,6 @@ sub doshow {
- $dbh->do('delete from videometadata where filename="' . $output . '"');
- $sth = $dbh->prepare('insert into videometadata(title, plot, rating, filename, showlevel) values(?, ?, ?, ?, ?)');
- $sth->execute($title, $desc, "NR", $output, "1");
- $sth->finish();
- }
+ };
+
+ $dbh->do('delete from videometadata where filename="' . $output . '"');
+ $sth = $dbh->prepare('insert into videometadata(title, plot, rating, filename, showlevel) values(?, ?, ?, ?, ?)');
+ $sth->execute($title, $desc, "NR", $output, "1");
+ $sth->finish();
@@ -1049,3 +1113,3 @@ sub getinput {
- my ($y, $x, $prompt, $input, $mask) = @_;
- my ($pos, $line, $col, $startcol, $key, $msg);
- my ($original, $temp) = $input;
+ my ($y, $x, $prompt, $input, $mask, $cancelvalue) = @_;
+ my ($pos, $line, $col, $startcol, $key, $msg, $temp);
+ my $original = $cancelvalue;
@@ -1080,0 +1145,2 @@ sub getinput {
+ move($y,$x);
+ clrtoeol();
@@ -1253 +1319 @@ sub dointeractive {
- my (@shows, $lineno, $index, @vals, @info, $temp);
+ my (@shows, $lineno, $index, @vals, @info, $temp, $videodir);
@@ -1260,0 +1327 @@ sub dointeractive {
+ ($videodir) = $dbh->selectrow_array('select data from settings where value="VideoStartupDir"');
@@ -1332 +1399,8 @@ sub dointeractive {
- $vals[6] = getinput ($LINES-1, 0, "Enter Output Filename:", $vals[6], '[A-Za-z0-9\-_/\.]+');
+ # Provide a default filename (suggesting a full path)
+ my $tempoutput = '';
+ if (not $vals[6]){
+ my $temptitle = "$vals[3]-$vals[4]";
+ $temptitle =~ s/[^A-Za-z0-9\-_\.]/_/g;
+ $tempoutput = "$videodir/$temptitle";
+ }
+ $vals[6] = getinput ($LINES-1, 0, "Enter Output Filename:", ($vals[6] || $tempoutput), '[A-Za-z0-9\-_/\.]+', $vals[6]);
More information about the mythtv-dev
mailing list