/************************************************************************** * 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 "k9cell.h" #include "k9dvdtitleset.h" int k9VobuList::compareItems ( TQPtrCollection::Item item1, TQPtrCollection::Item item2 ) { return(((k9Vobu*)item1)->oldSector- ((k9Vobu*)item2)->oldSector); } k9Vobu * k9VobuList::findVobu(uint32_t sector) { //int c=count(); //if (c >0) { k9Vobu *v1,*v2; v1=first(); v2=last(); if (v1==NULL) return NULL; if (sector >= v1->oldSector && sector <= v2->oldSector) return findVobu(sector,0,count()-1); else return NULL; //} } k9Vobu * k9VobuList::findVobu(uint32_t sector, uint32_t start, uint32_t end) { long lstart=start; long lend=end; while (lstart <=lend) { long m =(lstart+lend)/2; k9Vobu *v = (k9Vobu *)at(m); if ( v->oldSector == sector) { return v; } else if ( v->oldSector >sector) { lend = m-1; } else { lstart=m+1; } } return NULL; } uint32_t k9Cell::getnewSize() { uint32_t size=0; //for (k9Vobu * vobu=vobus.first();vobu;vobu=vobus.next()) for (uint i=0; isize; } return size; } int k9Cell::getStreamID(int type) { int abase=0; if (type >= 0x80 && type <= 0x87) { // AC3 audio abase = 0x80; } else if (type >= 0x88 && type <= 0x8f) { // DTS audio abase = 0x88; } else if (type >= 0xa0 && type <= 0xbf) { // LPCM audio abase = 0xa0; } else if (type >= 0xc0 && type <= 0xdf) { // MPEG audio abase = 0xc0; } else if (type >=0x20 && type <=0x3f) { //subpicture; abase =0x20; } return (type-abase ); } streamType_t k9Cell::identifyStream( uchar *buffer,int *packetType ) { *packetType = buffer[17]; if( (*packetType >= 0xE0) && (*packetType <= 0xEF) ) { // video streams return stVideo; } else if( *packetType == 0xBB ) { // system header return stOther; } else if( *packetType == 0xBE ) { // padding return stOther; } else if( *packetType == 0xBF ) { // nav pack return stOther; } else if( (*packetType >= 0xC0) && (*packetType <= 0xDF) ) { // mpeg audio return stAudio; } else if( *packetType == 0xBD ) { // private stream, check content *packetType = buffer[23+buffer[22]]; if (( (*packetType >=0x80) && (*packetType <=0x8f)) || ((*packetType >=0xa0) && (*packetType <=0xa7)) || ((*packetType >=0xc0) && (*packetType <=0xdf))) return stAudio; if ( (*packetType >=0x20) && (*packetType <=0x3f)) return stSubpicture; return stOther; } else return stOther; } int k9Cell::isNavPack (uchar *_ptr) { uint32_t start_code; uchar *ptr=_ptr; if ((ptr [0]!=0) || (ptr [1] !=0) || (ptr [2] != 0x01) || (ptr [3] != 0xba)) return 0; if ((ptr [4] & 0xc0) != 0x40) return 0; // ptr += 14; start_code = (uint32_t) (ptr [14]) << 24; start_code |= (uint32_t) (ptr [15]) << 16; start_code |= (uint32_t) (ptr [16]) << 8; start_code |= (uint32_t) (ptr [17]); if (start_code != 0x000001bb) return 0; // ptr += 24; start_code = (uint32_t) (ptr [0x26]) << 24; start_code |= (uint32_t) (ptr [0x27]) << 16; start_code |= (uint32_t) (ptr [0x28]) << 8; start_code |= (uint32_t) (ptr [0x29]); if (start_code != 0x000001bf) return 0; // ptr += 986; start_code = (uint32_t) (ptr [0x400]) << 24; start_code |= (uint32_t) (ptr [0x401]) << 16; start_code |= (uint32_t) (ptr [0x402]) << 8; start_code |= (uint32_t) (ptr [0x403]); if (start_code != 0x000001bf) return 0; return 1; } k9Cell::k9Cell(TQObject *parent, const char *name) : TQObject(parent, name) { vobus.setAutoDelete(true); numVobu=0; vts=0; pgc=0; vob=0; startSector=0; lastSector=0; //TO REMOVE oldStartSector=0; //TO REMOVE oldLastSector=0; //TO REMOVE newSize=0; id=0; selected=false; copied=false; //TO REMOVE nbVideoNew=0; //TO REMOVE nbVideoOld=0; angleBlock=angleNone; } k9Cell::~k9Cell() {} //add a title in the title list (titles using this cell) void k9Cell::addTitle( k9DVDTitle *_title) { m_titles.append( _title); } bool k9Cell::getforceFactor() { bool m_forced=false; for (uint i=0; i< m_titles.count() && !m_forced ;i++) { k9DVDTitle *title=m_titles.at(i); if (title->getforceFactor()) m_forced=true; } return m_forced; } // returns the shrink factor. float k9Cell::getFactor() { float factor=0; for (uint i=0; i< m_titles.count() ;i++) { k9DVDTitle *title=m_titles.at(i); if ((title->getfactor()< factor || factor==0 ) && title->getforceFactor() ) factor=title->getfactor(); } return factor; } //looking for the end reference frame adress block void k9Cell::addRefStream(k9Vobu *_vobu,uchar *_buffer,uint32_t _position) { if (_vobu->firstRefOk && _vobu->secondRefOk && _vobu->thirdRefOk) return; //offset of frame uint start=0x16+_buffer[0x16]+1; //PES Length uint length=_buffer[0x12]; length=(length <<8 ) + _buffer[0x13]; //end of PES uint end=0x14+length; if ( _vobu->frameType!=0x18) { if (!_vobu->firstRefOk) _vobu->firstRef=_position; else if (!_vobu->secondRefOk) _vobu->secondRef=_position; else if (!_vobu->thirdRefOk) _vobu->thirdRef=_position; } for (uint i=start;i frameType!=0x18) && (_vobu->frameType!=0)) { if (!_vobu->firstRefOk) { _vobu->firstRefOk=true; _vobu->firstRef=_position; } else if (!_vobu->secondRefOk) { _vobu->secondRefOk=true; _vobu->secondRef=_position; } else if (!_vobu->thirdRefOk) { _vobu->thirdRefOk=true; _vobu->thirdRef=_position; } } //keep the current frame type _vobu->frameType=frameType; } } } k9Vobu * k9Cell::addVobu(uint32_t _sector) { k9Vobu * vobu = new k9Vobu(this,_sector); vobus.append(vobu); return vobu; } void k9Cell::addNewVobus(char *_buffer,uint32_t _len,uint32_t _position,int _vobNum,long _vobPos) { uint32_t start= _position ;//lastSector - _len ; k9Vobu *vobu; for (uint32_t i= 0 ; i<_len ;i+=DVD_BLOCK_LEN) { if (isNavPack((uchar*)_buffer+i)) { vobu=(k9Vobu*)vobus.at(numVobu); vobu->newSector=i/DVD_BLOCK_LEN +start; numVobu++; vobu->vobNum=_vobNum; vobu->vobPos=_vobPos; //TQString c; //c.sprintf("vobu : %d old: %d new :%d",numVobu-1,vobu->oldSector,vobu->newSector); //tqDebug (c.latin1()); } else { streamType_t st; int packetType,id; st=k9Cell::identifyStream((uchar*)_buffer+i,&packetType); vobu=(k9Vobu*)vobus.at(numVobu-1); switch (st) { case stAudio: id=k9Cell::getStreamID(packetType); if (vobu->firstAudio[id]==-1) { vobu->firstAudio[id]= ((i/ DVD_BLOCK_LEN) + start) - vobu->newSector; } break; case stSubpicture: id=k9Cell::getStreamID(packetType); if ((id >=0) && (id<32)) { if (vobu->firstSubp[id]==-1) { vobu->firstSubp[id]= ((i / DVD_BLOCK_LEN)+start) - vobu->newSector; } } break; case stVideo: addRefStream(vobu,(uchar*)_buffer+i,(i/DVD_BLOCK_LEN +start) - vobu->newSector); if (vobu->firstVideo==-1) { vobu->firstVideo = ((i / DVD_BLOCK_LEN)+start) - vobu->newSector; } //TO REMOVE nbVideoNew++; break; } } vobu->size= _position-vobu->newSector; // �v�ifier lastSector=_position; } } k9Vobu::k9Vobu(k9Cell *_parent,uint32_t _oldSector) : TQObject(_parent,"") { parent=_parent; oldSector = _oldSector; newSector = 0; size=0; for (int i=0;i<8;i++) firstAudio[i]=-1; for (int i=0;i<32;i++) firstSubp[i]=-1; firstVideo=-1; empty=false; vobPos=0; vobNum=0; frameType=0; firstRef=0; secondRef=0; thirdRef=0; firstRefOk=false; secondRefOk=false; thirdRefOk=false; } /*! \fn k9Cell::findVobu(int _oldSector) */ k9Vobu * k9Cell::findVobu(uint32_t _oldSector) { return vobus.findVobu(_oldSector) ; } k9Vobu::~k9Vobu() {} k9Cell* k9CellList::addCell(int _vts,int _pgc, int _vob) { k9Cell* cell=new k9Cell; cell->cellList=this; cell->vts=_vts; cell->vob=_vob; cell->pgc=_pgc; if (count()!=0) { k9Cell *prev=(k9Cell*)getLast(); if (prev->vts==_vts) { cell->startSector= prev->lastSector +1; if (_pgc!=prev->pgc) cell->id=1; else cell->id=prev->id+1; } } else { cell->startSector = 0; cell->id=1; } append (cell); return(cell); } k9Vobu *k9CellList::findVobu(uint32_t sector) { k9Vobu *vobu=NULL; k9Cell *cell=findCell(sector); if (cell==NULL) return NULL; else return cell->findVobu(sector); int nbCells=count(); for (int i=0;i findVobu(sector); if (vobu !=NULL) { return vobu; } cell = (k9Cell*)at(nbCells-1-i); vobu = cell->findVobu(sector); if (vobu !=NULL) { return vobu; } } return vobu; } k9Cell * k9CellList::findCell(uint32_t sector) { return findCell(sector,0,count()-1); } k9Cell * k9CellList::findCell(uint32_t sector, uint32_t start, uint32_t end) { long lstart=start; long lend=end; while (lstart <=lend) { long m =(lstart+lend)/2; k9Cell *cell = (k9Cell *)at(m); k9Vobu *fv=cell->vobus.first(); k9Vobu *lv=cell->vobus.last(); if ( sector >=fv->oldSector && sector<= lv->oldSector) { return cell; } else if ( fv->oldSector >sector) { lend = m-1; } else { lstart=m+1; } } return NULL; } k9DVDTitleset * k9Cell::getTitleset() { k9DVDTitle *title=m_titles.at(0); return title->gettitleset(); } #include "k9cell.moc"