File indexing completed on 2024-05-12 04:51:52
0001 /* 0002 SPDX-FileCopyrightText: 2006-2009 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "k3bvideodvdrippingjob.h" 0009 0010 #include "k3bvideodvdtitletranscodingjob.h" 0011 #include "k3bvideodvdtitledetectclippingjob.h" 0012 0013 #include <QDebug> 0014 #include <KLocalizedString> 0015 0016 0017 K3b::VideoDVDRippingJob::TitleRipInfo::TitleRipInfo() 0018 : title(1), 0019 audioStream(0), 0020 width(0), 0021 height(0), 0022 videoBitrate(0), 0023 clipTop(0), 0024 clipLeft(0), 0025 clipBottom(0), 0026 clipRight(0) 0027 { 0028 } 0029 0030 0031 K3b::VideoDVDRippingJob::TitleRipInfo::TitleRipInfo( int _title, 0032 int _audioStream, 0033 const QString& fn, 0034 int _width, 0035 int _height, 0036 int _videoBitrate, 0037 int _clipTop, 0038 int _clipLeft, 0039 int _clipBottom, 0040 int _clipRight ) 0041 : title(_title), 0042 audioStream(_audioStream), 0043 filename(fn), 0044 width(_width), 0045 height(_height), 0046 videoBitrate(_videoBitrate), 0047 clipTop(_clipTop), 0048 clipLeft(_clipLeft), 0049 clipBottom(_clipBottom), 0050 clipRight(_clipRight) 0051 { 0052 } 0053 0054 0055 0056 class K3b::VideoDVDRippingJob::Private { 0057 public: 0058 Private() 0059 : autoClipping( true ) { 0060 } 0061 0062 int currentTitleInfoIndex; 0063 bool autoClipping; 0064 0065 bool canceled; 0066 0067 int videoBitrate; 0068 0069 int failedTitles; 0070 0071 QVector<double> titleProgressParts; 0072 QVector<double> titleClippingProgressParts; 0073 }; 0074 0075 0076 0077 K3b::VideoDVDRippingJob::VideoDVDRippingJob( K3b::JobHandler* hdl, QObject* parent ) 0078 : K3b::Job( hdl, parent ) 0079 { 0080 d = new Private(); 0081 0082 m_transcodingJob = new K3b::VideoDVDTitleTranscodingJob( this, this ); 0083 connectSubJob( m_transcodingJob, 0084 SLOT(slotTranscodingJobFinished(bool)), 0085 SIGNAL(newTask(QString)), 0086 SIGNAL(newSubTask(QString)), 0087 SLOT(slotTranscodingProgress(int)), 0088 SIGNAL(subPercent(int)), 0089 0, 0090 0 ); 0091 m_detectClippingJob = 0; 0092 } 0093 0094 0095 K3b::VideoDVDRippingJob::~VideoDVDRippingJob() 0096 { 0097 delete d; 0098 } 0099 0100 0101 QString K3b::VideoDVDRippingJob::jobDescription() const 0102 { 0103 return i18n("Ripping Video DVD Titles"); 0104 } 0105 0106 0107 QString K3b::VideoDVDRippingJob::jobDetails() const 0108 { 0109 return i18np("Transcoding 1 title to %2/%3", "Transcoding %1 titles to %2/%3", m_titleRipInfos.count(), 0110 K3b::VideoDVDTitleTranscodingJob::videoCodecString( m_transcodingJob->videoCodec() ) , 0111 K3b::VideoDVDTitleTranscodingJob::audioCodecString( m_transcodingJob->audioCodec() ) ); 0112 } 0113 0114 0115 void K3b::VideoDVDRippingJob::start() 0116 { 0117 jobStarted(); 0118 d->canceled = false; 0119 d->failedTitles = 0; 0120 0121 initProgressInfo(); 0122 0123 if( d->autoClipping ) 0124 startDetectClipping( 0 ); 0125 else 0126 startTranscoding( 0 ); 0127 } 0128 0129 0130 void K3b::VideoDVDRippingJob::slotTranscodingJobFinished( bool success ) 0131 { 0132 if( d->canceled ) { 0133 emit canceled(); 0134 jobFinished( false ); 0135 } 0136 else { 0137 if( success ) 0138 emit infoMessage( i18n("Successfully ripped title %1 to '%2'", 0139 m_titleRipInfos[d->currentTitleInfoIndex].title, 0140 m_titleRipInfos[d->currentTitleInfoIndex].filename ), MessageSuccess ); 0141 else { 0142 d->failedTitles++; 0143 emit infoMessage( i18n("Failed to rip title %1", m_titleRipInfos[d->currentTitleInfoIndex].title), MessageError ); 0144 } 0145 0146 ++d->currentTitleInfoIndex ; 0147 if( d->currentTitleInfoIndex < m_titleRipInfos.count() ) { 0148 if( d->autoClipping ) 0149 startDetectClipping( d->currentTitleInfoIndex ); 0150 else 0151 startTranscoding( d->currentTitleInfoIndex ); 0152 } 0153 else { 0154 jobFinished( d->failedTitles == 0 ); 0155 } 0156 } 0157 } 0158 0159 0160 void K3b::VideoDVDRippingJob::slotDetectClippingJobFinished( bool success ) 0161 { 0162 if( d->canceled ) { 0163 emit canceled(); 0164 jobFinished( false ); 0165 } 0166 else { 0167 m_titleRipInfos[d->currentTitleInfoIndex].clipTop = 0; 0168 m_titleRipInfos[d->currentTitleInfoIndex].clipLeft = 0; 0169 m_titleRipInfos[d->currentTitleInfoIndex].clipBottom = 0; 0170 m_titleRipInfos[d->currentTitleInfoIndex].clipRight = 0; 0171 0172 if( success ) { 0173 emit infoMessage( i18n("Determined clipping values for title %1",m_titleRipInfos[d->currentTitleInfoIndex].title), MessageSuccess ); 0174 emit infoMessage( i18n("Top: %1, Bottom: %2", m_detectClippingJob->clippingTop(), m_detectClippingJob->clippingBottom()), MessageInfo ); 0175 emit infoMessage( i18n("Left: %1, Right: %2", m_detectClippingJob->clippingLeft(), m_detectClippingJob->clippingRight()), MessageInfo ); 0176 0177 // let's see if the clipping values make sense 0178 if( m_detectClippingJob->clippingTop() + m_detectClippingJob->clippingBottom() 0179 >= (int)m_dvd[d->currentTitleInfoIndex].videoStream().pictureHeight() || 0180 m_detectClippingJob->clippingLeft() + m_detectClippingJob->clippingRight() 0181 >= (int)m_dvd[d->currentTitleInfoIndex].videoStream().pictureWidth() ) { 0182 emit infoMessage( i18n("Insane clipping values. No clipping will be done at all."), MessageWarning ); 0183 } 0184 else { 0185 m_titleRipInfos[d->currentTitleInfoIndex].clipTop = m_detectClippingJob->clippingTop(); 0186 m_titleRipInfos[d->currentTitleInfoIndex].clipLeft = m_detectClippingJob->clippingLeft(); 0187 m_titleRipInfos[d->currentTitleInfoIndex].clipBottom = m_detectClippingJob->clippingBottom(); 0188 m_titleRipInfos[d->currentTitleInfoIndex].clipRight = m_detectClippingJob->clippingRight(); 0189 } 0190 } 0191 else 0192 emit infoMessage( i18n("Failed to determine clipping values for title %1",m_titleRipInfos[d->currentTitleInfoIndex].title), MessageError ); 0193 0194 startTranscoding( d->currentTitleInfoIndex ); 0195 } 0196 } 0197 0198 0199 void K3b::VideoDVDRippingJob::startTranscoding( int ripInfoIndex ) 0200 { 0201 d->currentTitleInfoIndex = ripInfoIndex; 0202 0203 m_transcodingJob->setVideoDVD( m_dvd ); 0204 m_transcodingJob->setTitle( m_titleRipInfos[ripInfoIndex].title ); 0205 m_transcodingJob->setAudioStream( m_titleRipInfos[ripInfoIndex].audioStream ); 0206 m_transcodingJob->setClipping( m_titleRipInfos[ripInfoIndex].clipTop, 0207 m_titleRipInfos[ripInfoIndex].clipLeft, 0208 m_titleRipInfos[ripInfoIndex].clipBottom, 0209 m_titleRipInfos[ripInfoIndex].clipRight ); 0210 m_transcodingJob->setSize( m_titleRipInfos[ripInfoIndex].width, m_titleRipInfos[ripInfoIndex].height ); 0211 m_transcodingJob->setFilename( m_titleRipInfos[ripInfoIndex].filename ); 0212 0213 if( m_titleRipInfos[ripInfoIndex].videoBitrate > 0 ) 0214 m_transcodingJob->setVideoBitrate( m_titleRipInfos[ripInfoIndex].videoBitrate ); 0215 else 0216 m_transcodingJob->setVideoBitrate( d->videoBitrate ); 0217 0218 m_transcodingJob->start(); 0219 } 0220 0221 0222 void K3b::VideoDVDRippingJob::startDetectClipping( int ripInfoIndex ) 0223 { 0224 d->currentTitleInfoIndex = ripInfoIndex; 0225 0226 if( !m_detectClippingJob ) { 0227 m_detectClippingJob = new K3b::VideoDVDTitleDetectClippingJob( this, this ); 0228 connectSubJob( m_detectClippingJob, 0229 SLOT(slotDetectClippingJobFinished(bool)), 0230 SIGNAL(newTask(QString)), 0231 SIGNAL(newSubTask(QString)), 0232 SLOT(slotDetectClippingProgress(int)), 0233 SIGNAL(subPercent(int)), 0234 0, 0235 0 ); 0236 } 0237 0238 m_detectClippingJob->setVideoDVD( m_dvd ); 0239 m_detectClippingJob->setTitle( m_titleRipInfos[ripInfoIndex].title ); 0240 m_detectClippingJob->setLowPriority( m_transcodingJob->lowPriority() ); 0241 0242 m_detectClippingJob->start(); 0243 } 0244 0245 0246 void K3b::VideoDVDRippingJob::slotTranscodingProgress( int p ) 0247 { 0248 // calculate the part already done 0249 double doneParts = 0.0; 0250 for( int i = 0; i < d->currentTitleInfoIndex; ++i ) { 0251 doneParts += d->titleProgressParts[i]; 0252 if( d->autoClipping ) 0253 doneParts += d->titleClippingProgressParts[i]; 0254 } 0255 if( d->autoClipping ) 0256 doneParts += d->titleClippingProgressParts[d->currentTitleInfoIndex]; 0257 0258 // and the current thing 0259 doneParts += (double)p/100.0*d->titleProgressParts[d->currentTitleInfoIndex]; 0260 0261 emit percent( (int)( 100.0*doneParts ) ); 0262 } 0263 0264 0265 void K3b::VideoDVDRippingJob::slotDetectClippingProgress( int p ) 0266 { 0267 // calculate the part already done 0268 double doneParts = 0.0; 0269 for( int i = 0; i < d->currentTitleInfoIndex; ++i ) { 0270 doneParts += d->titleProgressParts[i]; 0271 doneParts += d->titleClippingProgressParts[i]; 0272 } 0273 0274 // and the current thing 0275 doneParts += (double)p/100.0*d->titleClippingProgressParts[d->currentTitleInfoIndex]; 0276 0277 emit percent( (int)( 100.0*doneParts ) ); 0278 } 0279 0280 0281 void K3b::VideoDVDRippingJob::cancel() 0282 { 0283 d->canceled = true; 0284 if( m_transcodingJob->active() ) 0285 m_transcodingJob->cancel(); 0286 else if( m_detectClippingJob && m_detectClippingJob->active() ) 0287 m_detectClippingJob->cancel(); 0288 } 0289 0290 0291 void K3b::VideoDVDRippingJob::setVideoCodec( K3b::VideoDVDTitleTranscodingJob::VideoCodec codec ) 0292 { 0293 m_transcodingJob->setVideoCodec( codec ); 0294 } 0295 0296 0297 void K3b::VideoDVDRippingJob::setVideoBitrate( int bitrate ) 0298 { 0299 d->videoBitrate = bitrate; 0300 } 0301 0302 0303 void K3b::VideoDVDRippingJob::setTwoPassEncoding( bool b ) 0304 { 0305 m_transcodingJob->setTwoPassEncoding( b ); 0306 } 0307 0308 0309 void K3b::VideoDVDRippingJob::setAudioCodec( K3b::VideoDVDTitleTranscodingJob::AudioCodec codec ) 0310 { 0311 m_transcodingJob->setAudioCodec( codec ); 0312 } 0313 0314 0315 void K3b::VideoDVDRippingJob::setAudioBitrate( int bitrate ) 0316 { 0317 m_transcodingJob->setAudioBitrate( bitrate ); 0318 } 0319 0320 0321 void K3b::VideoDVDRippingJob::setAudioVBR( bool vbr ) 0322 { 0323 m_transcodingJob->setAudioVBR( vbr ); 0324 } 0325 0326 0327 void K3b::VideoDVDRippingJob::setResampleAudioTo44100( bool b ) 0328 { 0329 m_transcodingJob->setResampleAudioTo44100( b ); 0330 } 0331 0332 0333 void K3b::VideoDVDRippingJob::setLowPriority( bool b ) 0334 { 0335 m_transcodingJob->setLowPriority( b ); 0336 } 0337 0338 0339 void K3b::VideoDVDRippingJob::setAutoClipping( bool b ) 0340 { 0341 d->autoClipping = b; 0342 } 0343 0344 0345 void K3b::VideoDVDRippingJob::initProgressInfo() 0346 { 0347 d->titleProgressParts.resize( m_titleRipInfos.count() ); 0348 d->titleClippingProgressParts.resize( m_titleRipInfos.count() ); 0349 0350 unsigned long long totalFrames = 0ULL; 0351 for( int i = 0; i < m_titleRipInfos.count(); ++i ) { 0352 if( m_transcodingJob->twoPassEncoding() ) 0353 totalFrames += m_dvd[m_titleRipInfos[i].title-1].playbackTime().totalFrames() * 2; 0354 else 0355 totalFrames += m_dvd[m_titleRipInfos[i].title-1].playbackTime().totalFrames(); 0356 0357 // using my knowledge of the internals of the clipping detection job: it decodes 200 frames 0358 // of every chapter 0359 if( d->autoClipping ) 0360 totalFrames += m_dvd[m_titleRipInfos[i].title-1].numChapters() * 200; 0361 } 0362 0363 for( int i = 0; i < m_titleRipInfos.count(); ++i ) { 0364 unsigned long long titleFrames = m_dvd[m_titleRipInfos[i].title-1].playbackTime().totalFrames(); 0365 if( m_transcodingJob->twoPassEncoding() ) 0366 titleFrames *= 2; 0367 0368 // using my knowledge of the internals of the clipping detection job: it decodes 200 frames 0369 // of every chapter 0370 unsigned long long titleClippingFrames = m_dvd[m_titleRipInfos[i].title-1].numChapters() * 200; 0371 0372 if (totalFrames) { 0373 d->titleProgressParts[i] = (double)titleFrames/(double)totalFrames; 0374 d->titleClippingProgressParts[i] = (double)titleClippingFrames/(double)totalFrames; 0375 } 0376 } 0377 } 0378 0379 #include "moc_k3bvideodvdrippingjob.cpp"