/*************************************************************************** * 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., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "k9dvdbackup.h" #include "k9dvd.h" #include "bswap.h" #include "k9ifo2.h" #include "k9vamps.h" #include "ac.h" #include "k9dvdtitleset.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "k9backupdlg.h" #include "dvdread.h" #include "k9script.h" #include "k9tools.h" #define BUF_SECS 1024 #include "k9dvdbackup.moc" int k9CadtList::compareItems(TQPtrCollection::Item item1,TQPtrCollection::Item item2) { cell_adr_t * it1=(cell_adr_t*)item1; cell_adr_t * it2=(cell_adr_t*)item2; return it1->start_sector - it2->start_sector; }; int k9TitleSetList::compareItems ( TQPtrCollection::Item item1, TQPtrCollection::Item item2 ) { k9TitleSet * it1,*it2; it1=(k9TitleSet *) item1; it2=(k9TitleSet *)item2; return it1->VTS - it2->VTS; } /*void k9TitleSet::clearCells() { while (!cells.isEmpty()) delete cells.take(); //qDeleteAll(cells); cells.clear(); } */ k9TitleSet::k9TitleSet(int _VTS):TQObject(NULL,"") { startSector=0; lastSector=0; VTS=_VTS; cells.setAutoDelete(true); ifoTitle=NULL; } k9TitleSet::~k9TitleSet() { //ifoTitle->closeIFO(); //delete 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(TQObject* _dvd,const char* name,const TQStringList& ) : TQObject(NULL, name) { DVD = (k9DVD*)_dvd; m_dvdread=DVD->getdvd(); currVTS=0; outputFile=NULL; currTS=NULL; errMsg=""; error=false; backupDlg = new k9BackupDlg(tqApp->mainWidget(),"",true); // cells.setAutoDelete(true); vamps=new k9vamps(this); m_withMenu=false; m_forcedFactor=false; m_preserve=true; } k9DVDBackup::~k9DVDBackup() { if (outputFile !=NULL) { outputFile->close(); delete outputFile; } delete backupDlg; delete vamps; } void k9DVDBackup::setWithMenus(bool _value) { m_withMenu=_value; } bool k9DVDBackup::geterror() { return error; } void k9DVDBackup::seterror(const TQString &_msg) { error=true; errMsg=_msg; } TQString k9DVDBackup::getErrMsg() { return(errMsg); } void k9DVDBackup::prepareVTS(int _VTS) { if (error) return; ifo_handle_t *hifo; cellSize=0; if (currTS==NULL) { currVTS=0; m_vmgSize=copyMenu2(0); calcFactor(); if (outputFile != NULL) { outputFile->close(); delete outputFile; outputFile=NULL; } } if (backupDlg->getAbort()) { seterror(tr2i18n("DVD backup cancelled")); return; } //creation of output file if (currVTS != _VTS) { if (outputFile != NULL) { outputFile->close(); delete outputFile; outputFile=NULL; updateIfo(); updateVob(&currTS->cells); } if (backupDlg->getAbort()) { seterror(tr2i18n("DVD backup cancelled")); return; } uint32_t startSector=0; if (currTS != NULL) { startSector = currTS->startSector + currTS->getSize(); } else { k9Ifo2 *kifo; kifo=m_dvdread->getIfo(0); hifo = kifo->getIFO(); if (!hifo) { seterror( tr2i18n("unable to open VIDEO_TS.IFO")); return; } startSector= hifo->vmgi_mat->vmg_last_sector+1 ; } currTS = new k9TitleSet(_VTS); currVOB=0; currVTS=_VTS; calcFactor(); //menus are always shrinked currTS->menuSize=copyMenu2(_VTS); if (outputFile != NULL) { outputFile->close(); delete outputFile; } TQString filename; filename.sprintf("/VTS_%02d_1.VOB",_VTS); filename=output+filename; outputFile=new TQFile(filename); if (! outputFile->open(IO_WriteOnly)) { seterror(tr2i18n("Unable to open file ") + filename); return; } currVOB=1; currTS->startSector=startSector; currTS->lastSector += currTS->menuSize ; titleSets.append(currTS); k9Ifo2 *kifo; kifo=m_dvdread->getIfo(_VTS); currTS->ifoTitle=kifo; m_position=0; m_copyMenu=false; calcFactor(); } currVTS=_VTS; } void k9DVDBackup::copyCell(int _VTS,k9Cell * _cell,bool _empty) { if (error) return; prepareVTS(_VTS); if (error) return; if (_cell->getforceFactor()) forceFactor( _cell->getFactor()); mutex.lock(); k9Cell *cell= currTS->addCell(_VTS,0,0); //JMP cell->startSector=m_position; cell->startSector=cell->cellList->getPosition(); currCell=cell; //start cell copy mutex.unlock(); if (!_empty) { if (!vamps->running()) { vamps->reset(); vamps->setPreserve(true); vamps->setInputSize(argSize); TQValueList::iterator it; for ( it = _cell->audio.begin(); it != _cell->audio.end(); ++it ) { if (m_preserve) vamps->addAudio(*it); else vamps->addAudio(*it,_cell->getTitleset()->getNewAudioStreamId(*it)); } for ( it = _cell->subpicture.begin(); it != _cell->subpicture.end(); ++it ) { vamps->addSubpicture(*it); } vamps->setVapFactor(argFactor); vamps->start(TQThread::NormalPriority); } playCell(_VTS,_cell,_empty); } else copyEmptyPgc(_VTS,_cell); tqApp->processEvents(); } void k9DVDBackup::copyEmptyPgc(int _vts,k9Cell *_cell) { if (error) return; ifo_handle_t *vts_handle=currTS->ifoTitle->getIFO(); ; k9DVDFile *dvdfile; if ((dvdfile = m_dvdread->openTitle( _vts))== 0) { TQString stmp; stmp=i18n("Unable to open titleset %1").arg(_vts); seterror(stmp); return ; } backupDlg->setTotalSteps(vts_handle->vtsi_mat->vts_last_sector-vts_handle->vtsi_mat->vtstt_vobs -1); TQString c; c=i18n("Extracting titleset %1").arg(_vts); backupDlg->setProgressLabel(c); backupDlg->show(); uint32_t sector; int32_t len=0; uchar buffer[DVD_VIDEO_LB_LEN]; sector = _cell->startSector; backupDlg->setProgress(sector); dsi_t dsi_pack; uint32_t nsectors; len=dvdfile->readBlocks (sector, 1, buffer); //JMP : D V C if (!k9Cell::isNavPack( buffer) || len==-1) setDummyNavPack( buffer,sector); k9Vobu * vobu=currCell->addVobu(sector); vobu->empty=true; currCell->addNewVobus((char*)buffer,DVD_VIDEO_LB_LEN,currCell->cellList->getPosition(),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; //dummy video pack setDummyPack( buffer); currCell->addNewVobus((char*)buffer,DVD_VIDEO_LB_LEN,currCell->cellList->getPosition()+1,currVOB,outputFile->at()); outputFile->writeBlock((char*)buffer,DVD_VIDEO_LB_LEN); nsectors=1; len=1; //vobu->size +=nsectors; currCell->lastSector=currCell->startSector+ len; currCell->cellList->setPosition(currCell->cellList->getPosition()+1+len); currTS->lastSector+=len+1; dvdfile->close(); backupDlg->setProgressTotal(len+1); if (!m_forcedFactor) { m_cellCopyList->addInbytes( DVD_VIDEO_LB_LEN *2); m_cellCopyList->addOutbytes( DVD_VIDEO_LB_LEN *2); } else { m_cellCopyList->addFrcinbytes(DVD_VIDEO_LB_LEN *2); m_cellCopyList->addFrcoutbytes( DVD_VIDEO_LB_LEN *2); } } void k9DVDBackup::getOutput(uchar * buffer, uint32_t buflen) { if (error) return; mutex.lock(); backupDlg->playMovie(buffer,buflen); mutex.unlock(); if (!m_forcedFactor) m_cellCopyList->addOutbytes( buflen); else m_cellCopyList->addFrcoutbytes( buflen); uchar *temp =buffer; TQString sName; if ((buflen %2048) !=0) tqDebug("getOutput, buffer : %u",buflen); uint end=0; for (uint itemp=0;itempsize(); end=itemp+DVD_VIDEO_LB_LEN; if (k9Cell::isNavPack(temp+itemp)) { k9Vobu * vobu = vobuQueue.dequeue(); cellOut=vobu->parent; dsi_t dsiPack; navRead_DSI (&dsiPack, (uchar*)(temp+itemp) + 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++; if (currVTS==0) sName = "/VIDEO_TS.VOB"; else sName.sprintf("/VTS_%02d_%d.VOB",(int)currVTS,(int)currVOB); sName=output+sName; outputFile=new TQFile(sName); if ( !outputFile->open(IO_WriteOnly)) { seterror(tr2i18n("Unable to open file ") + sName); mutex.unlock(); return; } } } cellOut->addNewVobus((char*)(temp+itemp),DVD_VIDEO_LB_LEN,cellOut->cellList->getPosition() ,currVOB,outputFile->at()); outputFile->writeBlock((char*)(temp+itemp),DVD_VIDEO_LB_LEN); backupDlg->setProgressTotal(1); cellOut->cellList->setPosition( cellOut->cellList->getPosition()+1); if (!m_copyMenu) currTS->lastSector++; mutex.unlock(); } } /*! \fn k9DVDBackup::setDevice(TQString _device) */ void k9DVDBackup::setDevice(TQString _device) { device=_device; } /*! \fn k9DVDBackup::setOutput(TQString _output) */ void k9DVDBackup::setOutput(TQString _output) { output=TQDir::cleanDirPath(_output); } uint32_t k9DVDBackup::copyMenu2(int _vts) { if (error || !m_withMenu ) return 0; k9Ifo2 *kifo; kifo=m_dvdread->getIfo( _vts); ifo_handle_t *hifo =kifo->getIFO(); m_ifo=hifo; uint32_t msize=0; uint32_t menuLastSector; if (_vts==0) msize=hifo->vmgi_mat->vmg_last_sector -1 - 2* hifo->vmgi_mat->vmgi_last_sector; else msize=hifo->vtsi_mat->vtstt_vobs - hifo->vtsi_mat->vtsi_last_sector -1; if (msize==0) { //kifo.closeIFO(); return 0; } menuLastSector=msize-1; m_position=0; m_copyMenu=true; TQString targetName; if (_vts == 0) { targetName="VIDEO_TS.VOB"; } else { targetName.sprintf("VTS_%02i_0.VOB",_vts); } targetName=output+"/"+targetName; outputFile=new TQFile(targetName); if (! outputFile->open(IO_WriteOnly)) { seterror(tr2i18n("Unable to open file ") + targetName); return 0; } k9DVDFile *dvdfile; if ((dvdfile = m_dvdread->openMenu( _vts))== 0) { TQString stmp; stmp=i18n("Unable to open menu for titleset %1").arg(_vts); seterror (stmp); return 0; } k9CellList *lstCell; if (_vts==0) lstCell = &vmgCells; else lstCell = &currTS->menuCells; lstCell->setAutoDelete(true); c_adt_t *c_adt = hifo->menu_c_adt; // c_adt shouldn't be null. It would say that the menu doesn't contain video !? if (c_adt==NULL) return 0; uint32_t length = c_adt->last_byte + 1 - C_ADT_SIZE; cell_adr_t *ptr; ptr= c_adt->cell_adr_table; uint32_t sector, dsi_next_vobu = 0; uint32_t imax=length/sizeof(cell_adr_t); TQString c; c=i18n("Extracting menu for titleset %1").arg(_vts); backupDlg->setProgressLabel(c); backupDlg->show(); backupDlg->setTotalSteps(ptr[imax-1].last_sector); k9CadtList cadr; uint32_t nbCells=0; for (uint32_t i=0;ilast_sector > menuLastSector) (ptr+i)->last_sector=menuLastSector; if ((ptr+i)->start_sector <= menuLastSector) { cadr.append(ptr+i); nbCells++; } //else //tqDebug() << TQString("cell start sector (%1) exceed menu size (%2)").arg((ptr+i)->start_sector).arg(menuLastSector); } cadr.sort(); vamps->reset(); vamps->setPreserve(true); for (uint i=1;i<=8;i++) vamps->addAudio(i); for (uint i=1;i<=32;i++) vamps->addSubpicture(i); vamps->setVapFactor(argFactor); vamps->setInputSize(msize*2048); vamps->start(TQThread::NormalPriority); // while(!vamps->running() && !vamps->finished()); for(uint32_t i = 0; i < nbCells; i++) { currCell=lstCell->addCell(_vts,1,1); dsi_next_vobu=0; cell_adr_t * cellAdr=cadr.at(i); for (sector = cellAdr->start_sector; sector <= cellAdr->last_sector; sector += dsi_next_vobu & 0x7fffffff) { backupDlg->setProgress(sector); if (backupDlg->getAbort()) { seterror(tr2i18n("DVD backup cancelled")); } if (error) { vamps->abort(); break; } else if (vamps->geterror()) { seterror( vamps->geterrMsg()); break; } dsi_next_vobu= copyVobu(dvdfile,sector,NULL); } } vamps->setNoData(); vamps->wait(); uint32_t size=0; //JMP size=m_position; size =lstCell->getPosition(); dvdfile->close(); outputFile->close(); delete outputFile; outputFile=NULL; //kifo.closeIFO(); updateVob(lstCell); m_copyMenu=false; return size; } void k9DVDBackup::playCell (int vts_num, k9Cell *_cell,bool _empty) { if (error) return; ifo_handle_t *vts_handle; k9DVDFile *dvdfile; uint32_t sector, dsi_next_vobu = 0; /* open disc */ if (m_dvdread->opened()) { /* load information for the given VTS */ // vts_handle = ifoOpen (dvd_handle, vts_num); vts_handle=currTS->ifoTitle->getIFO(); if (!vts_handle) { TQString stmp; stmp=i18n("Unable to open ifo file for titleset %1").arg(vts_num); seterror (stmp); //JMP vamps->setNoData(); return; } backupDlg->setTotalSteps( vts_handle->vtsi_mat->vts_last_sector-vts_handle->vtsi_mat->vtstt_vobs -1); TQString c; c=i18n("Extracting titleset %1").arg(vts_num); backupDlg->setProgressLabel(c); backupDlg->show(); } else { seterror(tr2i18n("Unable to open DVD")); //JMP vamps->setNoData(); return; } /* open VTS data */ dvdfile = m_dvdread->openTitle (vts_num); if (! dvdfile) { TQString stmp; stmp=i18n("Unable to open vobs for titleset %1").arg(vts_num); seterror( stmp); //JMP vamps->setNoData(); return; } /* loop until out of the cell */ //TO REMOVE currCell->oldStartSector=_cell->startSector; for (sector = _cell->startSector; sector <= _cell->lastSector; sector += dsi_next_vobu & 0x7fffffff) { backupDlg->setProgress(sector); if (backupDlg->getAbort()) { seterror(tr2i18n("DVD backup cancelled")); } if (error) { vamps->abort(); break; } else if (vamps->geterror()) { seterror( vamps->geterrMsg()); break; } dsi_next_vobu= copyVobu(dvdfile,sector,NULL,_empty); } dvdfile->close(); } void k9DVDBackup::setDummyNavPack(uchar *buf,uint32_t _sector) { int8_t *ptr = (int8_t*)buf; static uint8_t nav_pack1 [] = { /* pack header: SCR=0, mux rate=10080000bps, stuffing length=0 */ 0, 0, 1, 0xba, 0x44, 0x00, 0x04, 0x00, 0x04, 0x01, 0x01, 0x89, 0xc3, 0xf8, /* system header */ 0, 0, 1, 0xbb, 0x00, 0x12, /* contents of system header filled in at run time (18 bytes) */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PES header for first private stream 2 packet */ 0, 0, 1, 0xbf, 0x03, 0xd4 }; static uint8_t nav_pack2 [] = { /* PES header for second private stream 2 packet */ 0, 0, 1, 0xbf, 0x03, 0xfa }; tc_memcpy (ptr, nav_pack1, sizeof (nav_pack1)); ptr += sizeof (nav_pack1); memset (ptr, 0, DVD_VIDEO_LB_LEN/2 - sizeof (nav_pack1)); ptr = (int8_t*)buf + DVD_VIDEO_LB_LEN/2; tc_memcpy (ptr, nav_pack2, sizeof (nav_pack2)); ptr += sizeof (nav_pack2); memset (ptr, 0, DVD_VIDEO_LB_LEN/2 - sizeof (nav_pack2)); dsi_t dsiPack; pci_t pciPack; navRead_DSI (&dsiPack, buf + DSI_START_BYTE); k9Ifo2::navRead_PCI (&pciPack, buf+0x2d); dsiPack.dsi_gi.nv_pck_lbn=_sector; dsiPack.dsi_gi.vobu_ea = 1; navRead_DSI((dsi_t*)(buf + DSI_START_BYTE),(uchar*)&dsiPack); pciPack.pci_gi.nv_pck_lbn =dsiPack.dsi_gi.nv_pck_lbn; k9Ifo2::navRead_PCI((pci_t*)(buf+0x2d),(uchar*)&pciPack); } void k9DVDBackup::setDummyPack(uchar *_buffer) { int8_t *ptr = (int8_t*)_buffer; uint8_t dummy_pack [] = { /* pack header: SCR=0, mux rate=10080000bps, stuffing length=0 */ 0, 0, 1, 0xba, 0x44, 0x00, 0x04, 0x00, 0x04, 0x01, 0x01, 0x89, 0xc3, 0xf8, /* PES header for dummy video packet */ 0, 0, 1, 0xe0, 0x07, 0xec, 0x81, 0x00, 0x00 }; tc_memcpy (ptr, dummy_pack, sizeof (dummy_pack)); ptr += sizeof (dummy_pack); memset (ptr, 0xff, DVD_VIDEO_LB_LEN - sizeof (dummy_pack)); } uint32_t k9DVDBackup::findNextVobu(uint32_t _sector) { k9Ifo2 *ifo; ifo = m_dvdread->getIfo(currVTS); m_ifo=ifo->getIFO(); vobu_admap_t * vobu_admap; if (m_copyMenu) vobu_admap = m_ifo->menu_vobu_admap; else vobu_admap = m_ifo->vts_vobu_admap; uint32_t length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; for(uint32_t i = 0; i < length/sizeof(uint32_t); i++) { if (vobu_admap->vobu_start_sectors[i] >= _sector) { uint32_t nextVobu=vobu_admap->vobu_start_sectors[i+1]; //ifo.closeIFO(); return nextVobu; } } //ifo.closeIFO(); return 0; } uint32_t k9DVDBackup::copyVobu(k9DVDFile *_fileHandle,uint32_t _startSector,k9Vobu * _vobu,bool _empty) { dsi_t dsi_pack; k9Vobu * currVobu; bool badNavPack=false; uint32_t nsectors, nextVobu=0; int32_t len=0; uchar *buf; uint32_t sector=_startSector; /* read nav pack */ buf=(uchar*) malloc(DVD_VIDEO_LB_LEN); len = _fileHandle->readBlocks ( sector, 1, buf); /* parse contained DSI pack */ //test if nav pack is ok if (len !=-1) { navRead_DSI (&dsi_pack, buf + DSI_START_BYTE); if (dsi_pack.dsi_gi.nv_pck_lbn != sector) { len=-1; } } if (len==-1) { setDummyNavPack(buf,sector); nextVobu=findNextVobu(sector); tqDebug ("VOBU : %u Read Error !!!! ==> %u",sector,nextVobu); badNavPack=true; } currVobu=_vobu; mutex.lock(); if (k9Cell::isNavPack(buf)) { //TO REMOVE currCell->oldLastSector=sector; if (currVobu==NULL) { currVobu =currCell->addVobu(sector); vobuQueue.enqueue(currVobu); } } mutex.unlock(); /* generate an MPEG2 program stream (including nav packs) */ wrote=false; vamps->addData(buf,DVD_VIDEO_LB_LEN); if (!m_forcedFactor) m_cellCopyList->addInbytes( DVD_VIDEO_LB_LEN); else m_cellCopyList->addFrcinbytes(DVD_VIDEO_LB_LEN); uint32_t end; if (badNavPack) { setDummyPack(buf); nsectors=1; if (nextVobu !=0) end=nextVobu-_startSector-1; } else { if (!_empty) nsectors = dsi_pack.dsi_gi.vobu_ea; else nsectors = 1; //uint32_t dsi_next_vobu = dsi_pack.vobu_sri.next_vobu; buf=(uchar*) realloc(buf,nsectors*DVD_VIDEO_LB_LEN); end=dsi_pack.dsi_gi.vobu_ea; if (_empty) setDummyPack(buf); /* read VOBU */ else for (uint32_t i=0;i< nsectors;i++) { len = _fileHandle->readBlocks ( (sector + 1)+i, 1, buf +(i*DVD_VIDEO_LB_LEN)); if (len==-1) { tqDebug ("VOBU : %u Read Error !!!!",sector); //setDummyPack(buf + (i*DVD_VIDEO_LB_LEN)); setDummyPack(buf); nsectors=1; break; } } } /* write VOBU */ for (uint32_t i=0;iaddData(buf + (i*DVD_VIDEO_LB_LEN), DVD_VIDEO_LB_LEN); } free(buf); if (! m_forcedFactor) m_cellCopyList->addInbytes( nsectors*DVD_VIDEO_LB_LEN); else m_cellCopyList->addFrcinbytes( nsectors*DVD_VIDEO_LB_LEN); mutex.lock(); tqApp->processEvents(); mutex.unlock(); return (end+1); } 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; k9CellList *lstCell; if(! m_copyMenu) { lstCell=&(currTS->cells); } else { if (currVTS==0) lstCell=&vmgCells; else lstCell=&(currTS->menuCells); } vobu=lstCell->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; } k9CellList *lstCell; if(! m_copyMenu) { lstCell=&(currTS->cells); } else { if (currVTS==0) lstCell=&vmgCells; else lstCell=&(currTS->menuCells); } vobu1 = lstCell->findVobu(sector); vobu2 = lstCell->findVobu(sector+_dir*offset); if ((vobu1 !=NULL) && (vobu2!=NULL)) { *_offset = labs(vobu1->newSector - vobu2->newSector) | maskOffset1 ; *_offset |= maskOffset2; return vobu2; } if (vobu1==NULL && vobu2==NULL) tqDebug ("remapOffset : sector not found"); } return vobu2; } void k9DVDBackup::updateMainIfo() { if (error) return; k9Ifo2 ifo(m_dvdread); ifo.setOutput(output); ifo.setDevice(device); ifo.openIFO(0); ifo_handle_t *hifo =ifo.getIFO(); hifo->vmgi_mat->vmg_last_sector= 1+ m_vmgSize+hifo->vmgi_mat->vmgi_last_sector*2; if (m_vmgSize >0) { if (hifo->vmgi_mat->vmgm_vobs != hifo->vmgi_mat->vmgi_last_sector +1) tqDebug ("error in ifo file : vmgm_vobs %u -> %u)",hifo->vmgi_mat->vmgm_vobs,hifo->vmgi_mat->vmgi_last_sector +1); hifo->vmgi_mat->vmgm_vobs=hifo->vmgi_mat->vmgi_last_sector +1; } currVTS=0; k9Vobu* vobu2=NULL; uint32_t newPos=0; //update first play PGC if (hifo->first_play_pgc !=NULL ) { m_copyMenu=true; pgc_t *pgc=hifo->first_play_pgc; if (! m_withMenu && pgc->command_tbl!=0 ) { pgc->command_tbl->nr_of_pre=0; pgc->command_tbl->nr_of_post=0; pgc->command_tbl->nr_of_cell=0; } cell_playback_t *cell_playback =pgc->cell_playback; uint32_t nr= pgc->nr_of_cells; vobu2=NULL; cell_playback_t cell; newPos=0; for( uint32_t 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;jnr_of_cells=newPos; m_copyMenu=false; } updatePgci_ut(hifo); update4Menu(hifo); //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;iTSVTS == 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::updatePgci_ut(ifo_handle_t *_hifo) { pgci_ut_t *pgci_ut=_hifo->pgci_ut; k9Vobu* vobu2=NULL; uint newPos=0; //update pgci_ut if (pgci_ut !=0 && m_withMenu) { m_copyMenu=true; for (uint i=0; i nr_of_lus;i++) { pgci_lu_t *pgci_lu= &pgci_ut->lu[i]; pgcit_t * pgcit= pgci_lu->pgcit; for (uint i2=0 ; i2 nr_of_pgci_srp;i2++) { pgci_srp_t * pgci_srp=&pgcit->pgci_srp[i2]; pgc_t *pgc=pgci_srp->pgc; if (! m_withMenu && pgc->command_tbl!=0) { pgc->command_tbl->nr_of_pre=0; pgc->command_tbl->nr_of_post=0; pgc->command_tbl->nr_of_cell=0; } cell_playback_t *cell_playback =pgc->cell_playback; uint32_t nr= pgc->nr_of_cells; vobu2=NULL; cell_playback_t cell; newPos=0; for( uint32_t 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_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;jnr_of_cells=newPos; } } m_copyMenu=false; } if (!m_withMenu ) { k9Script *script=new k9Script(_hifo,DVD); script->updatePGCIUT(); script->updateFPPGC(); delete script; if (_hifo->vmgi_mat) { _hifo->vmgi_mat->vmgm_c_adt=0; _hifo->vmgi_mat->vmgm_vobu_admap=0; } else { _hifo->vtsi_mat->vtsm_c_adt=0; _hifo->vtsi_mat->vtsm_vobu_admap=0; } } } void k9DVDBackup::update4Menu(ifo_handle_t *_hifo) { if (!m_withMenu) return; // Mise �jour vtsm_c_adt pour le menu m_copyMenu=true; //indispensable pour remapvobu c_adt_t *c_adt = _hifo->menu_c_adt; uint32_t length; if (c_adt!=NULL) { length = c_adt->last_byte + 1 - C_ADT_SIZE; cell_adr_t *ptr= c_adt->cell_adr_table; 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) tqDebug ("Error : could not find startSector"); else { if (remapVobu(&lastSect)==NULL) lastSect=vobu->parent->lastSector; else lastSect--; ptr[i].start_sector = startSect; ptr[i].last_sector = lastSect; } } } vobu_admap_t * vobu_admap = _hifo->menu_vobu_admap; if (vobu_admap != NULL) { length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE; uint 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; } m_copyMenu=false; } void k9DVDBackup::updateIfo() { if (error) return; k9Ifo2 ifo(m_dvdread); 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 ; hifo->vtsi_mat->vtstt_vobs = hifo->vtsi_mat->vtsi_last_sector + 1 + currTS->menuSize; //JMP if (currTS->menuSize >0) { if (hifo->vtsi_mat->vtsm_vobs != hifo->vtsi_mat->vtsi_last_sector +1) tqDebug ("error in ifo file %u : vtsm_vobs %u -> %u",currTS->VTS,hifo->vtsi_mat->vtsm_vobs,hifo->vtsi_mat->vtsi_last_sector +1); hifo->vtsi_mat->vtsm_vobs= hifo->vtsi_mat->vtsi_last_sector +1 ; }else hifo->vtsi_mat->vtsm_vobs=0; updatePgci_ut(hifo); k9Vobu* vobu2=NULL; uint32_t newPos=0; //update first play PGC if (hifo->first_play_pgc !=NULL ) { pgc_t *pgc=hifo->first_play_pgc; if (! m_withMenu && pgc->command_tbl!=0) { pgc->command_tbl->nr_of_pre=0; pgc->command_tbl->nr_of_post=0; pgc->command_tbl->nr_of_cell=0; } cell_playback_t *cell_playback =pgc->cell_playback; uint32_t nr= pgc->nr_of_cells; vobu2=NULL; cell_playback_t cell; newPos=0; for( uint 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;jnr_of_cells=newPos; } newPos=0; audio_attr_t vts_audio_attr[8]; //update each PGC bool bUpdateAudioAttr=true; if (!m_preserve) { memcpy (vts_audio_attr, hifo->vtsi_mat->vts_audio_attr,sizeof(audio_attr_t)*8); memset(hifo->vtsi_mat->vts_audio_attr,0,sizeof(audio_attr_t)*8); } for(uint32_t i = 0; i < pgcit->nr_of_pgci_srp; i++) { pgc_t *pgc=pgcit->pgci_srp[i].pgc; int numTitle=pgcit->pgci_srp[i].entry_id & 0x7F; if (! m_withMenu) { k9Script *script=new k9Script(hifo,DVD); script->updatePGC(pgc,currTS->VTS,numTitle); delete script; } //shift audio streams; if (!m_preserve) { int idx=0; uint16_t audio_control [8]; memcpy(audio_control,pgc->audio_control,sizeof(uint16_t) *8); memset(pgc->audio_control,0,sizeof(uint16_t) *8); for (int istr=0; istr< 8; istr++) { uint16_t ctrl=audio_control[istr] & 0xF8FF; int streamId = 1+ ((audio_control[istr]>>8) & 0x7) ; int newStreamId = DVD->gettitleset(currTS->VTS-1)->getNewAudioStreamId(streamId); if (newStreamId !=0) { pgc->audio_control[idx]=ctrl | ((newStreamId-1)<<8); if (bUpdateAudioAttr) { hifo->vtsi_mat->vts_audio_attr[idx]=vts_audio_attr[istr]; } idx++; } } if (bUpdateAudioAttr) hifo->vtsi_mat->nr_of_vts_audio_streams=idx; bUpdateAudioAttr=false; } cell_playback_t *cell_playback =pgc->cell_playback; uint32_t nr= pgc->nr_of_cells; vobu2=NULL; cell_playback_t cell; newPos=0; for( uint32_t 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;jnr_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= 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) tqDebug ("Error : could not find startSector"); else { if (remapVobu(&lastSect)==NULL) lastSect= vobu->parent->lastSector; else lastSect--; ptr[i].start_sector = startSect; ptr[i].last_sector = lastSect; } } 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; } } update4Menu(hifo); ifo.saveIFO(); } void k9DVDBackup::updateVob(k9CellList *cellLst) { int nbVobuUpdated=0; uchar buffer[DVD_VIDEO_LB_LEN]; TQFile *file=NULL; TQString dbg; int pVobNum=-1; //for (uint iCell=0;iCellcells.count();iCell++) { // k9Cell *cell=currTS->cells.at(iCell); for (uint iCell=0;iCell< cellLst->count();iCell++) { k9Cell *cell=cellLst->at(iCell); for (uint ivobu=0; ivobuvobus.count();ivobu++) { tqApp->processEvents(); k9Vobu * vobu = cell->vobus.at(ivobu); int VobNum=vobu->vobNum; if (error) return; if (pVobNum !=VobNum) { if (file !=NULL){ file->close(); delete file; } //fclose(file); TQString sName; if (currVTS==0) sName="VIDEO_TS.VOB"; else sName.sprintf("VTS_%02d_%d.VOB",(int)currVTS,(int)VobNum); dbg=i18n("Updating vob %1").arg(sName); sName=output+"/"+sName; TQFileInfo finfo(sName); long fileSize=finfo.size(); backupDlg->setTotalSteps(fileSize); backupDlg->setProgressLabel(dbg); file =new TQFile(sName); file->open( IO_ReadWrite); //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; /* long currpos=ftell(file); long offset=pos-currpos; fseek(file,offset,SEEK_CUR); */ //fseek(file,pos,SEEK_SET); file->at(pos); //fread(buffer,DVD_VIDEO_LB_LEN,1,file); file->readBlock((char*)buffer,DVD_VIDEO_LB_LEN); if (k9Cell::isNavPack((uchar*)buffer)) { dsi_t dsiPack; pci_t pciPack; nbVobuUpdated++; navRead_DSI (&dsiPack, buffer + DSI_START_BYTE); k9Ifo2::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) && (dsiPack.synci.a_synca[i] !=0x0)) { if ( (dsiPack.synci.a_synca[i] !=0x3FFF) && (dsiPack.synci.a_synca[i] !=0x0)) { if (vobu->firstAudio[i] !=-1) { dsiPack.synci.a_synca[i]=vobu->firstAudio [i]; } else { //JMP dsiPack.synci.a_synca[i] =0; dsiPack.synci.a_synca[i] =0x3FFF; } } } //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) && (dsiPack.synci.sp_synca[i] != 0x0)) { if ((dsiPack.synci.sp_synca[i] != 0x3FFFFFFF) && (dsiPack.synci.sp_synca[i] != 0x0)) { if (vobu->firstSubp[i] !=-1) { dsiPack.synci.sp_synca[i]=vobu->firstSubp [i]; } else { //JMP dsiPack.synci.sp_synca[i] =0; dsiPack.synci.sp_synca[i] =0x3FFFFFFF; } } } //ILVU for (int i=0;i<9;i++) { if (dsiPack.sml_agli.data[i].address !=0 && dsiPack.sml_agli.data[i].address !=0x7FFFFFFF) { uint32_t tmpAdr=dsiPack.sml_agli.data[i].address; uint32_t tmpSize=(dsiPack.sml_agli.data[i].address & 0x7FFFFFFF) + dsiPack.sml_agli.data[i].size; int dir; if ((tmpAdr & 0x80000000) ==0x80000000) dir=-1; else dir=1; remapOffset(sector,&tmpAdr,dir); remapOffset(sector,&tmpSize,1); dsiPack.sml_agli.data[i].address=tmpAdr; dsiPack.sml_agli.data[i].size=tmpSize-(tmpAdr &0x7FFFFFFF); } } 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) { TQFile *file2; if ( vobu2->vobNum != VobNum) { TQString sName; sName.sprintf("/VTS_%02d_%d.VOB",(int)currVTS,(int)vobu2->vobNum); sName=output+sName; file2=new TQFile(sName); file2->open(IO_ReadWrite); //file2=fopen(sName,"rb"); } else file2=file; //fseek(file2,vobu2->vobPos,SEEK_SET); file2->at(vobu2->vobPos); uchar *tmpbuff=(uchar*)malloc(2048); //fread(tmpbuff,DVD_VIDEO_LB_LEN,1,file2); file2->readBlock( (char*)tmpbuff,DVD_VIDEO_LB_LEN); 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,§mp,1); dsiPack.sml_pbi.size=sectmp; free (tmpbuff); if (vobu2->vobNum!=VobNum) { file2->close(); delete file2; } } } // end block reference frames dsiPack.dsi_gi.vobu_1stref_ea = vobu->firstRef; dsiPack.dsi_gi.vobu_2ndref_ea=vobu->secondRef; dsiPack.dsi_gi.vobu_3rdref_ea=vobu->thirdRef; // 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]=0x3fff; for (int i =0 ;i <32 ;i++) dsiPack.synci.sp_synca[i] =0x3FFFFFFF; // end block reference frames dsiPack.dsi_gi.vobu_1stref_ea = 0; dsiPack.dsi_gi.vobu_2ndref_ea=0; dsiPack.dsi_gi.vobu_3rdref_ea=0; //JMP for tests pciPack.pci_gi.vobu_s_ptm=0; pciPack.pci_gi.vobu_e_ptm=0; pciPack.pci_gi.vobu_se_e_ptm=0; pciPack.pci_gi.e_eltm.hour = pciPack.pci_gi.e_eltm.minute =pciPack.pci_gi.e_eltm.second=0; dsiPack.dsi_gi.c_eltm.hour=dsiPack.dsi_gi.c_eltm.minute=dsiPack.dsi_gi.c_eltm.second=0; for (int i=0;i<9;i++) { dsiPack.sml_agli.data[i].address=0x7FFFFFFF; dsiPack.sml_agli.data[i].size=0; } dsiPack.sml_pbi.ilvu_ea=0; dsiPack.sml_pbi.ilvu_sa=0; dsiPack.sml_pbi.size=0; dsiPack.dsi_gi.vobu_1stref_ea = 0; dsiPack.dsi_gi.vobu_2ndref_ea=0; dsiPack.dsi_gi.vobu_3rdref_ea=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; k9Ifo2::navRead_PCI((pci_t*)(buffer+0x2d),(uchar*)&pciPack); //mise �jour du fichier //fseek(file,pos,SEEK_SET); file->at(pos); //fwrite(buffer,DVD_VIDEO_LB_LEN,1,file); file->writeBlock((const char*)buffer,DVD_VIDEO_LB_LEN); } } else { tqDebug ("erreur positionning"); } } } if (file!=NULL) { file->close(); delete file; } } uint k9DVDBackup::getLastCell(k9CellCopyList *_cellCopyList, uint _index) { k9Cell *orig=(k9Cell*)_cellCopyList->at(_index); uint result=_index; uint64_t dsize=1+orig->lastSector-orig->startSector; uchar audioOrig[8]; uchar subpOrig[32]; memset(audioOrig,0,sizeof(uchar)*8); memset(subpOrig,0,sizeof(uchar)*32); ; TQValueList::iterator it; for ( it = orig->audio.begin(); it != orig->audio.end(); ++it ) audioOrig[*it -1]=1; for ( it = orig->subpicture.begin(); it != orig->subpicture.end(); ++it ) subpOrig[*it -1]=1; float factor=-1; for (uint iCell=_index+1;(iCell<_cellCopyList->count()) ;iCell++) { k9Cell *cell=(k9Cell*)_cellCopyList->at(iCell); if ((cell->vts== orig->vts) && ( cell->selected)) { //if the cell factor changed, it's a new group of cells if (factor==-1) factor=cell->getFactor(); else { if (cell->getFactor()!=factor) break; } uchar audio[8]; uchar subp[32]; memset(audio,0,sizeof(uchar)*8); memset(subp,0,sizeof(uchar)*32); ; TQValueList::iterator it; for ( it = cell->audio.begin(); it != cell->audio.end(); ++it ) audio[*it -1]=1; for ( it = cell->subpicture.begin(); it != cell->subpicture.end(); ++it ) subp[*it -1]=1; if ( (memcmp(audioOrig,audio,sizeof(uchar)*8) ==0) && (memcmp(subpOrig,subp,sizeof(uchar)*32) ==0)) { result=iCell; dsize+=1+cell->lastSector-cell->startSector; } else break; } else break; } dsize*=DVD_BLOCK_LEN; argSize=dsize; return result; } void k9DVDBackup::calcFactor() { double factor=m_cellCopyList->getfactor(m_withMenu,false); TQString sFactor; sFactor.sprintf("%.2f",factor); backupDlg->setFactor(sFactor); argFactor = factor; m_forcedFactor=false; } void k9DVDBackup::forceFactor(double _factor) { double factor=_factor; double minFactor=m_cellCopyList->getMinFactor( m_withMenu); if (factorsetFactor(sFactor); argFactor = factor; m_forcedFactor=true; tqDebug("force factor : %f min:%f",factor,minFactor); } void k9DVDBackup::execute() { TQString sOutput=output; output=TQDir::cleanDirPath(output +"/dvd"); TQDir root("/"); root.mkdir(output); k9Tools::clearOutput(output); TQDir dir(output); dir.mkdir("VIDEO_TS"); dir.mkdir("AUDIO_TS"); output=TQDir::cleanDirPath(output +"/VIDEO_TS"); m_dvdread->openDevice(device); if (!m_dvdread->opened()) { seterror(tr2i18n("Unable to open DVD")); return; } k9CellCopyList *cellCopyList =new k9CellCopyList(m_dvdread,DVD); m_cellCopyList=cellCopyList; double totalSize=cellCopyList->gettotalSize(); if (m_withMenu) totalSize+=DVD->getmenuSize() *2048 ; totalSize/=(1024*1024); totalSize = (totalSize >k9DVDSize::getMaxSize()) ? k9DVDSize::getMaxSize():totalSize; backupDlg->setTotalMax((uint32_t)totalSize); int lastCell; calcFactor(); //VTSList is sorted by size, so it is easier to ajust the compression factor for(uint iTS=0;iTSVTSList.count() &&(!error);iTS++) { k9CellCopyVTS *VTS=cellCopyList->VTSList.at(iTS); //loop on each cell from the titleset lastCell=-1; for (uint iCell=0;(iCellcount()) ;iCell++) { k9Cell *cell=(k9Cell*)cellCopyList->at(iCell); if (cell->vts==(int) VTS->getnum() && (!cell->copied)) { // currCopyCell=cell; if (lastCell < (int)iCell) { lastCell=getLastCell( cellCopyList,iCell); //adjusting factor of compression if ( cell->getforceFactor()) forceFactor( cell->getFactor()); else calcFactor(); } copyCell(cell->vts,cell,! cell->selected); if (!error) { cell->copied=true; } // } if (lastCell==(int)iCell) { vamps->setNoData(); vamps->wait(); } if (error) break; } } vamps->setNoData(); vamps->wait(); } delete cellCopyList; if (!error) { updateIfo(); updateVob(&currTS->cells); updateMainIfo(); } output=sOutput; backupDlg->hide(); if (error) KMessageBox::error(0,errMsg,"DVD Backup"); //m_dvdread->close(); }