diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-17 00:32:19 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-17 00:32:19 +0000 |
commit | 0d382a262c0638d0f572fc37193ccc5ed3dc895f (patch) | |
tree | 8578dcddfce4191f3f7a142a37769df7add48475 /libk9copy/k9mp4enc.cpp | |
download | k9copy-0d382a262c0638d0f572fc37193ccc5ed3dc895f.tar.gz k9copy-0d382a262c0638d0f572fc37193ccc5ed3dc895f.zip |
Added old abandoned version of k9copy
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/k9copy@1091546 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'libk9copy/k9mp4enc.cpp')
-rw-r--r-- | libk9copy/k9mp4enc.cpp | 571 |
1 files changed, 571 insertions, 0 deletions
diff --git a/libk9copy/k9mp4enc.cpp b/libk9copy/k9mp4enc.cpp new file mode 100644 index 0000000..7d82c4f --- /dev/null +++ b/libk9copy/k9mp4enc.cpp @@ -0,0 +1,571 @@ +// +// C++ Implementation: k9mp4enc +// +// Description: +// +// +// Author: Jean-Michel PETIT <[email protected]>, (C) 2006 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "k9mp4enc.h" +#include "k9mp4dlg.h" +#include "k9config.h" +#include <qcstring.h> +#include <qapplication.h> +#include <klocale.h> +#include <qstringlist.h> +#include <qdir.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <qstringlist.h> +#include <ktempfile.h> +#include <kstandarddirs.h> +#include "k9tools.h" +#include "k9audiocodecs.h" +#include "k9videocodecs.h" +#include <qcstring.h> + +k9MP4Enc::k9MP4Enc ( QObject *parent, const char *name,const QStringList& ) + : QObject ( parent, name ) +{ + m_fourcc=m_height=m_width=m_audioBitrate=m_videoBitrate=m_filename=""; + m_codec=0; //lavc_mp4; + m_audioCodec=0; + m_cpt=-1; + m_parts=1; + + QStringList laudio; + QStringList llabels; + QStringList lvideo; + + k9Config config; + m_lstAudio=config.getCodecAudio(); + m_lstCodecs=config.getCodecLabels(); + m_lstVideo=config.getCodecVideo(); + + timer = new QTimer ( this ); + connect ( timer, SIGNAL ( timeout() ), this, SLOT ( timerDone() ) ); + m_progress=new k9MP4Dlg ( qApp->mainWidget(),0 ); + +} + +QString k9MP4Enc::round16 ( QString _wh ) +{ + if ( _wh !="" ) + { + int value=_wh.toInt() /16; + return QString::number ( value*16 ); + + } + else + return _wh; + + +} + +QString k9MP4Enc::getChapterList ( k9DVDTitle *_title ) +{ + QString res=""; + QPtrList <k9DVDChapter> chapters=_title->getChapters(); + for ( k9DVDChapter *chapter=chapters.first();chapter;chapter=chapters.next() ) + { + if ( chapter->getSelected() ) + { + res+=res=="" ? QString::number ( chapter->getnum() ) : ","+QString::number ( chapter->getnum() ); + } + } + QPtrList <k9DVDTitle> titles=_title->getTitles(); + + for ( k9DVDTitle *title=titles.first();title;title=titles.next() ) + { + chapters=title->getChapters(); + for ( k9DVDChapter *chapter=chapters.first();chapter;chapter=chapters.next() ) + { + if ( chapter->getSelected() ) + { + res+=res=="" ? QString::number ( chapter->getnum() ) : ","+QString::number ( chapter->getnum() ); + } + } + } + return res; + +} + + +int k9MP4Enc::getselectedSubp ( k9DVDTitle *_title ) +{ + for ( int i=0;i< _title->getsubPictureCount();i++ ) + { + if ( _title->getsubtitle ( i )->getselected() ) + { + return _title->getsubtitle ( i )->getID().first()-1; + } + } + //nos subtitle selected + return -1; +} + + + +void k9MP4Enc::execute ( k9DVDTitle *_title ) +{ + bool error=false; + + if ( m_mpeg2 ) + { + m_parts=1; + m_2pass=false; + } + + if ( ! k9Tools::checkProgram ( "mencoder" ) && ! m_mpeg2 ) + { + KMessageBox::error ( qApp->mainWidget(),i18n ( "Unable to run %1" ).arg ( "mencoder" ) , i18n ( "Encoding error" ) ); + error = TRUE; + return; + } + + time = new QTime ( 0,0 ); + m_percent=0; + m_remain="--:--:--"; + + m_totalSize=_title->getChaptersSize ( true ); + + QString injectName; + KTempFile injectFile ( locateLocal ( "tmp", "k9copy/k9v" ), "" ); + injectFile.setAutoDelete ( true ); + injectFile.close(); + injectName=injectFile.name(); + + + int maxPass=0; + int pass=0; + + //build the cell list for mpeg2 extraction + QMap<QString,int> chapterCells; + QMap<QString, int>::iterator ichapterCells; + QStringList chapters; + if ( m_mpeg2 && m_mpegChapters ) + { + m_parts=0; + chapters=QStringList::split ( ",", getChapterList ( _title ) ); + for ( unsigned int idxChap = 0; idxChap < chapters.size(); idxChap++ ) + { + QString chapter = chapters[idxChap]; + //foreach (QString chapter,chapters) { + int iCell=0; + k9DVDChapter *chap=_title->getChapter ( chapter.toInt()-1 ); + //foreach(k9ChapterCell *cell ,chap->cells) { + iCell++; + chapterCells.insert ( chapter,iCell ); + m_parts++; + //} + } + ichapterCells = chapterCells.begin(); + } + + for ( int m_part =1 ; ( m_part <=m_parts ) && !error ;m_part++ ) + { + if ( m_2pass ) + { + maxPass=2; + pass=1; + } + KTempFile passLogFile ( locateLocal ( "tmp", "k9copy/k9v" ), "" ); + passLogFile.setAutoDelete ( true ); + passLogFile.close(); + + do + { + uint32_t nbSectors= m_totalSize / m_parts ; + + uint32_t startSector= nbSectors* ( m_part-1 ); + uint32_t endSector= startSector+nbSectors; + + //calculer le bitrate en faisant la somme des cells compris entre startSector et endSector + //FIXME Mettre en place la sélection par chapitres + m_stderr=""; + m_title=_title; + if ( m_height=="" || m_height=="0" ) + m_height="-2"; + if ( m_width=="" ) + m_width="640"; + if ( m_audioBitrate=="" ) + m_audioBitrate="128"; + if ( m_size=="" ) + m_size="700"; + if ( m_filename=="" ) + m_filename=KFileDialog::getSaveFileName ( QDir::homeDirPath(),"*.avi", 0,i18n ( "Save file to disk" ) ); + if ( m_filename =="" ) + return; + + QDir d=QDir::root(); + if ( d.exists ( m_filename ) ) + d.remove ( m_filename ); + + m_progress->setbitrate ( QString::number ( getBitRate ( _title ) ) ); + if ( !m_mpeg2 ) + m_progress->setsize ( m_size +i18n ( "MB" ) +" X " +QString::number ( m_parts ) ); + else + m_progress->setsize ( m_size +i18n ( "MB" ) +" X " ); + + m_process=new k9Process ( this,0 ); + m_process->setUseShell ( true ); + *m_process << "k9copy" << "--play" << "--endsector" << QString::number ( endSector ) ; + *m_process << "--inject" << injectName; //"/tmp/kde-jmp/inject"; + *m_process << "--input" << "'"+m_device+"'"; + *m_process << "--dvdtitle" << QString::number ( _title->getnumTitle() ); + + if ( m_mpegChapters && m_mpeg2 ) + { + *m_process << "--chapter" << ichapterCells.key();//chapters.at(m_part-1); + //*m_process << "--cell" << QString::number(ichapterCells.value()); + } + else + *m_process << "--chapterlist" << getChapterList ( _title ); + + if ( m_part==1 || m_mpeg2 ) + *m_process << "--initstatus"; + else + *m_process << "--continue"; + + if ( pass==1 ) + *m_process << "--firstpass"; + + for ( int i=0;i<_title->getaudioStreamCount();i++ ) + { + if ( _title->getaudioStream ( i )->getselected() ) + { + *m_process << "--audiofilter" << QString::number ( _title->getaudioStream ( i )->getID() ); + break; + } + } + + if ( getselectedSubp ( _title ) !=-1 ) + { + *m_process << "--subpicturefilter" ; + QString s=""; + for ( int i=1; i<=_title->getsubPictureCount();i++ ) + s+= ( i>1?",":"" ) + QString::number ( i ); + *m_process << s; + } + + if ( m_usecache ) + *m_process << "--usecache"; + + if ( m_mpeg2 ) + { + m_progress->setbitrate ( "--" ); + double size; + + if ( _title->getforceFactor() ) + { + size = _title->getChaptersSize_mb ( true ) /_title->getfactor(); + *m_process << "--vampsfactor" << QString::number ( _title->getfactor() ) << "--ffactor"; + } + else + size = _title->getChaptersSize_mb ( true ); + m_progress->setsize ( QString::number ( size ) +i18n ( "MB" ) ); + QString path=m_filename; + if ( m_parts>1 ) + { + QString ext=m_filename.section ( ".",-1 ); + if ( ext!="" ) + ext="."+ext; + path=m_filename.left ( m_filename.length()-ext.length() ); + //path=QString("%1-chapter%2-cell%3%4").arg(path).arg(ichapterCells.key()).arg(ichapterCells.value()).arg(ext); + path=QString ( "%1-chapter%2%3" ).arg ( path ).arg ( ichapterCells.key() ).arg ( ext ); + ++ichapterCells; + } + *m_process << "> "+path; + } + else + { + *m_process << "| mencoder" << "/dev/stdin"; + *m_process << "-passlogfile" << passLogFile.name(); + + bool audio=false; + QString sPass=""; + QString sCodec=""; + + k9AudioCodecs *audioCodecs=new k9AudioCodecs ( 0,0 ); + k9VideoCodecs *videoCodecs=new k9VideoCodecs ( 0,0 ); + + QString sVOption; + m_pass=pass; + switch ( pass ) + { + case 1: + sVOption=replaceParams ( videoCodecs->getOptions1 ( m_codec ) ); + break; + case 2: + sVOption=replaceParams ( videoCodecs->getOptions2 ( m_codec ) ); + break; + default: + sVOption=replaceParams ( videoCodecs->getOptions0 ( m_codec ) ); + break; + } + sCodec=videoCodecs->getCodecName ( m_codec ); + sVOption=sVOption.simplifyWhiteSpace(); + int pos; + //*m_process << "-ovc" << sVOption; + /* int pos=sVOption.find("-vf"); + if (pos==-1) + *m_process <<"-vf" << QString("scale=%1:%2").arg(m_width).arg(m_height); + else + sVOption=sVOption.insert(pos+4,QString("scale=%1:%2,").arg(m_width).arg(m_height)); + */ + *m_process << sVOption; + + QString sAOption=replaceParams ( audioCodecs->getOptions ( m_audioCodec ) ).simplifyWhiteSpace(); + + + + if ( pass >0 ) + m_progress->setTitleLabel ( i18n ( "Encoding %1" ).arg ( sCodec ) +" - "+i18n ( "pass %1" ).arg ( pass ) ); + else + m_progress->setTitleLabel ( i18n ( "Encoding %1" ).arg ( sCodec ) ); + + if ( m_fourcc !="" ) + *m_process << "-ffourcc" << m_fourcc; + else if ( videoCodecs->getFourcc ( m_codec ) !="" ) + *m_process << "-ffourcc" << videoCodecs->getFourcc ( m_codec ); + + delete audioCodecs; + delete videoCodecs; + + //looking for first audio selected + for ( int i=0;i<_title->getaudioStreamCount();i++ ) + { + if ( _title->getaudioStream ( i )->getselected() ) + { + //*m_process << "-oac" << sAOption; + pos=sAOption.find ( "-af" ); + if ( pos==-1 ) + *m_process << QString ( "-af volume=%1" ).arg ( m_audioGain ); + else + sAOption=sAOption.insert ( pos+4,QString ( "volume=%1," ).arg ( m_audioGain ) ); + *m_process << sAOption; + + audio=true; + break; + } + } + + if ( getselectedSubp ( _title ) !=-1 ) + { + *m_process << "-sid" << QString::number ( getselectedSubp ( _title ) ); + } + if ( !audio ) + *m_process << "-nosound"; + + QString path=m_filename; + + if ( m_parts>1 ) + { + QString ext=m_filename.section ( ".",-1 ); + if ( ext!="" ) + ext="."+ext; + path=m_filename.left ( m_filename.length()-ext.length() ); + path=path+QString::number ( m_part ) +ext; + } + if ( pass==1 ) + *m_process << "-o" << "/dev/null"; + else + *m_process <<"-o" << "'"+path+"'"; + if ( path.upper().endsWith ( "MPEG" ) || path.upper().endsWith ( "MPG" ) ) + *m_process << "-of" << "mpeg"; + else if ( path.upper().endsWith ( "AVI" ) ) + *m_process << "-of" << "avi"; + else + { + *m_process << "-of" << "lavf"; + *m_process << "-lavfopts" << "i_certify_that_my_video_stream_does_not_use_b_frames"; + } + //*m_process << "-of" << "avi"; + + } + QString s=""; + for ( uint i=0; i< m_process->args().count();i++ ) + { + QCString str=* ( m_process->args().at ( i ) ); + s +=QString ( str ) +" "; + } + qDebug ( s ); + time->start(); + m_timer3.start(); + connect ( m_process, SIGNAL ( receivedStdout ( KProcess *, char *, int ) ),this, SLOT ( getStdout ( KProcess *, char *, int ) ) ); + connect ( m_process, SIGNAL ( receivedStderr ( KProcess *, char *, int ) ),this, SLOT ( getStderr ( KProcess *, char *, int ) ) ); + //connect(m_process, SIGNAL(processExited(KProcess*)),this,SLOT(exited(KProcess*))); + connect ( m_progress,SIGNAL ( sigCancel() ),this,SLOT ( slotCancel() ) ); + m_canceled=false; + m_progress->show(); + m_process->start ( KProcess::OwnGroup, KProcess::All ); + timer->start ( 500, 0 ); + m_process->sync(); + //if application is exiting, kill the encoding process + if ( m_process->isRunning() ) + { + m_process->kill(); + return; + } + if ( m_canceled ) + { + KMessageBox::information ( qApp->mainWidget(),i18n ( "MPEG-4 Encoding cancelled" ), i18n ( "MPEG-4 Encoding" ) ); + error=true; + } + else if ( !m_process->normalExit() ) + { + KMessageBox::error ( qApp->mainWidget(),"<b>"+i18n ( "Error while running mencoder :" ) +"</b><br>"+m_stderr, i18n ( "Encoding error" ) ); + error=true; + } + if ( maxPass >0 ) + pass++; + } + while ( pass<=maxPass && !error && m_2pass ); + + } +} + + +void k9MP4Enc::slotCancel() +{ + m_canceled=true; + m_process->kill(); +} + + +QString k9MP4Enc::replaceParams ( QString _value ) +{ + QString str=_value; + str.replace ( "$PASS",QString::number ( m_pass ) ); + str.replace ( "$WIDTH",m_width ); + str.replace ( "$HEIGHT",m_height ); + str.replace ( "$VIDBR",QString::number ( getBitRate ( m_title ) ) ); + str.replace ( "$AUDBR",m_audioBitrate ); + return str; +} + + +int k9MP4Enc::getBitRate ( k9DVDTitle *_title ) +{ + // bitrate video = (MB *8388.608) /SEC - bitrate audio + + if ( m_videoBitrate!="" ) + { + return m_videoBitrate.toInt(); + } + else + { + int size=m_size.toInt(); + float titleSize=_title->getChaptersSize_mb ( true ); + if ( titleSize< ( float ) size ) + size= ( int ) ( titleSize/m_parts ) ; + m_progress->setsize ( QString::number ( size ) +i18n ( "MB" ) +" X " +QString::number ( m_parts ) ); + QTime t1 ( 0,0 ); + int sec=t1.secsTo ( _title->getSelectedLength() ); + //int bitrate=(int)( ((size*m_parts) * 8388.608)/sec - m_audioBitrate.toInt()); + int bitrate=8* ( ( ( size*m_parts*1024 )- ( m_audioBitrate.toInt() *sec/8 ) ) /sec ); + + return bitrate; + } +} + + +void k9MP4Enc::getStdout ( KProcess *, char *buffer, int buflen ) +{ + QCString tmp ( buffer,buflen ); + m_cpt++; + if ( m_cpt==100 ) + m_cpt=0; + + if ( m_cpt!=0 ) + return; + + int pos=tmp.find ( "Pos:" ); + if ( pos!=-1 ) + { + QString tmp2=tmp.mid ( pos ); + float t; + int frame; + int fps; + sscanf ( tmp2.latin1(),"Pos: %f%*s%d",&t,&frame ); + tmp2=tmp2.mid ( tmp2.find ( "(" ) +1 ); + tmp2=tmp2.mid ( tmp2.find ( ")" ) +1 ); + sscanf ( tmp2.latin1(),"%d",&fps ); + + m_progress->setfps ( QString::number ( fps ) ); + } + + +} + +void k9MP4Enc::getStderr ( KProcess *proc, char *buffer, int buflen ) +{ + //m_stderr=QString::fromLatin1(buffer,buflen); + QCString cstderr ( buffer,buflen+1 ); + + if ( cstderr.find ( "FATAL:" ) !=-1 ) + { + proc->kill(); + } + + int pos=cstderr.find ( "INFOPOS:" ); + if ( pos!=-1 ) + { + if ( m_timer3.elapsed() >500 ) + { + m_timer3.restart(); + QString tmp=cstderr.mid ( pos ); + uint32_t totalBytes,totalSize; + sscanf ( tmp.latin1(),"INFOPOS: %d %d",&totalBytes,&totalSize ); + if ( totalSize !=0 ) + m_percent= ( float ) totalBytes / ( float ) m_totalSize; + + + QTime time2 ( 0,0 ); + time2=time2.addMSecs ( time->elapsed() ); + if ( m_percent>0 ) + { + QTime time3 ( 0,0 ); + time3=time3.addMSecs ( ( uint32_t ) ( time->elapsed() * ( 1/m_percent ) ) ); + m_remain=time3.toString ( "hh:mm:ss" ); + } + + m_percent*=100; + m_progress->setProgress ( ( int ) m_percent ); + m_progress->setremain ( time2.toString ( "hh:mm:ss" ) +" / " +m_remain ); + } + } + else + { + pos=cstderr.find ( "INFOIMAGE:" ); + if ( pos!=-1 ) + { + m_progress->setImage ( cstderr.mid ( pos+10 ) ); + } + else + qDebug ( "[%s]",buffer ); + } + m_stderr=cstderr; +} + +void k9MP4Enc::timerDone() +{ + QTime time2 ( 0,0 ); + time2=time2.addMSecs ( time->elapsed() ); + m_progress->setremain ( time2.toString ( "hh:mm:ss" ) +" / " +m_remain ); + +} + +bool k9MP4Enc::isCanceled() +{ + return m_canceled; +} + + +k9MP4Enc::~k9MP4Enc() {} + + +#include "k9mp4enc.moc" |