You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
k3b/src/rip/videodvd/k3bvideodvdrippingjob.cpp

386 lines
11 KiB

/*
*
* $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
* Copyright (C) 2006 Sebastian Trueg <trueg@k3b.org>
*
* This file is part of the K3b project.
* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* See the file "COPYING" for the exact licensing terms.
*/
#include "k3bvideodvdrippingjob.h"
#include <k3bvideodvdtitletranscodingjob.h>
#include <k3bvideodvdtitledetectclippingjob.h>
#include <kdebug.h>
#include <tdelocale.h>
K3bVideoDVDRippingJob::TitleRipInfo::TitleRipInfo()
: title(1),
audioStream(0),
width(0),
height(0),
videoBitrate(0),
clipTop(0),
clipLeft(0),
clipBottom(0),
clipRight(0)
{
}
K3bVideoDVDRippingJob::TitleRipInfo::TitleRipInfo( int _title,
int _audioStream,
const TQString& fn,
int _width,
int _height,
int _videoBitrate,
int _clipTop,
int _clipLeft,
int _clipBottom,
int _clipRight )
: title(_title),
audioStream(_audioStream),
filename(fn),
width(_width),
height(_height),
videoBitrate(_videoBitrate),
clipTop(_clipTop),
clipLeft(_clipLeft),
clipBottom(_clipBottom),
clipRight(_clipRight)
{
}
class K3bVideoDVDRippingJob::Private {
public:
Private()
: autoClipping( true ) {
}
unsigned int currentTitleInfoIndex;
bool autoClipping;
bool canceled;
int videoBitrate;
int failedTitles;
TQValueVector<double> titleProgressParts;
TQValueVector<double> titleClippingProgressParts;
};
K3bVideoDVDRippingJob::K3bVideoDVDRippingJob( K3bJobHandler* hdl, TQObject* parent )
: K3bJob( hdl, parent )
{
d = new Private();
m_transcodingJob = new K3bVideoDVDTitleTranscodingJob( this, this );
connectSubJob( m_transcodingJob,
TQT_SLOT(slotTranscodingJobFinished(bool)),
TQT_SIGNAL(newTask(const TQString&)),
TQT_SIGNAL(newSubTask(const TQString&)),
TQT_SLOT(slotTranscodingProgress(int)),
TQT_SIGNAL(subPercent(int)),
0,
0 );
m_detectClippingJob = 0;
}
K3bVideoDVDRippingJob::~K3bVideoDVDRippingJob()
{
delete d;
}
TQString K3bVideoDVDRippingJob::jobDescription() const
{
return i18n("Ripping Video DVD Titles");
}
TQString K3bVideoDVDRippingJob::jobDetails() const
{
return i18n("Transcoding %n title to %1/%2", "Transcoding %n titles to %1/%2", m_titleRipInfos.count() )
.arg( K3bVideoDVDTitleTranscodingJob::videoCodecString( m_transcodingJob->videoCodec() ) )
.arg( K3bVideoDVDTitleTranscodingJob::audioCodecString( m_transcodingJob->audioCodec() ) );
}
void K3bVideoDVDRippingJob::start()
{
jobStarted();
d->canceled = false;
d->failedTitles = 0;
initProgressInfo();
if( d->autoClipping )
startDetectClipping( 0 );
else
startTranscoding( 0 );
}
void K3bVideoDVDRippingJob::slotTranscodingJobFinished( bool success )
{
if( d->canceled ) {
emit canceled();
jobFinished( false );
}
else {
if( success )
emit infoMessage( i18n("Successfully ripped title %1").arg(m_titleRipInfos[d->currentTitleInfoIndex].title), SUCCESS );
else {
d->failedTitles++;
emit infoMessage( i18n("Failed to rip title %1").arg(m_titleRipInfos[d->currentTitleInfoIndex].title), ERROR );
}
++d->currentTitleInfoIndex ;
if( d->currentTitleInfoIndex < m_titleRipInfos.count() ) {
if( d->autoClipping )
startDetectClipping( d->currentTitleInfoIndex );
else
startTranscoding( d->currentTitleInfoIndex );
}
else {
jobFinished( d->failedTitles == 0 );
}
}
}
void K3bVideoDVDRippingJob::slotDetectClippingJobFinished( bool success )
{
if( d->canceled ) {
emit canceled();
jobFinished( false );
}
else {
m_titleRipInfos[d->currentTitleInfoIndex].clipTop = 0;
m_titleRipInfos[d->currentTitleInfoIndex].clipLeft = 0;
m_titleRipInfos[d->currentTitleInfoIndex].clipBottom = 0;
m_titleRipInfos[d->currentTitleInfoIndex].clipRight = 0;
if( success ) {
emit infoMessage( i18n("Determined clipping values for title %1").arg(m_titleRipInfos[d->currentTitleInfoIndex].title), SUCCESS );
emit infoMessage( i18n("Top: %1, Bottom: %2")
.arg(m_detectClippingJob->clippingTop()).arg(m_detectClippingJob->clippingBottom()), INFO );
emit infoMessage( i18n("Left: %1, Right: %2")
.arg(m_detectClippingJob->clippingLeft()).arg(m_detectClippingJob->clippingRight()), INFO );
// let's see if the clipping values make sense
if( m_detectClippingJob->clippingTop() + m_detectClippingJob->clippingBottom()
>= (int)m_dvd[d->currentTitleInfoIndex].videoStream().pictureHeight() ||
m_detectClippingJob->clippingLeft() + m_detectClippingJob->clippingRight()
>= (int)m_dvd[d->currentTitleInfoIndex].videoStream().pictureWidth() ) {
emit infoMessage( i18n("Insane clipping values. No clipping will be done at all."), WARNING );
}
else {
m_titleRipInfos[d->currentTitleInfoIndex].clipTop = m_detectClippingJob->clippingTop();
m_titleRipInfos[d->currentTitleInfoIndex].clipLeft = m_detectClippingJob->clippingLeft();
m_titleRipInfos[d->currentTitleInfoIndex].clipBottom = m_detectClippingJob->clippingBottom();
m_titleRipInfos[d->currentTitleInfoIndex].clipRight = m_detectClippingJob->clippingRight();
}
}
else
emit infoMessage( i18n("Failed to determine clipping values for title %1").arg(m_titleRipInfos[d->currentTitleInfoIndex].title), ERROR );
startTranscoding( d->currentTitleInfoIndex );
}
}
void K3bVideoDVDRippingJob::startTranscoding( int ripInfoIndex )
{
d->currentTitleInfoIndex = ripInfoIndex;
m_transcodingJob->setVideoDVD( m_dvd );
m_transcodingJob->setTitle( m_titleRipInfos[ripInfoIndex].title );
m_transcodingJob->setAudioStream( m_titleRipInfos[ripInfoIndex].audioStream );
m_transcodingJob->setClipping( m_titleRipInfos[ripInfoIndex].clipTop,
m_titleRipInfos[ripInfoIndex].clipLeft,
m_titleRipInfos[ripInfoIndex].clipBottom,
m_titleRipInfos[ripInfoIndex].clipRight );
m_transcodingJob->setSize( m_titleRipInfos[ripInfoIndex].width, m_titleRipInfos[ripInfoIndex].height );
m_transcodingJob->setFilename( m_titleRipInfos[ripInfoIndex].filename );
if( m_titleRipInfos[ripInfoIndex].videoBitrate > 0 )
m_transcodingJob->setVideoBitrate( m_titleRipInfos[ripInfoIndex].videoBitrate );
else
m_transcodingJob->setVideoBitrate( d->videoBitrate );
m_transcodingJob->start();
}
void K3bVideoDVDRippingJob::startDetectClipping( int ripInfoIndex )
{
d->currentTitleInfoIndex = ripInfoIndex;
if( !m_detectClippingJob ) {
m_detectClippingJob = new K3bVideoDVDTitleDetectClippingJob( this, this );
connectSubJob( m_detectClippingJob,
TQT_SLOT(slotDetectClippingJobFinished(bool)),
TQT_SIGNAL(newTask(const TQString&)),
TQT_SIGNAL(newSubTask(const TQString&)),
TQT_SLOT(slotDetectClippingProgress(int)),
TQT_SIGNAL(subPercent(int)),
0,
0 );
}
m_detectClippingJob->setVideoDVD( m_dvd );
m_detectClippingJob->setTitle( m_titleRipInfos[ripInfoIndex].title );
m_detectClippingJob->setLowPriority( m_transcodingJob->lowPriority() );
m_detectClippingJob->start();
}
void K3bVideoDVDRippingJob::slotTranscodingProgress( int p )
{
// calculate the part already done
double doneParts = 0.0;
for( unsigned int i = 0; i < d->currentTitleInfoIndex; ++i ) {
doneParts += d->titleProgressParts[i];
if( d->autoClipping )
doneParts += d->titleClippingProgressParts[i];
}
if( d->autoClipping )
doneParts += d->titleClippingProgressParts[d->currentTitleInfoIndex];
// and the current thing
doneParts += (double)p/100.0*d->titleProgressParts[d->currentTitleInfoIndex];
emit percent( (int)( 100.0*doneParts ) );
}
void K3bVideoDVDRippingJob::slotDetectClippingProgress( int p )
{
// calculate the part already done
double doneParts = 0.0;
for( unsigned int i = 0; i < d->currentTitleInfoIndex; ++i ) {
doneParts += d->titleProgressParts[i];
doneParts += d->titleClippingProgressParts[i];
}
// and the current thing
doneParts += (double)p/100.0*d->titleClippingProgressParts[d->currentTitleInfoIndex];
emit percent( (int)( 100.0*doneParts ) );
}
void K3bVideoDVDRippingJob::cancel()
{
d->canceled = true;
if( m_transcodingJob->active() )
m_transcodingJob->cancel();
else if( m_detectClippingJob && m_detectClippingJob->active() )
m_detectClippingJob->cancel();
}
void K3bVideoDVDRippingJob::setVideoCodec( K3bVideoDVDTitleTranscodingJob::VideoCodec codec )
{
m_transcodingJob->setVideoCodec( codec );
}
void K3bVideoDVDRippingJob::setVideoBitrate( int bitrate )
{
d->videoBitrate = bitrate;
}
void K3bVideoDVDRippingJob::setTwoPassEncoding( bool b )
{
m_transcodingJob->setTwoPassEncoding( b );
}
void K3bVideoDVDRippingJob::setAudioCodec( K3bVideoDVDTitleTranscodingJob::AudioCodec codec )
{
m_transcodingJob->setAudioCodec( codec );
}
void K3bVideoDVDRippingJob::setAudioBitrate( int bitrate )
{
m_transcodingJob->setAudioBitrate( bitrate );
}
void K3bVideoDVDRippingJob::setAudioVBR( bool vbr )
{
m_transcodingJob->setAudioVBR( vbr );
}
void K3bVideoDVDRippingJob::setResampleAudioTo44100( bool b )
{
m_transcodingJob->setResampleAudioTo44100( b );
}
void K3bVideoDVDRippingJob::setLowPriority( bool b )
{
m_transcodingJob->setLowPriority( b );
}
void K3bVideoDVDRippingJob::setAutoClipping( bool b )
{
d->autoClipping = b;
}
void K3bVideoDVDRippingJob::initProgressInfo()
{
d->titleProgressParts.resize( m_titleRipInfos.count() );
d->titleClippingProgressParts.resize( m_titleRipInfos.count() );
unsigned long long totalFrames = 0ULL;
for( unsigned int i = 0; i < m_titleRipInfos.count(); ++i ) {
if( m_transcodingJob->twoPassEncoding() )
totalFrames += m_dvd[m_titleRipInfos[i].title-1].playbackTime().totalFrames() * 2;
else
totalFrames += m_dvd[m_titleRipInfos[i].title-1].playbackTime().totalFrames();
// using my knowledge of the internals of the clipping detection job: it decodes 200 frames
// of every chapter
if( d->autoClipping )
totalFrames += m_dvd[m_titleRipInfos[i].title-1].numChapters() * 200;
}
for( unsigned int i = 0; i < m_titleRipInfos.count(); ++i ) {
unsigned long long titleFrames = m_dvd[m_titleRipInfos[i].title-1].playbackTime().totalFrames();
if( m_transcodingJob->twoPassEncoding() )
titleFrames *= 2;
// using my knowledge of the internals of the clipping detection job: it decodes 200 frames
// of every chapter
unsigned long long titleClippingFrames = m_dvd[m_titleRipInfos[i].title-1].numChapters() * 200;
d->titleProgressParts[i] = (double)titleFrames/(double)totalFrames;
d->titleClippingProgressParts[i] = (double)titleClippingFrames/(double)totalFrames;
}
}
#include "k3bvideodvdrippingjob.moc"