summaryrefslogtreecommitdiffstats
path: root/libk9copy/k9dvdbackup.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-17 00:32:19 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-17 00:32:19 +0000
commit0d382a262c0638d0f572fc37193ccc5ed3dc895f (patch)
tree8578dcddfce4191f3f7a142a37769df7add48475 /libk9copy/k9dvdbackup.cpp
downloadk9copy-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/k9dvdbackup.cpp')
-rwxr-xr-xlibk9copy/k9dvdbackup.cpp1776
1 files changed, 1776 insertions, 0 deletions
diff --git a/libk9copy/k9dvdbackup.cpp b/libk9copy/k9dvdbackup.cpp
new file mode 100755
index 0000000..a651475
--- /dev/null
+++ b/libk9copy/k9dvdbackup.cpp
@@ -0,0 +1,1776 @@
+/***************************************************************************
+* 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 <kmessagebox.h>
+#include <kapplication.h>
+#include <qapplication.h>
+#include <qfileinfo.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 "k9backupdlg.h"
+#include "dvdread.h"
+#include "k9script.h"
+#include "k9tools.h"
+
+#define BUF_SECS 1024
+
+
+#include "k9dvdbackup.moc"
+
+int k9CadtList::compareItems(QPtrCollection::Item item1,QPtrCollection::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 ( QPtrCollection::Item item1, QPtrCollection::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):QObject(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(QObject* _dvd,const char* name,const QStringList& )
+ : QObject(NULL, name) {
+ DVD = (k9DVD*)_dvd;
+ m_dvdread=DVD->getdvd();
+ currVTS=0;
+ outputFile=NULL;
+ currTS=NULL;
+ errMsg="";
+ error=false;
+ backupDlg = new k9BackupDlg(qApp->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 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;
+ 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;
+ }
+
+ QString filename;
+ filename.sprintf("/VTS_%02d_1.VOB",_VTS);
+ filename=output+filename;
+ outputFile=new QFile(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);
+ QValueList<int>::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(QThread::NormalPriority);
+ }
+ playCell(_VTS,_cell,_empty);
+ } else
+ copyEmptyPgc(_VTS,_cell);
+ qApp->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) {
+ QString 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);
+ QString 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;
+ QString sName;
+ if ((buflen %2048) !=0)
+ qDebug("getOutput, buffer : %u",buflen);
+ uint end=0;
+
+ for (uint itemp=0;itemp<buflen;itemp+=DVD_VIDEO_LB_LEN) {
+ if (buflen-itemp <DVD_VIDEO_LB_LEN)
+ break;
+
+
+ mutex.lock();
+ long fileSize=outputFile->size();
+ 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 QFile(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(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::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;
+ QString targetName;
+ if (_vts == 0) {
+ targetName="VIDEO_TS.VOB";
+ } else {
+ targetName.sprintf("VTS_%02i_0.VOB",_vts);
+ }
+ targetName=output+"/"+targetName;
+
+ outputFile=new QFile(targetName);
+ if (! outputFile->open(IO_WriteOnly)) {
+ seterror(tr2i18n("Unable to open file ") + targetName);
+ return 0;
+ }
+
+ k9DVDFile *dvdfile;
+ if ((dvdfile = m_dvdread->openMenu( _vts))== 0) {
+ QString 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);
+ QString 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;i<imax;i++) {
+ if ((ptr+i)->last_sector > menuLastSector)
+ (ptr+i)->last_sector=menuLastSector;
+
+ if ((ptr+i)->start_sector <= menuLastSector) {
+ cadr.append(ptr+i);
+ nbCells++;
+ }
+ //else
+ //qDebug() << QString("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(QThread::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) {
+ QString 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);
+ QString 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) {
+ QString 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);
+ qDebug ("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) {
+ qDebug ("VOBU : %u Read Error !!!!",sector);
+ //setDummyPack(buf + (i*DVD_VIDEO_LB_LEN));
+ setDummyPack(buf);
+ nsectors=1;
+ break;
+ }
+ }
+ }
+
+ /* write VOBU */
+ for (uint32_t i=0;i<nsectors ;i++) {
+ vamps->addData(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();
+ qApp->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 = 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;
+
+ 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)
+ qDebug ("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;j<nr;j++)
+ cell_playback[j].last_sector=0;
+ pgc->nr_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;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::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 <pgci_ut->nr_of_lus;i++) {
+ pgci_lu_t *pgci_lu= &pgci_ut->lu[i];
+ pgcit_t * pgcit= pgci_lu->pgcit;
+ for (uint i2=0 ; i2 <pgcit->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;j<nr;j++)
+ cell_playback[j].last_sector=0;
+ pgc->nr_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)
+ qDebug ("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)
+ qDebug ("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;j<nr;j++)
+ cell_playback[j].last_sector=0;
+ pgc->nr_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;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= 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");
+ 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];
+ QFile *file=NULL;
+ QString dbg;
+ int pVobNum=-1;
+ //for (uint iCell=0;iCell<currTS->cells.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; ivobu<cell->vobus.count();ivobu++) {
+ qApp->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);
+ QString 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;
+ QFileInfo finfo(sName);
+ long fileSize=finfo.size();
+
+ backupDlg->setTotalSteps(fileSize);
+ backupDlg->setProgressLabel(dbg);
+ file =new QFile(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) {
+ QFile *file2;
+ if ( vobu2->vobNum != VobNum) {
+ QString sName;
+ sName.sprintf("/VTS_%02d_%d.VOB",(int)currVTS,(int)vobu2->vobNum);
+ sName=output+sName;
+ file2=new QFile(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,&sectmp,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 {
+ qDebug ("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);
+
+ ;
+ QValueList<int>::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);
+ ;
+ QValueList<int>::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);
+ QString 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 (factor<minFactor)
+ factor=minFactor;
+ QString sFactor;
+ sFactor.sprintf("%.2f",factor);
+ backupDlg->setFactor(sFactor);
+ argFactor = factor;
+ m_forcedFactor=true;
+ qDebug("force factor : %f min:%f",factor,minFactor);
+}
+
+
+void k9DVDBackup::execute() {
+ QString sOutput=output;
+
+ output=QDir::cleanDirPath(output +"/dvd");
+
+ QDir root("/");
+ root.mkdir(output);
+ k9Tools::clearOutput(output);
+
+ QDir dir(output);
+ dir.mkdir("VIDEO_TS");
+ dir.mkdir("AUDIO_TS");
+
+ output=QDir::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;iTS<cellCopyList->VTSList.count() &&(!error);iTS++) {
+ k9CellCopyVTS *VTS=cellCopyList->VTSList.at(iTS);
+ //loop on each cell from the titleset
+ lastCell=-1;
+ for (uint iCell=0;(iCell<cellCopyList->count()) ;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();
+}