/usr/local/CPAN/dvdrip/Video/DVDRip/Cluster/Title.pm
# $Id: Title.pm 2397 2010-03-06 13:06:33Z joern $
#-----------------------------------------------------------------------
# Copyright (C) 2001-2006 Jörn Reder <joern AT zyn.de>.
# All Rights Reserved. See file COPYRIGHT for details.
#
# This program is part of Video::DVDRip, which is free software; you can
# redistribute it and/or modify it under the same terms as Perl itself.
#-----------------------------------------------------------------------
package Video::DVDRip::Cluster::Title;
use Locale::TextDomain qw (video.dvdrip);
use base Video::DVDRip::Title;
use Carp;
use strict;
use File::Basename;
sub frames_finished { shift->{frames_finished} }
sub with_cleanup { shift->{with_cleanup} }
sub with_vob_remove { shift->{with_vob_remove} }
sub frames_per_chunk { shift->{frames_per_chunk} }
sub set_frames_finished { shift->{frames_finished} = $_[1] }
sub set_with_cleanup { shift->{with_cleanup} = $_[1] }
sub set_with_vob_remove { shift->{with_vob_remove} = $_[1] }
sub set_frames_per_chunk { shift->{frames_per_chunk} = $_[1] }
sub info {
my $self = shift;
return $self->project->name . " (#" . $self->nr . ")";
}
sub create_vob_dir {
my $self = shift;
# no vob_dir creating here. This is done just before we
# start transcoding to prevent from too much ssh remote
# communication.
return 1;
}
sub create_avi_dir {
my $self = shift;
# no avi_dir creating here. This is done just before we
# start transcoding to prevent from too much ssh remote
# communication.
return 1;
}
sub is_ripped {
return 1;
}
#-----------------------------------------------------------------------
# Filenames of all stages
#-----------------------------------------------------------------------
sub multipass_log_dir { # directory for multipass logs
my $self = shift;
my $job = $Event::ExecFlow::JOB;
return sprintf (
"%s/%s/cluster/%03d-%02d-%05d",
$job->get_node->data_base_dir,
$self->project->name,
$self->nr,
$job->get_stash->{psu},
$job->get_stash->{chunk},
);
}
sub avi_chunks_dir { # directory for avi chunks
my $self = shift;
my $job = $Event::ExecFlow::JOB;
return sprintf (
"%s/%03d/chunks-psu-%02d",
$self->project->final_avi_dir,
$self->nr,
$job->get_stash->{psu},
);
}
sub avi_file { # transcode output file
my $self = shift;
my $job = $Event::ExecFlow::JOB;
return sprintf (
"%s/%s-%03d-%05d.avi",
$self->avi_chunks_dir,
$self->project->name,
$self->nr,
$job->get_stash->{chunk},
);
}
sub target_avi_audio_file {
my $self = shift;
my $ext = $self->is_ogg ? $self->config('ogg_file_ext') : 'avi';
my $job = $Event::ExecFlow::JOB;
return sprintf (
"%s/%03d/audio-psu-%02d/%s-%03d-audio-psu-%02d-%02d.$ext",
$self->project->final_avi_dir,
$self->nr,
$job->get_stash->{psu},
$self->project->name,
$self->nr,
$job->get_stash->{psu},
$job->get_stash->{avi_nr},
);
}
sub audio_video_psu_dir {
my $self = shift;
return sprintf (
"%s/%03d/audio-video-psu",
$self->project->final_avi_dir,
$self->nr,
);
}
sub audio_video_psu_file {
my $self = shift;
my $ext = $self->is_ogg ? $self->config('ogg_file_ext') : 'avi';
my $job = $Event::ExecFlow::JOB;
return sprintf (
"%s/%s-%03d-av-psu-%02d.$ext",
$self->audio_video_psu_dir,
$self->project->name,
$self->nr,
$job->get_stash->{psu},
);
}
sub target_avi_file { # final avi, merged PSUs + audio
my $self = shift;
my $ext = $self->is_ogg ? $self->config('ogg_file_ext') : 'avi';
return sprintf(
"%s/%03d/%s-%03d.$ext",
$self->project->final_avi_dir,
$self->nr,
$self->project->name,
$self->nr
);
}
#-----------------------------------------------------------------------
# Commands for all Jobs
#-----------------------------------------------------------------------
sub get_transcode_command {
my $self = shift;
my $psu = "DVDRIP_JOB_PSU";
my $chunk = "DVDRIP_JOB_CHUNK";
my $chunk_cnt = "DVDRIP_JOB_CHUNK_CNT";
my $nav_file = $self->vob_nav_file;
my $command = $self->SUPER::get_transcode_command(
no_audio => 1,
@_
);
# remove EXECFLOW_OK
$command =~ s/&&\s+echo\s+EXECFLOW_OK//;
# no audio options
$command =~ s/\s-[baN]\s+[^\s]+//;
# no -c in cluster mode
$command =~ s/ -c \d+-\d+//;
# no preview in cluster mode
$command =~ s/-J\s+preview=[^\s]+//;
# add -S and -W options for chunk selection (dont' just append,
# because the transcode command probably got appended some
# additional shell commands - e.g. h264 log copy stuff)
$command =~
s{ (execflow.*?transcode) }
{ $1 -S $psu -W $chunk,$chunk_cnt,$nav_file };
# sorry, can't remember why I do that...
$command =~ s/-M 2//;
# add directory creation code
my $avi_dir = dirname $self->avi_file;
$command = "mkdir -m 0775 -p '$avi_dir' && $command";
# add EXECFLOW_OK
$command .= " && echo EXECFLOW_OK";
return $command;
}
sub get_transcode_audio_command {
my $self = shift;
my %par = @_;
my ( $vob_nr, $target_nr ) = @par{ 'vob_nr', 'target_nr' };
my $command = $self->SUPER::get_transcode_audio_command(@_);
$command =~ s/\s+&& echo EXECFLOW_OK//;
if ( $self->version("transcode") >= 10100 ) {
$command .=
" --psu_mode --no_split"
. " --psu_chunks DVDRIP_JOB_PSU-DVDRIP_JOB_ADD_ONE_PSU"
. " --nav_seek ".$self->vob_nav_file;
}
else {
$command .=
" -S DVDRIP_JOB_PSU"
. " -W DVDRIP_JOB_CHUNK_CNT,DVDRIP_JOB_CHUNK_CNT,"
. $self->vob_nav_file;
}
$command .= " && echo EXECFLOW_OK";
return $command;
}
sub get_merge_audio_command {
my $self = shift;
my %par = @_;
my ( $vob_nr, $target_nr ) = @par{ 'vob_nr', 'target_nr' };
my $avi_file = $self->audio_video_psu_file;
my $audio_file = $self->target_avi_audio_file;
my $target_file = $avi_file;
my $command;
my $nice;
$nice = "`which nice` -n " . $self->tc_nice . " "
if $self->tc_nice =~ /\S/;
$command = $nice;
# operate on final avi file if no PSU merging is necessary
# if ( @{$self->program_stream_units} == 1 ) {
# $avi_file = $self->target_avi_file;
# $target_file = $self->target_avi_file;
# }
if ( $self->is_ogg ) {
# remove audio_video_psu file here, because
# this isn't done in get_merge_video_audio_command,
# because audio merging is done here with ogg.
my $audio_video_psu_file;
$audio_video_psu_file = $self->audio_video_psu_file
if $self->with_cleanup
and $self->audio_video_psu_file ne $target_file;
$command .= "execflow ogmmerge -o $avi_file.merged "
. " $avi_file"
. " $audio_file &&"
. " mv $avi_file.merged $target_file &&"
. " rm -f $audio_file $audio_video_psu_file &&"
. " echo EXECFLOW_OK";
}
else {
$command .= "execflow avimerge"
. " -p $audio_file"
. " -a $target_nr"
. " -o $avi_file.merged"
. " -i $avi_file &&"
. " mv $avi_file.merged $target_file &&"
. " rm $audio_file &&"
. " echo EXECFLOW_OK";
}
return $command;
}
sub get_merge_video_audio_command {
my $self = shift;
#-- with one PSU and AVI processing this avimerge file
#-- creates the final file
my $move_final = 0;
# @{$self->program_stream_units} == 1 && !$self->is_ogg;
my $avi_chunks_dir = $self->avi_chunks_dir;
my $audio_video_psu_file = $self->audio_video_psu_file;
$audio_video_psu_file = $self->target_avi_file
if $move_final;
my $audio_video_psu_dir = dirname($audio_video_psu_file);
my $audio_psu_file = $self->target_avi_audio_file;
my $chunks_mask = sprintf( "%s/%03d/chunks-psu-??/*",
$self->project->final_avi_dir, $self->nr );
my $nice;
$nice = "`which nice` -n " . $self->tc_nice . " "
if $self->tc_nice =~ /\S/;
my $command = "mkdir -m 0775 -p '$audio_video_psu_dir' && "
. "${nice}execflow avimerge -o $audio_video_psu_file";
$command .= " -p $audio_psu_file " if !$self->is_ogg;
#-- -i *always* at the end! At some time avimerge's cmd line
#-- parser was messed up...
$command .= " -i $avi_chunks_dir/*";
$command .= " && rm $avi_chunks_dir/*"
if $self->with_cleanup;
$command .= " '$audio_psu_file'"
if $self->with_cleanup
and not $self->is_ogg;
$command .= " && echo EXECFLOW_OK";
return $command;
}
sub get_merge_psu_command {
my $self = shift;
my %par = @_;
my ($psu) = @par{'psu'};
my $target_avi_file = $self->target_avi_file;
my $target_avi_dir = dirname($target_avi_file);
my $audio_video_psu_dir = $self->audio_video_psu_dir;
my $ext = $self->is_ogg ? $self->config('ogg_file_ext') : 'avi';
my $nice;
$nice = "`which nice` -n " . $self->tc_nice . " "
if $self->tc_nice =~ /\S/;
my $command
= "mkdir -m 0775 -p '$target_avi_dir' && " . "${nice}execflow ";
if ( $self->is_ogg ) {
$command .= "ogmcat -v -v "; # -v -v to prevent timeouts
}
else {
$command .= "avimerge ";
}
$command .= "-o '$target_avi_file' ";
$command .= "-i " if not $self->is_ogg;
$command .= "$audio_video_psu_dir/*.$ext";
$command .= " && echo EXECFLOW_OK";
$command .= " && rm $audio_video_psu_dir/*.$ext"
if $self->with_cleanup;
return $command;
}
sub get_split_command {
my $self = shift;
my $target_avi_file = $self->target_avi_file;
my $command = $self->SUPER::get_split_command;
$command .= " && rm '$target_avi_file'"
if $self->with_cleanup
and $command =~ /avisplit|ogmsplit/;
return $command;
}
sub save {
my $self = shift;
$self->project->save;
1;
}
1;