diff options
Diffstat (limited to 'src/rip/videodvd/k3bvideodvdrippingjob.cpp')
-rw-r--r-- | src/rip/videodvd/k3bvideodvdrippingjob.cpp | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/src/rip/videodvd/k3bvideodvdrippingjob.cpp b/src/rip/videodvd/k3bvideodvdrippingjob.cpp new file mode 100644 index 0000000..c10c127 --- /dev/null +++ b/src/rip/videodvd/k3bvideodvdrippingjob.cpp @@ -0,0 +1,385 @@ +/* + * + * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $ + * Copyright (C) 2006 Sebastian Trueg <[email protected]> + * + * This file is part of the K3b project. + * Copyright (C) 1998-2007 Sebastian Trueg <[email protected]> + * + * 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 <klocale.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 QString& 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; + + QValueVector<double> titleProgressParts; + QValueVector<double> titleClippingProgressParts; +}; + + + +K3bVideoDVDRippingJob::K3bVideoDVDRippingJob( K3bJobHandler* hdl, QObject* parent ) + : K3bJob( hdl, parent ) +{ + d = new Private(); + + m_transcodingJob = new K3bVideoDVDTitleTranscodingJob( this, this ); + connectSubJob( m_transcodingJob, + SLOT(slotTranscodingJobFinished(bool)), + SIGNAL(newTask(const QString&)), + SIGNAL(newSubTask(const QString&)), + SLOT(slotTranscodingProgress(int)), + SIGNAL(subPercent(int)), + 0, + 0 ); + m_detectClippingJob = 0; +} + + +K3bVideoDVDRippingJob::~K3bVideoDVDRippingJob() +{ + delete d; +} + + +QString K3bVideoDVDRippingJob::jobDescription() const +{ + return i18n("Ripping Video DVD Titles"); +} + + +QString 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, + SLOT(slotDetectClippingJobFinished(bool)), + SIGNAL(newTask(const QString&)), + SIGNAL(newSubTask(const QString&)), + SLOT(slotDetectClippingProgress(int)), + 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" |