Logo Search packages:      
Sourcecode: k9copy version File versions  Download package

k9dvdbackup.cpp

/***************************************************************************
*   Copyright (C) 2005 by Jean-Michel Petit                               *
*   jm_petit@laposte.net                                                  *
*                                                                         *
*   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.                                   *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
*                                                                         *
*   You should have received a copy of the GNU General Public License     *
*   along with this program; if not, write to the                         *
*   Free Software Foundation, Inc.,                                       *
*   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
***************************************************************************/
#include "k9dvdbackup.h"
#include <dvdread/dvd_reader.h>
#include <dvdread/ifo_read.h>
#include <dvdread/ifo_print.h>
#include <dvdread/nav_read.h>
#include <kmessagebox.h>
#include <kapplication.h>
#include <qapplication.h>
#include <qfileinfo.h>
#include "k9backupdlg.h"
#include "k9dvd.h"
#include "bswap.h"
#include "k9ifo.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <klocale.h>
#include <qdir.h>
#include <kstandarddirs.h>
#include <qptrlist.h>

#define BUF_SECS  1024

#ifndef DVD_BLOCK_LEN
#define DVD_BLOCK_LEN 2048
#endif

#include "k9dvdbackup.moc"

int k9TitleSetList::compareItems ( QPtrCollection::Item item1, QPtrCollection::Item item2 ) {
    k9TitleSet * it1,*it2;
    it1=(k9TitleSet *) item1;
    it2=(k9TitleSet *)item2;
    return it1->VTS - it2->VTS;
}


k9TitleSet::k9TitleSet(int _VTS):QObject(NULL,"") {
    startSector=0;
    lastSector=0;
    VTS=_VTS;
    cells.setAutoDelete(true);
    ifoTitle=NULL;
}

k9TitleSet::~k9TitleSet() {
    ifoClose(ifoTitle);
}

k9Cell* k9TitleSet::addCell(int _vts,int _pgc, int _vob) {
    return cells.addCell(_vts,_pgc,_vob);

}

uint32_t k9TitleSet::getSize() {
    return (lastSector +1) ;
}


k9DVDBackup::k9DVDBackup(QObject* _dvd,const char* name,const QStringList& args)
        : QObject(NULL, "") {
    DVD = (k9DVD*)_dvd;
    currVTS=0;
    outputFile=NULL;
    currTS=NULL;
    errMsg="";
    error=false;
    backupDlg = new k9BackupDlg(qApp->mainWidget(),"",true);
    //  cells.setAutoDelete(true);
}


k9DVDBackup::~k9DVDBackup() {
    if (outputFile !=NULL) {
        outputFile->close();
        delete outputFile;
    }
    delete backupDlg;

}

bool k9DVDBackup::geterror() {
    return error;
}

void k9DVDBackup::seterror(const QString &_msg) {
    error=true;
    errMsg=_msg;
}

QString k9DVDBackup::getErrMsg() {
    return(errMsg);
}

void k9DVDBackup::prepareVTS(int _VTS) {
    if (error)
        return;
    ifo_handle_t *hifo;

    cellSize=0;
    uint32_t menuSize = 0;
    if (currTS==NULL)
        copyMenu(0);
    if (backupDlg->getAbort()) {
        seterror(tr2i18n("DVD backup cancelled"));
        return;
    }
    //creation of output file
    if (currVTS != _VTS) {
        if (outputFile != NULL) {
            outputFile->close();
            delete outputFile;
            updateIfo();
            updateVob();
        }
        menuSize =copyMenu(_VTS);

        if (backupDlg->getAbort()) {
            seterror(tr2i18n("DVD backup cancelled"));
            return;
        }

        QString filename;
        filename.sprintf("%s/VTS_%02d_1.VOB",output.latin1(),_VTS);
        outputFile=new QFile(filename);
        if (! outputFile->open(IO_WriteOnly)) {
            seterror(tr2i18n("Unable to open file ") + filename);
            return;
        }
        currVOB=1;

        uint32_t startSector=0;

        if (currTS != NULL) {
            startSector = currTS->startSector + currTS->getSize();
        } else {
            hifo = ifoOpen (m_dvdhandle, 0);
            if (!hifo) {
                seterror( tr2i18n("unable to open VIDEO_TS.IFO"));
                return;
            }
            startSector= hifo->vmgi_mat->vmg_last_sector+1  ;
            ifoClose(hifo);

        }
        currTS = new k9TitleSet(_VTS);
        currTS->startSector=startSector;
        currTS->lastSector += menuSize ;
        titleSets.append(currTS);
        currTS->ifoTitle=ifoOpen(m_dvdhandle,_VTS);
        //JMP :  à vérifier
        m_position=0;
    }

    currVTS=_VTS;

}

KProcess * k9DVDBackup::createVampsProcess() {
    KProcess *process = new KProcess();
    process->setUseShell(TRUE);

    connect( process, SIGNAL(receivedStdout (KProcess *, char *, int )),
             this, SLOT(receivedStdout (KProcess *, char *, int )) );
    connect( process, SIGNAL(receivedStderr (KProcess *, char *, int )),
             this, SLOT(receivedStderr (KProcess *, char *, int )) );
    connect( process, SIGNAL(wroteStdin (KProcess * )),
             this, SLOT(wroteStdin (KProcess * )) );
    *process << "vamps" << "-p " << " -i " << inject << " -S " << argSize ;
    if (argAudio !="")
        *process << "-a" <<argAudio;
    if (argSubp !="" )
        *process << "-s" <<argSubp;
    *process << "-E" << argFactor; //   "1.50";
    return process;
}

void k9DVDBackup::copyCell(int _VTS, int _pgc,int _cell,bool _empty) {
    if (error)
        return;
    prepareVTS(_VTS);

    k9Cell *cell= currTS->addCell(_VTS,_pgc,0);
    cell->startSector=m_position;
    currCell=cell;
    //start cell copy
    tempSize=0;
    //JMP position=currCell->startSector;
    if (!_empty) {
        KProcess *process =createVampsProcess();
        wrote=false;
        if (! process->start(KProcess::NotifyOnExit,KProcess::All)) {
            seterror(tr2i18n("Unable to start vamps"));
            delete process;
            return;
        }

        playCell(process,_VTS,_pgc,_cell);
        while (process->isRunning()) {
            qApp->processEvents();
        }
//    process->wait(-1);
        if(process->normalExit() && process->exitStatus()!=0) {
            seterror("vamps : " +vampsMsg);
            delete process;
            return;
        }

        delete process;
    } else
        copyEmptyPgc(_VTS,_pgc,_cell);
}

void k9DVDBackup::copyEmptyPgc(int _vts,int _pgc,int _cell) {
    if (error)
        return;

    pgc_t * pgc;
    ifo_handle_t *vts_handle=currTS->ifoTitle;

    dvd_file_t *dvd_file;
    if ((dvd_file = DVDOpenFile(m_dvdhandle, _vts, DVD_READ_TITLE_VOBS))== 0) {
        QString stmp;
        stmp.sprintf (tr2i18n("Unable to open titleset %d"),_vts);
        seterror(stmp);
        return ;
    }
    /* load information for the given VTS */
    /*      vts_handle = ifoOpen (dvd_handle, _vts);
    if (!vts_handle) {
    errMsg.sprintf(tr2i18n("Unable to open ifo file for titleset %d"),_vts);
    DVDClose(dvd_handle);
    }
    */
    backupDlg->setTotalSteps(vts_handle->vtsi_mat->vts_last_sector-vts_handle->vtsi_mat->vtstt_vobs  -1);
    QString c;
    c.sprintf(tr2i18n("Extracting titleset %d"),_vts);
    backupDlg->setProgressLabel(c);
    backupDlg->show();

    pgc = vts_handle->vts_pgcit->pgci_srp [_pgc - 1].pgc;

    uint32_t sector,dsi_next_vobu = 0,len=0;
    uchar buffer[DVD_VIDEO_LB_LEN];
    currCell->oldStartSector=pgc -> cell_playback[_cell - 1].first_sector;
    sector = pgc -> cell_playback[_cell-1].first_sector;
    backupDlg->setProgress(sector);
    dsi_t    dsi_pack;
    uint32_t       nsectors;

    DVDReadBlocks (dvd_file,sector, 1, buffer);


    currCell->oldLastSector=pgc -> cell_playback[_cell - 1].last_sector;
    k9Vobu * vobu=currCell->addVobu(sector);
    vobu->empty=true;
    currCell->addNewVobus((char*)buffer,DVD_VIDEO_LB_LEN,m_position,currVOB,outputFile->at());
    outputFile->writeBlock((char*)buffer,DVD_VIDEO_LB_LEN);

    /* parse contained DSI pack */
    navRead_DSI (&dsi_pack, buffer + DSI_START_BYTE);
    currCell->vob = dsi_pack.dsi_gi.vobu_vob_idn;
    //vobu->size=1;

    if (dsi_pack.dsi_gi.vobu_ea != 0) {
        nsectors      = 1; //dsi_pack.dsi_gi.vobu_ea;
        dsi_next_vobu = dsi_pack.vobu_sri.next_vobu;

        uchar *buf=(uchar*) malloc(nsectors*DVD_VIDEO_LB_LEN);

        /* read VOBU */
        len = DVDReadBlocks (dvd_file, (uint32_t) (sector + 1), nsectors, buf) +len ;
        outputFile->writeBlock((char*)buf,nsectors * DVD_VIDEO_LB_LEN);
        free(buf);
    } else {
        nsectors = 0;
    }
    vobu->size +=nsectors;
    currCell->lastSector=currCell->startSector+ len;  //JMP *DVD_VIDEO_LB_LEN;
    // position+=DVD_VIDEO_LB_LEN + len*DVD_VIDEO_LB_LEN;
    m_position+=1 + len;
    currTS->lastSector+=len+1;

    DVDCloseFile(dvd_file);
    backupDlg->setProgressTotal(len+1);
}


void k9DVDBackup::receivedStderr(KProcess * proc, char * buffer, int buflen) {
    QString dbg(buffer);
    vampsMsg=dbg;
}
/*!
\fn k9DVDBackup::receivedStdout ( KProcess * proc, char * buffer, int buflen)
*/
void k9DVDBackup::receivedStdout (KProcess * proc, char * buffer, int buflen) {
    if (error)
        return;

    memcpy(temp + tempSize ,buffer,buflen);
    tempSize+=buflen;
    QString sName;

    long fileSize=outputFile->size();

    if (tempSize>=DVD_VIDEO_LB_LEN) {
        if (k9Cell::isNavPack(temp)) {
            if (vobuList.count()>0) {
                k9Vobu *vobu=vobuList.at(0);
                vobuList.remove(vobu);
                cellOut=vobu->parent;
            } else
                cellOut=currCell;
            dsi_t dsiPack;
            navRead_DSI (&dsiPack, (uchar*)temp + DSI_START_BYTE);
            cellOut->vob = dsiPack.dsi_gi.vobu_vob_idn;
            if ((dsiPack.dsi_gi.vobu_ea * DVD_VIDEO_LB_LEN) + fileSize >= (1024*1024*1024)) {
                outputFile->close();
                delete outputFile;
                currVOB++;
                sName.sprintf("%s/VTS_%02d_%d.VOB",output.latin1(),currVTS,currVOB);
                outputFile=new QFile(sName);
                if ( !outputFile->open(IO_WriteOnly)) {
                    seterror(tr2i18n("Unable to open file ") + sName);
                    return;
                }
            }
        }

        cellOut->addNewVobus((char*)temp,DVD_VIDEO_LB_LEN,m_position,currVOB,outputFile->at());
        outputFile->writeBlock((char*)temp,DVD_VIDEO_LB_LEN);
      backupDlg->setProgressTotal(1);
        tempSize-=DVD_VIDEO_LB_LEN;
        memcpy(temp,temp+DVD_VIDEO_LB_LEN,tempSize);
        m_position++;
        currTS->lastSector++;
    }


}

void k9DVDBackup::wroteStdin (KProcess * proc) {
    wrote=true;
}




void k9DVDBackup::copyAngleBlock(k9CellCopyList *_list,uint _num) {
    uint num=_num;
    k9Cell * cell =(k9Cell*)_list->at(_num);
    QPtrList <k9Cell> cells;

    prepareVTS(cell->vts);

    ifo_handle_t *vts_handle;
    dvd_file_t *  file_handle;

    vts_handle=currTS->ifoTitle;
    if (!vts_handle) {
        QString stmp;
        stmp.sprintf(tr2i18n("Unable to open ifo file for titleset %d"),cell->vts);
        seterror (stmp);
        return;
    }
    file_handle = DVDOpenFile (m_dvdhandle, cell->vts, DVD_READ_TITLE_VOBS);
    if (! file_handle) {
        QString stmp;
        stmp.sprintf(tr2i18n("Unable to open vobs for titleset %d"),cell->vts);
        seterror( stmp);
        return;
    }

    uchar angleBlock=angleStart;
    while (angleBlock !=angleNone) {
        cell =(k9Cell*)_list->at(num);
        angleBlock=cell->angleBlock;
        if (angleBlock !=angleNone) {
            cell->copied=true;
            k9Cell *newCell= currTS->addCell(cell->vts,cell->pgc,0);
            cells.append(newCell);
            tempSize=0;
            pgc_t *     pgc;
            uint32_t    sector, dsi_next_vobu = 0;

            pgc = vts_handle -> vts_pgcit -> pgci_srp [cell->pgc - 1].pgc;
            uchar *buf;
            k9Vobu * currVobu;
            //making the vobu List;
            for (sector = pgc -> cell_playback [cell->id  - 1].first_sector;
                    dsi_next_vobu != SRI_END_OF_CELL; sector += dsi_next_vobu & 0x7fffffff) {
                dsi_t   dsi_pack;

                /* read nav pack */
                buf=(uchar*) malloc(DVD_VIDEO_LB_LEN);
                DVDReadBlocks (file_handle,  sector, 1, buf);

                if (k9Cell::isNavPack(buf)) {
                    currVobu =newCell->addVobu(sector);
                    vobuList.append(currVobu);

                    navRead_DSI (&dsi_pack, buf + DSI_START_BYTE);
                    ;
                    dsi_next_vobu = dsi_pack.vobu_sri.next_vobu;
                }

                free(buf);
            }
        }
        num++;
    }
    //sort the list to create an interleaved vobu list
    vobuList.sort();
    //start copy of angle block

    while (vobuList.count() >0) {
        uint iVobu=0;
        wrote=false;

        k9Vobu *vobu=vobuList.at(iVobu);
        currCell=vobu->parent;
      
      if (vobuList.count()>1) {
         double dsize;
         k9Vobu *vobu2=vobuList.at(1);
         dsize=vobu2->oldSector-vobu->oldSector;
           dsize*=DVD_BLOCK_LEN;
           argSize.sprintf("%.0f",dsize);
      }

      KProcess * process =createVampsProcess();
        if (! process->start(KProcess::NotifyOnExit,KProcess::All)) {
            seterror(tr2i18n("Unable to start vamps"));
            delete process;
            return;
        }

        copyVobu(process,file_handle,vobu->oldSector,vobu);

        process->closeStdin();
        while (process->isRunning()) {
            qApp->processEvents();
        }
//    process->wait(-1);
        if(process->normalExit() && process->exitStatus()!=0) {
            seterror("vamps : " +vampsMsg);
            delete process;
            return;
        }
      delete process;
    }

    DVDCloseFile(file_handle);

    num=_num;
    for (uint iCell=0;iCell<cells.count();iCell++) {
        k9Cell * cell=cells.at(iCell);
        k9Vobu *vobu=cell->vobus.at(0);
        cell->startSector=vobu->newSector;
        cell->oldStartSector=vobu->oldSector;
        k9Cell *c=(k9Cell*)_list->at(num);
        c->newSize=cell->getnewSize();
        num++;
    }
    vobuList.clear();

}



/*!
\fn k9DVDBackup::setDevice(QString _device)
*/
void k9DVDBackup::setDevice(QString _device) {
    device=_device;
}


/*!
\fn k9DVDBackup::setOutput(QString _output)
*/
void k9DVDBackup::setOutput(QString _output) {
    output=QDir::cleanDirPath(_output);
}

uint32_t k9DVDBackup::copyMenu(int _vts) {
    if (error)
        return 0;

    QFile *menuFile;
    QString targetName;
    if (_vts == 0) {
        targetName="VIDEO_TS.VOB";
    } else {
        targetName.sprintf("VTS_%02i_0.VOB",_vts);
    }

    uint32_t size;
    QString c;
    c="/VIDEO_TS/" + targetName;
    //gets the menu vob size
    ifo_handle_t *hifo = ifoOpen (m_dvdhandle, _vts);
    if (_vts==0)
        size=hifo->vmgi_mat->vmg_last_sector -1  - 2* hifo->vmgi_mat->vmgi_last_sector;
    else
        size=hifo->vtsi_mat->vtstt_vobs - hifo->vtsi_mat->vtsi_last_sector -1;
    ifoClose(hifo) ;

    size*=DVD_BLOCK_LEN;

    if (size ==0)
        return 0;

    menuFile=new QFile( output +"/"+targetName);
    if( !menuFile->open(IO_WriteOnly)) {
        seterror(tr2i18n("Unable to open ") +output +"/"+targetName);
        return 0;
    }

    dvd_file_t *dvd_file;
    if ((dvd_file = DVDOpenFile(m_dvdhandle, _vts, DVD_READ_MENU_VOBS))== 0) {
        QString stmp;
        stmp.sprintf(tr2i18n("Unable to open menu for titleset %d"),_vts);
        seterror (stmp);
        return 0;
    }


    size=size/DVD_VIDEO_LB_LEN;
    c.sprintf(tr2i18n("Extracting menu for titleset %d"),_vts);
    backupDlg->setProgressLabel(c);

    backupDlg->show();
    backupDlg->setTotalSteps(size);
    uchar buffer[DVD_VIDEO_LB_LEN];
    for (uint32_t sector=0 ;sector < size ;sector++) {
        backupDlg->setProgress(sector);
        if (backupDlg->getAbort())
            break;
        int len;
        len = DVDReadBlocks (dvd_file,sector, 1, buffer);
        menuFile->writeBlock((char*)buffer,DVD_VIDEO_LB_LEN);
        backupDlg->setProgressTotal(1);
    }

    DVDCloseFile(dvd_file);
    menuFile->close();
    delete menuFile;

    return size;

}



void k9DVDBackup::playCell (KProcess * _process, int vts_num, int pgc_num, int cell) {

    if (error)
        return;

    pgc_t * pgc;
    ifo_handle_t *vts_handle;
    dvd_file_t *  file_handle;
    uint32_t      sector, dsi_next_vobu = 0;
    /* open disc */
    if (m_dvdhandle) {
        /* load information for the given VTS */
        // vts_handle = ifoOpen (dvd_handle, vts_num);
        vts_handle=currTS->ifoTitle;
        if (!vts_handle) {
            QString stmp;
            stmp.sprintf(tr2i18n("Unable to open ifo file for titleset %d"),vts_num);
            seterror (stmp);
            _process->closeStdin();
            return;
        }

        backupDlg->setTotalSteps( vts_handle->vtsi_mat->vts_last_sector-vts_handle->vtsi_mat->vtstt_vobs  -1);
        QString c;
        c.sprintf(tr2i18n("Extracting titleset %d"),vts_num);
        backupDlg->setProgressLabel(c);
        backupDlg->show();
    } else {
        seterror(tr2i18n("Unable to open DVD"));
        _process->closeStdin();
        return;
    }


    /* open VTS data */
    file_handle = DVDOpenFile (m_dvdhandle, vts_num, DVD_READ_TITLE_VOBS);
    if (! file_handle) {
        QString stmp;
        stmp.sprintf(tr2i18n("Unable to open vobs for titleset %d"),vts_num);
        seterror( stmp);
        _process->closeStdin();
        return;
    }

    pgc = vts_handle -> vts_pgcit -> pgci_srp [pgc_num - 1].pgc;

    /* loop until out of the cell */
    currCell->oldStartSector=pgc -> cell_playback [cell - 1].first_sector;
    for (sector = pgc -> cell_playback [cell - 1].first_sector;
            dsi_next_vobu != SRI_END_OF_CELL; sector += dsi_next_vobu & 0x7fffffff) {

        backupDlg->setProgress(sector);
        if (backupDlg->getAbort()) {
            seterror(tr2i18n("DVD backup cancelled"));
        }

        if (error)
            break;
        dsi_next_vobu= copyVobu(_process,file_handle,sector,NULL);
    }
    _process->closeStdin();
    DVDCloseFile(file_handle);
}

uint32_t k9DVDBackup::copyVobu( KProcess *_process,dvd_file_t  *_fileHandle,uint32_t _startSector,k9Vobu * _vobu) {
    dsi_t   dsi_pack;
    k9Vobu * currVobu;

    uint32_t      nsectors, len;
    uchar *buf;
    uint32_t sector=_startSector;
    /* read nav pack */
    buf=(uchar*) malloc(DVD_VIDEO_LB_LEN);
    len = DVDReadBlocks (_fileHandle,  sector, 1, buf);
    currVobu=_vobu;

    if (k9Cell::isNavPack(buf)) {
        currCell->oldLastSector=sector;
        if (currVobu==NULL)
            currVobu =currCell->addVobu(sector);
    }

    /* generate an MPEG2 program stream (including nav packs) */
    wrote=false;
    if (_process->writeStdin((char*)buf,DVD_VIDEO_LB_LEN)) {
        while (!wrote && _process->isRunning()) {
            qApp->processEvents();
        }
    }

    /* parse contained DSI pack */
    navRead_DSI (&dsi_pack, buf + DSI_START_BYTE);

    nsectors      = dsi_pack.dsi_gi.vobu_ea;
    uint32_t dsi_next_vobu = dsi_pack.vobu_sri.next_vobu;
    //free(buf);
    buf=(uchar*) realloc(buf,nsectors*DVD_VIDEO_LB_LEN);

    /* read VOBU */
    len = DVDReadBlocks (_fileHandle, (sector + 1), nsectors, buf);

    /* write VOBU */
    for (uint32_t i=0;i<nsectors ;i++) {
        wrote=false;
        if (_process->writeStdin((char*)buf + (i*DVD_VIDEO_LB_LEN), DVD_VIDEO_LB_LEN)) {
            while (!wrote && _process->isRunning()) {
                qApp->processEvents();
            }
        }
    }
    free(buf);
    return dsi_next_vobu;
}



k9Vobu * k9DVDBackup::remapVobu(uint32_t *value) {
    k9Vobu *vobu=NULL;
    uint32_t sector,mask;
    if ( (*value & 0x80000000) == 0x80000000) {
        sector = *value & 0x7FFFFFFF;
        mask=0x80000000;
    } else {
        sector =*value;
        mask=0;
    }
    *value=0;
    for (int i=0;i <currTS->cells.count();i++) {
        k9Cell * cell = (k9Cell*)currTS->cells.at(i);
        vobu = cell->findVobu(sector);
        if (vobu !=NULL) {
            *value = vobu->newSector | mask;
            return vobu;
        }
    }
    *value=0;
    return vobu;

}


k9Vobu * k9DVDBackup::remapOffset(uint32_t _sector,uint32_t *_offset,int _dir) {
    k9Vobu *vobu1=NULL, *vobu2=NULL;
    uint32_t offset,sector;
    uint32_t maskOffset1=0,maskOffset2=0,maskSector=0;

    if ((*_offset!= 0xbfffffff) && (*_offset!=0x3fffffff) && (*_offset!=0x7fffffff)) {

        if ( (*_offset & 0x80000000) == 0x80000000)
            maskOffset1= 0x80000000;
        if ( (*_offset & 0x40000000) == 0x40000000)
            maskOffset2= 0x40000000;
        offset = *_offset & 0x3FFFFFFF;

        if ( (_sector & 0x80000000) == 0x80000000) {
            sector = _sector & 0x7FFFFFFF;
            maskSector=0x80000000;
        } else {
            sector =_sector;
            maskSector=0;
        }

        for (uint32_t i=0;(i <currTS->cells.count()) && (vobu1==NULL) ;i++) {
            k9Cell * cell = (k9Cell*)currTS->cells.at(i);
            vobu1 = cell->findVobu(sector);
        }

        for (uint32_t i=0;i <currTS->cells.count() && (vobu2==NULL);i++) {
            k9Cell * cell = (k9Cell*)currTS->cells.at(i);
            vobu2 = cell->findVobu(sector+_dir*offset);
        }

        if ((vobu1 !=NULL) && (vobu2!=NULL)) {
            *_offset = abs(vobu1->newSector - vobu2->newSector)  | maskOffset1 ;
            *_offset |= maskOffset2;
            return vobu2;
        }

        if (vobu1==NULL && vobu2==NULL)
            qDebug ("remapOffset : sector not found");
    }
    return vobu2;
}


void k9DVDBackup::updateMainIfo() {

    if (error)
        return;

    k9Ifo ifo;
    ifo.setOutput(output);
    ifo.setDevice(device);

    ifo.openIFO(0);
    ifo_handle_t *hifo =ifo.getIFO();

    //mise à jour des startSectors
    k9TitleSet *TSp=NULL;
    titleSets.sort();
    for (uint iTS=0;iTS < titleSets.count();iTS++) {
        k9TitleSet *TS=titleSets.at(iTS);
        uint32_t startSector;
        if (TSp!=NULL)
            startSector = TSp->startSector + TSp->getSize();
        else
            startSector= hifo->vmgi_mat->vmg_last_sector+1  ;
        TS->startSector=startSector;
        TSp=TS;
    }

    hifo->vmgi_mat->vmg_category=0;
    bool found=false;
    for (uint32_t i=0 ; i< hifo->tt_srpt->nr_of_srpts;i++) {
        for (uint iTS=0;iTS<titleSets.count() &&(!found);iTS++) {
            k9TitleSet *TS=titleSets.at(iTS);
            if (TS->VTS == hifo->tt_srpt->title[i].title_set_nr ) {
                hifo->tt_srpt->title[i].title_set_sector = TS->startSector;
                found=true;
            }
        }
        found=false;
    }

    ifo.saveIFO();
    ifo.closeIFO();

}

void k9DVDBackup::updateIfo() {

    if (error)
        return;

    k9Ifo ifo;
    ifo.setOutput(output);
    ifo.setDevice(device);

    ifo.openIFO(currVTS);

    ifo_handle_t *hifo =ifo.getIFO();

    pgcit_t * pgcit = hifo->vts_pgcit;

    //update total VTS size with IFO size
    currTS->lastSector += 2 *(hifo->vtsi_mat->vtsi_last_sector ) +1;

    hifo->vtsi_mat->vts_last_sector =   currTS->lastSector ;

    k9Vobu* vobu2=NULL;
    uint32_t newPos=0;
    //update first play PGC
    if (hifo->first_play_pgc !=NULL ) {
        pgc_t *pgc=hifo->first_play_pgc;
        cell_playback_t *cell_playback =pgc->cell_playback;
        int nr= pgc->nr_of_cells;

        vobu2=NULL;
        cell_playback_t cell;
        newPos=0;
        for( int j = 0; j < nr; j++) {
            k9Vobu *vobu=remapVobu(&cell_playback[j].first_sector);
            vobu2=vobu;

            remapVobu(&cell_playback[j].first_ilvu_end_sector);
            if (vobu !=NULL) {
                vobu=remapVobu(&cell_playback[j].last_vobu_start_sector);
                if (vobu==NULL) {
                    cell_playback[j].last_vobu_start_sector=cell_playback[j].first_sector;
                    vobu=vobu2;
                    pgc->playback_time.hour=0;
                    pgc->playback_time.minute=0;
                    pgc->playback_time.second=0;

                    cell_playback[j].playback_time.hour=0;
                    cell_playback[j].playback_time.minute=0;
                    cell_playback[j].playback_time.second=0;
                }
                cell_playback[j].last_sector = vobu->newSector+vobu->size;// -1 ;
                cell_playback[newPos]=cell_playback[j];
                cell=cell_playback[newPos];
                newPos++;
            } else {
                cell_playback[newPos]=cell;
                newPos++;
            }
        }
        for (uint32_t j=newPos;j<nr;j++)
            cell_playback[j].last_sector=0;
        pgc->nr_of_cells=newPos;
    }

    newPos=0;
    //update each PGC


    for(uint32_t i = 0; i < pgcit->nr_of_pgci_srp; i++) {
        pgc_t *pgc=pgcit->pgci_srp[i].pgc;
        cell_playback_t *cell_playback =pgc->cell_playback;
        int nr= pgc->nr_of_cells;

        vobu2=NULL;
        cell_playback_t cell;
        newPos=0;
        for( int j = 0; j < nr; j++) {
            k9Vobu *vobu=remapVobu(&cell_playback[j].first_sector);
            vobu2=vobu;

            if (cell_playback[j].first_ilvu_end_sector !=0) {
                uint32_t tmp=cell_playback[j].first_ilvu_end_sector+1;
                remapVobu(&tmp);
                if (tmp!=0)
                    cell_playback[j].first_ilvu_end_sector=tmp-1;
            }
            if (vobu !=NULL) {
                vobu=remapVobu(&cell_playback[j].last_vobu_start_sector);
                if (vobu==NULL) {
                    cell_playback[j].last_vobu_start_sector=cell_playback[j].first_sector;
                    vobu=vobu2;
                    pgc->playback_time.hour=0;
                    pgc->playback_time.minute=0;
                    pgc->playback_time.second=0;

                    cell_playback[j].playback_time.hour=0;
                    cell_playback[j].playback_time.minute=0;
                    cell_playback[j].playback_time.second=0;

                }
                cell_playback[j].last_sector = vobu->newSector+vobu->size;// -1 ;
                cell_playback[newPos]=cell_playback[j];
                cell=cell_playback[newPos];
                newPos++;
            } else {
                cell_playback[newPos]=cell;
                newPos++;
            }
        }
        for (uint32_t j=newPos;j<nr;j++)
            cell_playback[j].last_sector=0;
        pgc->nr_of_cells=newPos;
    }

    c_adt_t *c_adt = hifo->vts_c_adt;
    uint32_t length = c_adt->last_byte + 1 - C_ADT_SIZE;
    cell_adr_t *ptr;
    ptr= c_adt->cell_adr_table;
    newPos=0;
    for(uint32_t i = 0; i < length/sizeof(cell_adr_t); i++) {
        uint32_t startSect=ptr[i].start_sector;
        // last sector of a vobu = start sector of next vobu -1
        uint32_t lastSect= ptr[i].last_sector +1;
        k9Vobu *vobu=remapVobu(&startSect);
        if (vobu == NULL)
            qDebug ("Error : could not find startSector");
        if (remapVobu(&lastSect)==NULL)
            //          lastSect=currTS->lastSector;
            vobu->parent->lastSector;
        else
            lastSect--;
        ptr[i].start_sector = startSect;
        ptr[i].last_sector = lastSect;

        /*        for (uint32_t j=0;j<currTS->cells.count();j++) {
        k9Cell * cell=(k9Cell*)currTS->cells.at(j);
        if (cell->oldStartSector==startSect) {
        ptr[newPos].start_sector = cell->startSector  ;
        ptr[newPos].last_sector = cell->lastSector; 
        newPos++;
        }
        }
        */
    }

    //   c_adt->last_byte=C_ADT_SIZE -1 +  ((newPos)*sizeof(cell_adr_t));


    vobu_admap_t * vobu_admap = hifo->vts_vobu_admap;
    length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE;
    newPos=0;
    for(uint32_t i = 0; i < length/sizeof(uint32_t); i++) {
        if (remapVobu(&vobu_admap->vobu_start_sectors[i])!= NULL) {
            vobu_admap->vobu_start_sectors[newPos]=vobu_admap->vobu_start_sectors[i];
            newPos++;
        }
    }
    for (uint32_t i=newPos ; i < length/sizeof(uint32_t);i++)
        vobu_admap->vobu_start_sectors[i]=0;

    vobu_admap->last_byte = newPos * sizeof(uint32_t) -1 +VOBU_ADMAP_SIZE;
    //update VTS_TMAP
    vts_tmapt_t *vts_tmapt=hifo->vts_tmapt;
    if (vts_tmapt) {
        for(uint32_t i = 0; i < vts_tmapt->nr_of_tmaps; i++) {
            if(vts_tmapt->tmap[i].nr_of_entries == 0) { // Early out if zero entries
                continue;
            }
            map_ent_t * map_ent=vts_tmapt->tmap[i].map_ent;
            newPos=0;
            for(uint32_t j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) {
                //bit 31 indicates whether  VOBU time codes are discontinous with previous
                uint32_t mask=map_ent[j] & 0x80000000 ;
                uint32_t value=map_ent[j] & 0x7FFFFFFF;
                if (remapVobu(&value) !=NULL) {
                    map_ent[j]=value | mask;
                    map_ent[newPos]=map_ent[j];
                    newPos++;
                } else
                    map_ent[j]=0;
            }
            for (int j = newPos; j < vts_tmapt->tmap[i].nr_of_entries;j++)
                map_ent[j]=0;
            vts_tmapt->tmap[i].nr_of_entries=newPos;
        }
    }
    ifo.saveIFO();
}

void k9DVDBackup::updateVob() {
    int nbVobuUpdated=0;

    uchar buffer[DVD_VIDEO_LB_LEN];
    FILE *file=NULL;
    QString dbg;
    int pVobNum=0;
    for (uint iCell=0;iCell<currTS->cells.count();iCell++) {
        k9Cell *cell=currTS->cells.at(iCell);
        for (uint ivobu=0; ivobu<cell->vobus.count();ivobu++) {
            k9Vobu * vobu = cell->vobus.at(ivobu);
            int VobNum=vobu->vobNum;

            if (error)
                return;
            if (pVobNum !=VobNum) {
                if (file !=NULL)
                    fclose(file);
                QString sName;
                sName.sprintf("%s/VTS_%02d_%d.VOB",output.latin1(),currVTS,VobNum);
                dbg="Updating vob : " + sName;
                qDebug(dbg);
                QFileInfo finfo(sName);
                long fileSize=finfo.size();

                dbg.sprintf(tr2i18n("Updating vob VTS_%02d_%d.VOB"),currVTS,VobNum);
                backupDlg->setTotalSteps(fileSize);
                backupDlg->setProgressLabel(dbg);

                file=fopen(sName,"r+b");
                pVobNum=VobNum;
            }
            if( file !=NULL) {
                uint32_t sector=0;
                long pos=vobu->vobPos;
                backupDlg->setProgress(pos);
                if (backupDlg->getAbort()) {
                    seterror(tr2i18n("DVD backup canceled"));
                    break;
                }

                bool emptyPgc=false;
                fseek(file,pos,SEEK_SET);
                fread(buffer,DVD_VIDEO_LB_LEN,1,file);
                if (k9Cell::isNavPack((uchar*)buffer)) {
                    dsi_t dsiPack;
                    pci_t pciPack;
                    nbVobuUpdated++;
                    navRead_DSI (&dsiPack, buffer + DSI_START_BYTE);
                    navRead_PCI (&pciPack, buffer+0x2d);
                    sector=dsiPack.dsi_gi.nv_pck_lbn;  //JMP : pour debug
                    //vobu=remapVobu(&dsiPack.dsi_gi.nv_pck_lbn );
                    sector=vobu->oldSector;
                    dsiPack.dsi_gi.nv_pck_lbn=vobu->newSector;
                    if (vobu != NULL) {
                        dsiPack.dsi_gi.vobu_ea = vobu->size;
                        emptyPgc=vobu->empty;
                    } else {
                        dbg.sprintf("remapVobu failed for %d",dsiPack.dsi_gi.nv_pck_lbn);
                    }

                    if (!emptyPgc) {
                        remapOffset(sector, &dsiPack.vobu_sri.next_video,1 );
                        for (int i =0;i<19;i++) {
                            remapOffset(sector,&dsiPack.vobu_sri.fwda[i],1);
                        }
                        remapOffset(sector,&dsiPack.vobu_sri.next_vobu,1);
                        remapOffset(sector,&dsiPack.vobu_sri.prev_vobu,-1);
                        for (int i =0;i<19;i++) {
                            remapOffset(sector,&dsiPack.vobu_sri.bwda[i],-1);
                        }

                        remapOffset(sector,&dsiPack.vobu_sri.prev_video,-1);

                        //1st audio packet
                        for (int i =0 ;i <8 ;i++) {
                            if (((dsiPack.synci.a_synca[i] & 0x8000) != 0x8000 ) && (dsiPack.synci.a_synca[i] !=0x3FFF)) {
                                if (vobu->firstAudio[i] !=-1) {
                                    dsiPack.synci.a_synca[i]=vobu->firstAudio [i];
                                } else {
                                    dsiPack.synci.a_synca[i] =0;
                                }
                            }
                        }
                        //1st subpicture packet
                        for (int i =0 ;i <32 ;i++) {
                            if (((dsiPack.synci.sp_synca[i] & 0x80000000) != 0x80000000) &&
                                    (dsiPack.synci.sp_synca[i] != 0x3FFFFFFF) && (dsiPack.synci.sp_synca[i] != 0x7FFFFFFF)) {
                                if (vobu->firstSubp[i] !=-1) {
                                    dsiPack.synci.sp_synca[i]=vobu->firstSubp [i];
                                } else {
                                    dsiPack.synci.sp_synca[i] =0;
                                }
                            }
                        }
                        //ILVU
                        if (dsiPack.sml_pbi.ilvu_ea !=0) {
                            uint32_t tmp=dsiPack.sml_pbi.ilvu_ea+1;
                            remapOffset(sector,&tmp,1);
                            if (tmp!=0)
                                tmp--;
                            dsiPack.sml_pbi.ilvu_ea=tmp;
                        }
                        if (dsiPack.sml_pbi.ilvu_sa !=0) {
                            k9Vobu *vobu2=remapOffset(sector,&dsiPack.sml_pbi.ilvu_sa,1);
                            if (vobu2!= NULL) {
                                FILE *file2;
                                if ( vobu2->vobNum != VobNum) {
                                    QString sName;
                                    sName.sprintf("%s/VTS_%02d_%d.VOB",output.latin1(),currVTS,vobu2->vobNum);
                                    file2=fopen(sName,"rb");
                                } else
                                    file2=file;
                                fseek(file2,vobu2->vobPos,SEEK_SET);
                                uchar *tmpbuff=(uchar*)malloc(2048);
                                fread(tmpbuff,DVD_VIDEO_LB_LEN,1,file2);
                                dsi_t dsiNext;
                                navRead_DSI (&dsiNext, tmpbuff + DSI_START_BYTE);
                                uint32_t sectmp= dsiNext.sml_pbi.ilvu_ea+1;
                                remapOffset(dsiNext.dsi_gi.nv_pck_lbn,&sectmp,1);
                                dsiPack.sml_pbi.size=sectmp;
                                free (tmpbuff);
                                if (vobu2->vobNum!=VobNum)
                                    fclose(file2);
                            }
                        }

                        // update pci pack
                        for (int i=0; i<9;i++) {
                            if ((pciPack.nsml_agli.nsml_agl_dsta[i] & 0x80000000) != 0x80000000)
                                remapOffset(sector,&pciPack.nsml_agli.nsml_agl_dsta[i],1);
                        }

                    } else {
                        dsiPack.vobu_sri.next_video= 0xbfffffff;
                        for (int i =0;i<19;i++)
                            dsiPack.vobu_sri.fwda[i] = 0x3fffffff;
                        dsiPack.vobu_sri.next_vobu=0x3fffffff;
                        dsiPack.vobu_sri.prev_vobu=0x3fffffff;
                        for (int i =0;i<19;i++)
                            dsiPack.vobu_sri.bwda[i] = 0x3fffffff;
                        dsiPack.vobu_sri.prev_video=0xbfffffff;
                        for (int i =0 ;i <8 ;i++)
                            dsiPack.synci.a_synca[i]=0;
                        for (int i =0 ;i <32 ;i++)
                            dsiPack.synci.sp_synca[i] =0;

                    }
                    // mise en place des donnees modifi�s dans le buffer de sortie
                    navRead_DSI((dsi_t*)(buffer + DSI_START_BYTE),(uchar*)&dsiPack);
                    pciPack.pci_gi.nv_pck_lbn =dsiPack.dsi_gi.nv_pck_lbn;
                    navRead_PCI((pci_t*)(buffer+0x2d),(uchar*)&pciPack);
                    //mise �jour du fichier
                    fseek(file,pos,SEEK_SET);
                    fwrite(buffer,DVD_VIDEO_LB_LEN,1,file);
                }

            }
        }
    }
    fclose(file);
    dbg.sprintf("VTS %d : nb VOBU updated : %d",currVTS,nbVobuUpdated);
    qDebug (dbg);
}

void k9DVDBackup::clearOutput(QString name) {
    QDir dir(name);
    //delete files in directory
    QStringList lst = dir.entryList( "*",QDir::Files |QDir::Hidden );
    for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
        QString c(( *it ).latin1() );
        dir.remove (c);
    }
    //scanning subdir
    QStringList lstdir = dir.entryList( "*",QDir::Dirs );
    for ( QStringList::Iterator it = lstdir.begin(); it != lstdir.end(); ++it ) {
        QString c(( *it ).latin1() );
        if ((c!=".") && c!="..") {
            clearOutput(dir.absFilePath(c));
            dir.rmdir(c);
        }
    }

}


void k9DVDBackup::execute() {
    QString sOutput=output;

    output=QDir::cleanDirPath(output +"/dvd");

    QDir root("/");
    root.mkdir(output);
    clearOutput(output);

    QDir dir(output);
    dir.mkdir("VIDEO_TS");
    dir.mkdir("AUDIO_TS");

    output=QDir::cleanDirPath(output +"/VIDEO_TS");

    m_dvdhandle= DVDOpen (device.latin1());
    if (!m_dvdhandle) {
        seterror(tr2i18n("Unable to open DVD"));
        return;
    }

    k9CellCopyList *cellCopyList =new k9CellCopyList(m_dvdhandle,DVD);

    inject = locateLocal("tmp", "k9v" + (QTime::currentTime()).toString("hhmmss"));

    double totalSize=DVD->getmenuSize() *2048 ;
    totalSize+=cellCopyList->gettotalSize();
    totalSize/=(1024*1024);
    totalSize = (totalSize >4400) ? 4400:totalSize;

    backupDlg->setTotalMax(totalSize);
    //VTSList is sorted by size, so it is easyer to ajust the compression factor
    for(uint iTS=0;iTS<cellCopyList->VTSList.count() &&(!error);iTS++) {
        k9CellCopyVTS *VTS=cellCopyList->VTSList.at(iTS);
        //loop on each cell from the titleset
        for (int iCell=0;(iCell<cellCopyList->count()) ;iCell++) {
            double factor= cellCopyList->getfactor(true,false);
            /*           uint copiedSize=cellCopyList->getcopiedSize();
                       copiedSize/=(1024*1024);
                       backupDlg->setProgressTotal(copiedSize);
            */
            k9Cell *cell=(k9Cell*)cellCopyList->at(iCell);
            if (cell->vts== VTS->getnum() && (!cell->copied)) {
                double dsize=cell->lastSector-cell->startSector;
                dsize*=DVD_BLOCK_LEN;
                argSize.sprintf("%.0f",dsize);
                QString caud="",csub="";
                QValueList<int>::iterator it;
                for ( it = cell->audio.begin(); it != cell->audio.end(); ++it ) {
                    if (caud !="")
                        caud +=",";
                    caud +=QString::number(*it);
                }

                for ( it = cell->subpicture.begin(); it != cell->subpicture.end(); ++it ) {
                    if (csub !="")
                        csub +=",";
                    csub +=QString::number(*it);
                }
                argAudio=caud;
                argSubp=csub;

                QString sFactor;
                sFactor.sprintf("%.2f",factor);
                backupDlg->setFactor(sFactor);

                argFactor =  QString::number(factor );
                if ((cell->angleBlock==angleStart) && cell->selected)
                    copyAngleBlock(cellCopyList,iCell);
                else if (cell->angleBlock==angleNone) {
                    copyCell(cell->vts,cell->pgc ,cell->id,! cell->selected);
                    if (!error) {
                        cell->copied=true;
                        //JMP :  faux, utiliser la somme de k9vobu->size (ajouter une méthode dans k9cell qui fait ça)
                        cell->newSize= currCell->getnewSize();  //currCell->lastSector- currCell->startSector ;
                    }
                }
                if (error)
                    break;
            }
        }
    }
    delete cellCopyList;
    if (!error) {
        updateIfo();
        updateMainIfo();
        updateVob();
    }
    output=sOutput;
    backupDlg->hide();

    if (error)
        KMessageBox::error(0,errMsg,"DVD Backup");
    DVDClose(m_dvdhandle);
}

Generated by  Doxygen 1.6.0   Back to index