[Matroska-cvs] [matroska] r1292 - in trunk/DvdMenuXtractor/dmx: .
vobparser vobparser/iso
smssms at matroska.org
smssms at matroska.org
Sat Mar 10 22:46:31 CET 2007
Author: smssms
Date: 2007-03-11 00:46:03 +0300 (Sun, 11 Mar 2007)
New Revision: 1292
Added:
trunk/DvdMenuXtractor/dmx/vobparser/
trunk/DvdMenuXtractor/dmx/vobparser/IFOContent.cpp
trunk/DvdMenuXtractor/dmx/vobparser/IFOContent.h
trunk/DvdMenuXtractor/dmx/vobparser/IFOFile.cpp
trunk/DvdMenuXtractor/dmx/vobparser/IFOFile.h
trunk/DvdMenuXtractor/dmx/vobparser/VobParser.cpp
trunk/DvdMenuXtractor/dmx/vobparser/VobParser.h
trunk/DvdMenuXtractor/dmx/vobparser/iso/
trunk/DvdMenuXtractor/dmx/vobparser/iso/iso-639.def
trunk/DvdMenuXtractor/dmx/vobparser/iso/iso_lang.c
trunk/DvdMenuXtractor/dmx/vobparser/iso/iso_lang.h
trunk/DvdMenuXtractor/dmx/vobparser/vobparser.proj
Log:
Added: trunk/DvdMenuXtractor/dmx/vobparser/IFOContent.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx/vobparser/IFOContent.cpp 2007-03-10 21:45:2=
8 UTC (rev 1291)
+++ trunk/DvdMenuXtractor/dmx/vobparser/IFOContent.cpp 2007-03-10 21:46:0=
3 UTC (rev 1292)
@@ -0,0 +1,273 @@
+// ---------------------------------------------------------------------=
-------
+#include "IFOContent.h"
+// ---------------------------------------------------------------------=
-------
+// Macro to convert Binary Coded Decimal to Decimal
+#define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f))
+// ---------------------------------------------------------------------=
-------
+int dvdtime2frame(dvd_time_t* dtime, double & frame_dur)
+{
+ double frame_rate;
+ double result =3D 0.0;
+ assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa);
+ assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa);
+ assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa);
+ assert((dtime->frame_u&0xf) < 0xa);
+
+ int hh, min, sec, ff;
+ hh =3D BCD2D(dtime->hour);
+ min =3D BCD2D(dtime->minute);
+ sec =3D BCD2D(dtime->second);
+ ff =3D BCD2D(dtime->frame_u & 0x3f);
+
+ frame_rate =3D ((dtime->frame_u & 0xc0) >> 6) =3D=3D 1 ? 25.0 : (30000.=
0/1001.0);
+ result =3D (((((hh * 60) + min) * 60) + sec) * frame_rate) + (ff & 0x3f=
);
+ frame_dur =3D 1000.0 / frame_rate;
+
+ return (int)result;
+}
+// ---------------------------------------------------------------------=
-------
+IFOContent::IFOContent(dvd_reader_t *dvdr, int16_t title)
+ :m_title(title)
+{
+ m_handle =3D ifoOpen(dvdr, title);
+ if (!m_handle)
+ throw IFOInvalidFileFormatException();
+
+ CellsHashType CellsHash;
+
+ if (title =3D=3D 0)
+ {
+ if (m_handle->vmgi_mat)
+ {
+ const vmgi_mat_t &vmgi_mat =3D *m_handle->vmgi_mat;
+ if (vmgi_mat.nr_of_vmgm_audio_streams)
+ m_langAudio.push_back(&vmgi_mat.vmgm_audio_attr);
+ if (vmgi_mat.nr_of_vmgm_subp_streams)
+ m_langSubs.push_back(&vmgi_mat.vmgm_subp_attr);
+ }
+
+ if (m_handle->pgci_ut && m_handle->menu_c_adt)
+ {
+ // add each cell in a list
+ // order this list according to vob ID, cell ID
+ // for each cell, find the duration (and start time) from all menu PG=
Cs
+ for(uint16_t i =3D 0; i < m_handle->pgci_ut->nr_of_lus; i++)
+ {
+ pgci_lu_t& lu =3D m_handle->pgci_ut->lu[i];
+ GetPGCCells(*lu.pgcit, *m_handle->menu_c_adt, &CellsHash);
+ }
+
+ // Transfer hash map to the list to be sorted
+ m_langCellsList.clear();
+ =09
+ for(CellsHashType::iterator it =3D CellsHash.begin(); it !=3D CellsHa=
sh.end(); ++it )
+ {
+ m_langCellsList.append(it.value());
+ }
+
+ m_langCellsList.arrange();
+ }
+ }
+ else
+ {
+ if (m_handle->vtsi_mat)
+ {
+ const vtsi_mat_t & vtsi_mat =3D *m_handle->vtsi_mat;
+ if (vtsi_mat.nr_of_vtsm_audio_streams)
+ m_langAudio.push_back(&vtsi_mat.vtsm_audio_attr);
+ if (vtsi_mat.nr_of_vtsm_subp_streams)
+ m_langSubs.push_back(&vtsi_mat.vtsm_subp_attr);
+
+ uint8_t _stream;
+ for (_stream=3D0; _stream < vtsi_mat.nr_of_vts_audio_streams; _stream=
++)
+ m_Audio.push_back(&vtsi_mat.vts_audio_attr[_stream]);
+ for (_stream=3D0; _stream < vtsi_mat.nr_of_vts_subp_streams; _stream+=
+)
+ m_Subs.push_back(&vtsi_mat.vts_subp_attr[_stream]);
+ }
+
+ // handle the list of menu cells with their ID and sectors
+ CellsHash.clear();
+ if (m_handle->pgci_ut && m_handle->menu_c_adt)
+ {
+ // add each cell in a list
+ // order this list according to vob ID, cell ID
+ // for each cell, find the duration (and start time) from all menu PG=
Cs
+ for(int i =3D 0; i < m_handle->pgci_ut->nr_of_lus; i++)
+ {
+ pgci_lu_t& lu =3D m_handle->pgci_ut->lu[i];
+ GetPGCCells(*lu.pgcit, *m_handle->menu_c_adt, &CellsHash);
+ }
+
+ // Transfer hash map to the list to be sorted
+ m_langCellsList.clear();
+ CellsHashType::iterator it;
+ for( it =3D CellsHash.begin(); it !=3D CellsHash.end(); ++it )
+ {
+ m_langCellsList.append(it.value());
+ }
+
+ m_langCellsList.arrange();
+ }
+
+ // handle the list of cells with their ID and sectors
+ CellsHash.clear();
+ if (m_handle->vts_pgcit && m_handle->vts_c_adt)
+ {
+ // add each cell in a list
+ // order this list according to vob ID, cell ID
+ // for each cell, find the duration (and start time) from all PGCs
+ GetPGCCells(*m_handle->vts_pgcit, *m_handle->vts_c_adt, &CellsHash);
+
+ // Transfer hash map to the list to be sorted
+ m_CellsList.clear();
+ =09
+ for(CellsHashType::iterator it =3D CellsHash.begin(); it !=3D CellsHa=
sh.end(); ++it )
+ {
+ m_CellsList.append(it.value());
+ }
+
+ m_CellsList.arrange();
+ }
+ }
+}
+// ---------------------------------------------------------------------=
-------
+void IFOContent::GetPGCCells(const pgcit_t & pgcit, const c_adt_t & adt,=
CellsHashType * CellsHash)
+{
+ CellListElem* cle;
+
+ for(int j=3D0; j < pgcit.nr_of_pgci_srp; j++)
+ {
+ pgci_srp_t& srp =3D pgcit.pgci_srp[j];
+ for(int k=3D0; k < srp.pgc->nr_of_cells; k++)
+ {
+ uint16_t vob_id =3D srp.pgc->cell_position[k].vob_id_nr;
+ uint8_t cell_id =3D srp.pgc->cell_position[k].cell_nr;
+
+ if (CellsHash->find(MAKE_CELLS_KEY(vob_id, cell_id)) =3D=3D CellsHash=
->end())
+ {
+ size_t cell_nr =3D adt.last_byte;
+ cell_nr -=3D 7;
+ cell_nr /=3D sizeof(cell_adr_t);
+ for (size_t l=3D0; l < cell_nr; l++)
+ {
+ if (adt.cell_adr_table[l].vob_id =3D=3D vob_id && adt.cell_adr_tabl=
e[l].cell_id =3D=3D cell_id)
+ {
+ cle =3D new CellListElem();
+ (*CellsHash)[MAKE_CELLS_KEY(vob_id, cell_id)] =3D cle;
+
+ cle->vobid =3D vob_id;
+ cle->cellid =3D cell_id;
+
+ cle->start_sector =3D adt.cell_adr_table[l].start_sector;
+ cle->last_sector =3D adt.cell_adr_table[l].last_sector;
+ cle->selected =3D true; // all cells selected for the moment
+ cle->found =3D false;
+ /* debug * / cle->found =3D true;*/
+
+ cle->nb_frames =3D dvdtime2frame(&srp.pgc->cell_playback[k].playba=
ck_time, cle->frame_dur);
+ cle->isStill =3D (srp.pgc->cell_playback[k].still_time > 0);
+ if (cle->isStill)
+ {
+ if (srp.pgc->cell_playback[k].still_time =3D=3D 0xFF) {
+ qWarning(qPrintable(QString("Still cell (%1.%2) detected with i=
nfinite duration !").arg(vob_id).arg(cell_id)));
+ } else {
+ qWarning(qPrintable(QString("Still cell (%1.%2) detected. Assum=
ing there is just one frame.").arg(vob_id).arg(cell_id)));
+ cle->nb_frames =3D 1; // maybe not true ?
+ cle->frame_dur =3D srp.pgc->cell_playback[k].still_time * 1000.0=
/ cle->nb_frames;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+// ---------------------------------------------------------------------=
-------
+uint8_t IFOContent::FindAudioStream(uint8_t streamID, bool menu) const
+{
+ assert(m_handle !=3D NULL);
+ if (menu)
+ {
+ if (m_handle->pgci_ut)
+ {
+ for (int i=3D0; i<m_handle->pgci_ut->nr_of_lus; i++)
+ {
+ pgci_lu_t &_lu =3D m_handle->pgci_ut->lu[i];
+ for (int j=3D0; j < _lu.pgcit->nr_of_pgci_srp; j++)
+ {
+ pgc_t *_pgc =3D _lu.pgcit->pgci_srp[j].pgc;
+ if(_pgc->audio_control[streamID] & 0x8000) // if present
+ return (_pgc->audio_control[streamID] >> 8) & 0x7F;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (m_handle->vts_pgcit)
+ {
+ for (int j=3D0; j < m_handle->vts_pgcit->nr_of_pgci_srp; j++)
+ {
+ pgc_t *_pgc =3D m_handle->vts_pgcit->pgci_srp[j].pgc;
+ if(_pgc->audio_control[streamID] & 0x8000) // if present
+ return (_pgc->audio_control[streamID] >> 8) & 0x7F;
+ }
+ }
+ }
+ return streamID;
+}
+// ---------------------------------------------------------------------=
-------
+IdArray IFOContent::FindSubStream(uint8_t streamID, bool menu) const
+{
+ IdArray result;
+
+ assert(m_handle !=3D NULL);
+ if (menu)
+ {
+ if (m_handle->pgci_ut)
+ {
+ for (int i=3D0; i<m_handle->pgci_ut->nr_of_lus; i++)
+ {
+ pgci_lu_t &_lu =3D m_handle->pgci_ut->lu[i];
+ for (int j=3D0; j < _lu.pgcit->nr_of_pgci_srp; j++)
+ {
+ pgc_t *_pgc =3D _lu.pgcit->pgci_srp[j].pgc;
+ if(_pgc->subp_control[streamID] & 0x80000000) // if present
+ {
+ result.push_back( _pgc->subp_control[streamID] >> 24 & 0x7F);
+ if (_pgc->subp_control[streamID] & 0x007F0000)
+ result.push_back( _pgc->subp_control[streamID] >> 16 & 0x7F);
+ if (_pgc->subp_control[streamID] & 0x00007F00)
+ result.push_back( _pgc->subp_control[streamID] >> 8 & 0x7F);
+ if (_pgc->subp_control[streamID] & 0x0000007F)
+ result.push_back( _pgc->subp_control[streamID] >> 0 & 0x7F);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (m_handle->vts_pgcit)
+ {
+ for (int j=3D0; j < m_handle->vts_pgcit->nr_of_pgci_srp; j++)
+ {
+ pgc_t *_pgc =3D m_handle->vts_pgcit->pgci_srp[j].pgc;
+ if(_pgc->subp_control[streamID] & 0x80000000) // if present
+ {
+ result.push_back( _pgc->subp_control[streamID] >> 24 & 0x7F);
+ if (_pgc->subp_control[streamID] & 0x007F0000)
+ result.push_back( _pgc->subp_control[streamID] >> 16 & 0x7F);
+ if (_pgc->subp_control[streamID] & 0x00007F00)
+ result.push_back( _pgc->subp_control[streamID] >> 8 & 0x7F);
+ if (_pgc->subp_control[streamID] & 0x0000007F)
+ result.push_back( _pgc->subp_control[streamID] >> 0 & 0x7F);
+ }
+ }
+ }
+ }
+
+ return result;
+}
+// ---------------------------------------------------------------------=
-------
Added: trunk/DvdMenuXtractor/dmx/vobparser/IFOContent.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx/vobparser/IFOContent.h 2007-03-10 21:45:28 =
UTC (rev 1291)
+++ trunk/DvdMenuXtractor/dmx/vobparser/IFOContent.h 2007-03-10 21:46:03 =
UTC (rev 1292)
@@ -0,0 +1,71 @@
+// ---------------------------------------------------------------------=
-------
+#ifndef _IFO_CONTENT_H_
+#define _IFO_CONTENT_H_
+// ---------------------------------------------------------------------=
-------
+#include <QHash>
+#include <vector>
+
+#include "VobParser.h"
+#include "dvdread/ifo_read.h"
+// ---------------------------------------------------------------------=
-------
+typedef std::vector<uint8_t> IdArray;
+
+typedef QHash<int, CellListElem *> CellsHashType;
+typedef std::vector<const audio_attr_t*> AudioTrackList;
+typedef std::vector<const subp_attr_t*> SubtitleTrackList;
+
+#define MAKE_CELLS_KEY(vob_id,cell_id) ((vob_id << 8) | cell_id)
+// ---------------------------------------------------------------------=
-------
+class IFOException { };
+class IFOFileIOException : public IFOException { };
+class IFOInvalidFileFormatException : public IFOException { };
+// ---------------------------------------------------------------------=
-------
+typedef QList<CellListElem*> CellsListBaseType;
+class CellsListType : public CellsListBaseType
+{
+public:
+ void arrange();
+ CellListElem* at(uint16_t vob_id, uint8_t cell_id) const;
+ const CellListElem* at(const cell_position_t & position) const;
+
+ // comperator for qSort()
+ static int cellListElemCompare(const CellListElem *arg1, const CellList=
Elem *arg2);
+};
+// ---------------------------------------------------------------------=
-------
+class IFOContent=20
+{
+public:
+ IFOContent(dvd_reader_t *dvdr, int16_t title);
+
+ ~IFOContent()
+ {
+ ifoClose(m_handle);
+ m_CellsList.clear();
+ m_langCellsList.clear();
+ }
+
+ ifo_handle_t& Handle()
+ {
+ assert(m_handle !=3D NULL);
+ return *m_handle;
+ }
+
+ IdArray FindSubStream(uint8_t streamID, bool menu) const;
+ uint8_t FindAudioStream(uint8_t streamID, bool menu) const;
+=09
+ void GetPGCCells(const pgcit_t & pgcit, const c_adt_t & adt, CellsHashT=
ype * CellsHash);
+
+ int16_t m_title;
+ AudioTrackList m_langAudio;
+ AudioTrackList m_Audio;
+ SubtitleTrackList m_langSubs;
+ SubtitleTrackList m_Subs;
+ CellsListType m_CellsList;
+ CellsListType m_langCellsList;
+
+protected:
+ ifo_handle_t *m_handle;
+};
+// ---------------------------------------------------------------------=
-------
+#endif
+// ---------------------------------------------------------------------=
-------
Added: trunk/DvdMenuXtractor/dmx/vobparser/IFOFile.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx/vobparser/IFOFile.cpp 2007-03-10 21:45:28 U=
TC (rev 1291)
+++ trunk/DvdMenuXtractor/dmx/vobparser/IFOFile.cpp 2007-03-10 21:46:03 U=
TC (rev 1292)
@@ -0,0 +1,300 @@
+// ---------------------------------------------------------------------=
-------
+#include "IFOFile.h"
+#include "iso/iso_lang.h"
+#include "dvdread/ifo_print.h"
+// ---------------------------------------------------------------------=
-------
+IFOFile::IFOFile(const QString& filename)
+{=09
+ m_dvd =3D DVDOpen(QFile::encodeName(filename));
+=09
+ if(!m_dvd) {
+ throw IFOInvalidFileFormatException();
+ }
+
+ try {
+ m_ifos.append(new IFOContent(m_dvd, 0)); =09
+ }
+ catch (...) {
+ qCritical("Cannot open VIDEO_TS.IFO.");
+ throw;
+ }
+
+ IFOContent *_ifo =3D m_ifos.getIfoContent(0);
+
+ if (_ifo && _ifo->Handle().vmgi_mat)
+ {
+ for (int i =3D 1; i <=3D _ifo->Handle().vmgi_mat->vmg_nr_of_title_sets=
; i++)
+ {
+ try {
+ m_ifos.append(new IFOContent(m_dvd,i));
+ }
+ catch (...) {
+ qCritical(qPrintable(QString("Cannot open VTS_%1_X.IFO").arg(i)));
+ }
+ }
+ }
+}
+// ---------------------------------------------------------------------=
-------
+IFOFile::~IFOFile()
+{
+ for (int i =3D 0; i < m_ifos.size(); i++)
+ delete m_ifos.at(i);
+=09
+ if (m_dvd)
+ {
+ DVDClose(m_dvd);
+ }
+}
+// ---------------------------------------------------------------------=
-------
+const pgc_t *IFOFile::FirstPlayPGC() const
+{
+ if (m_ifos.at(0))
+ return m_ifos.at(0)->Handle().first_play_pgc;
+ else
+ return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const tt_srpt_t *IFOFile::TitleMap() const
+{
+ if (m_ifos.at(0))
+ return m_ifos.at(0)->Handle().tt_srpt;
+ else
+ return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const pgci_ut_t *IFOFile::LanguageUnits(unsigned int title) const
+{
+ IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+=09
+ if (_ifo)
+ return _ifo->Handle().pgci_ut;
+ =09
+ return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const vts_ptt_srpt_t *IFOFile::VtsTitles(unsigned int title) const
+{
+ IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+ if (_ifo)
+ {
+ return _ifo->Handle().vts_ptt_srpt;
+ }
+ return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const pgcit_t *IFOFile::VtsPGCs(unsigned int title) const
+{
+ IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+ if (_ifo)
+ {
+ return _ifo->Handle().vts_pgcit;
+ }
+ return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const int16_t IFOFile::NumberOfTitles() const
+{
+ if (m_ifos.count() && m_ifos.at(0)->Handle().vmgi_mat)
+ return m_ifos.at(0)->Handle().vmgi_mat->vmg_nr_of_title_sets;
+ return 0;
+}
+// ---------------------------------------------------------------------=
-------
+int CellsListType::cellListElemCompare(const CellListElem *arg1, const C=
ellListElem *arg2)
+{
+ const CellListElem* cle1 =3D arg1;
+ const CellListElem* cle2 =3D arg2;
+
+ return (cle1->vobid > cle2->vobid) ? 1 :
+ (cle1->vobid < cle2->vobid) ? -1 :
+ (cle1->cellid > cle2->cellid) ? 1 :=20
+ (cle1->cellid < cle2->cellid) ? -1 :
+ 0;
+}
+// ---------------------------------------------------------------------=
-------
+const CellsListType* IFOFile::GetCellsList(unsigned int title, bool menu=
)
+{
+ CellsHashType CellsHash;
+
+ IFOContent *ifoc =3D m_ifos.getIfoContent(title);
+ if (!ifoc)
+ return NULL;
+
+ if (menu)
+ return &ifoc->m_langCellsList;
+ else
+ return &ifoc->m_CellsList;
+}
+// ---------------------------------------------------------------------=
-------
+const AudioTrackList & IFOFile::AudioTracks(unsigned int title, bool men=
u) const
+{
+ IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+ if (!_ifo)
+ throw;
+
+ if (menu)
+ return _ifo->m_langAudio;
+ else
+ return _ifo->m_Audio;
+}
+// ---------------------------------------------------------------------=
-------
+const SubtitleTrackList & IFOFile::SubsTracks(unsigned int title, bool m=
enu) const
+{
+ IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+ if (!_ifo)
+ throw;
+
+ if (menu)
+ return _ifo->m_langSubs;
+ else
+ return _ifo->m_Subs;
+}
+// ---------------------------------------------------------------------=
-------
+const CellsListType & IFOFile::CellsList(unsigned int title, bool menu) =
const
+{
+ IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+ if (!_ifo)
+ throw;
+
+ if (menu)
+ return _ifo->m_langCellsList;
+ else
+ return _ifo->m_CellsList;
+}
+// ---------------------------------------------------------------------=
-------
+bool IFOFile::VideoSize(unsigned int title, bool menu, uint16_t & width,=
uint16_t & height, double & fps) const
+{
+ IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+ assert(_ifo !=3D NULL);
+ video_attr_t *_attr =3D NULL;
+ if (menu)
+ {
+ if (title =3D=3D 0)
+ {
+ if (_ifo->Handle().vmgi_mat)
+ {
+ _attr =3D &_ifo->Handle().vmgi_mat->vmgm_video_attr;
+ }
+ }
+ else
+ {
+ if (_ifo->Handle().vtsi_mat)
+ {
+ _attr =3D &_ifo->Handle().vtsi_mat->vtsm_video_attr;
+ }
+ }
+ }
+ else
+ {
+ if (_ifo->Handle().vtsi_mat)
+ {
+ _attr =3D &_ifo->Handle().vtsi_mat->vts_video_attr;
+ }
+ }
+
+ if (_attr !=3D NULL)
+ {
+ height =3D 480;
+ if(_attr->video_format !=3D 0) {
+ fps =3D 25.0;
+ height =3D 576;
+ } else {
+ fps =3D 30000.0/1001.0;
+ }
+ switch(_attr->picture_size) {
+ case 0:
+ width =3D 720;
+ break;
+ case 1:
+ width =3D 704;
+ break;
+ case 2:
+ width =3D 352;
+ break;
+ case 3:
+ width =3D 352;
+ height >>=3D 1;
+ break; =20
+ }
+ return true;
+ }
+ return false;
+}
+// ---------------------------------------------------------------------=
-------
+const uint32_t * IFOFile::GetPalette(unsigned int title, bool menu) cons=
t
+{
+ IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+ assert(_ifo !=3D NULL);
+=09
+ if (menu)
+ return (_ifo->Handle().pgci_ut->lu->pgcit->pgci_srp->pgc->palette);
+=09
+ return (_ifo->Handle().vts_pgcit->pgci_srp->pgc->palette);
+}
+// ---------------------------------------------------------------------=
-------
+uint8_t IFOFile::GetAudioId(uint8_t streamID, uint8_t title, bool menu) =
const
+{
+ IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+ if (!_ifo)
+ throw;
+
+ return _ifo->FindAudioStream(streamID, menu);
+}
+// ---------------------------------------------------------------------=
-------
+IdArray IFOFile::GetSubsId(uint8_t streamID, uint8_t title, bool menu) c=
onst
+{
+ IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+ if (!_ifo)
+ throw;
+
+ return _ifo->FindSubStream(streamID, menu);
+}
+// ---------------------------------------------------------------------=
-------
+IFOContent * IfoHandleList::getIfoContent(int16_t title) const
+{
+ for (size_type _index =3D 0; _index < size(); _index++)
+ {
+ if (at(_index)->m_title =3D=3D title)
+ return at(_index);
+ }
+ return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const CellListElem* CellsListType::at(const cell_position_t & position) =
const
+{
+ return at(position.vob_id_nr, position.cell_nr);
+}
+// ---------------------------------------------------------------------=
-------
+CellListElem* CellsListType::at(uint16_t vob_id, uint8_t cell_id) const
+{
+ CellsListType::const_iterator node =3D begin();
+ while (node !=3D end())
+ {
+ CellListElem *cell =3D *node;
+ =09
+ if (cell->cellid =3D=3D cell_id && cell->vobid =3D=3D vob_id)
+ return cell;
+ =09
+ ++node;
+ }
+=09
+ return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+void CellsListType::arrange()
+{
+ qSort(begin(), end(), &CellsListType::cellListElemCompare);
+
+ // make the timecodes continuous
+ int64_t timecode =3D 0;
+ CellsListType::const_iterator node =3D begin();
+ while (node !=3D end())
+ {
+ CellListElem *cell =3D *node;
+ cell->start_time =3D timecode;
+ cell->duration =3D int64_t(cell->frame_dur * cell->nb_frames * 1000000=
.0);
+ if (cell->found)
+ timecode +=3D cell->duration;
+ ++node;
+ }
+}
+// ---------------------------------------------------------------------=
-------
Added: trunk/DvdMenuXtractor/dmx/vobparser/IFOFile.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx/vobparser/IFOFile.h 2007-03-10 21:45:28 UTC=
(rev 1291)
+++ trunk/DvdMenuXtractor/dmx/vobparser/IFOFile.h 2007-03-10 21:46:03 UTC=
(rev 1292)
@@ -0,0 +1,43 @@
+// ---------------------------------------------------------------------=
-------
+#ifndef _IFO_FILE_H_
+#define _IFO_FILE_H_
+// ---------------------------------------------------------------------=
-------
+#include <QStringList>
+
+#include "IFOContent.h"
+// ---------------------------------------------------------------------=
-------
+class IfoHandleList: public QList<IFOContent*>
+{
+public:
+ /// look for IfoContent corresponding to the title
+ IFOContent* getIfoContent(int16_t title) const;
+};
+// ---------------------------------------------------------------------=
-------
+class IFOFile =20
+{
+public:
+ IFOFile(const QString& filename);
+ const CellsListType* GetCellsList(unsigned int title, bool menu);
+ virtual ~IFOFile();
+ const pgc_t *FirstPlayPGC() const;
+ const tt_srpt_t *TitleMap() const;
+ const pgci_ut_t *LanguageUnits(unsigned int title) const;
+ const vts_ptt_srpt_t *VtsTitles(unsigned int title) const;
+ const pgcit_t *VtsPGCs(unsigned int title) const;
+ const int16_t NumberOfTitles() const;
+ const AudioTrackList & AudioTracks(unsigned int title, bool menu) const=
;
+ const SubtitleTrackList & SubsTracks(unsigned int title, bool menu) con=
st;
+ const CellsListType & CellsList(unsigned int title, bool menu) const;
+ bool VideoSize(unsigned int title, bool menu, uint16_t & width, uint16_=
t & height, double & fps) const;
+ const uint32_t * GetPalette(unsigned int title, bool menu) const;
+
+ uint8_t GetAudioId(uint8_t streamID, uint8_t title, bool menu) const;
+ IdArray GetSubsId(uint8_t streamID, uint8_t title, bool menu) const;
+
+private:
+ IfoHandleList m_ifos;
+ dvd_reader_t* m_dvd;
+};
+// ---------------------------------------------------------------------=
-------
+#endif
+// ---------------------------------------------------------------------=
-------
Added: trunk/DvdMenuXtractor/dmx/vobparser/VobParser.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx/vobparser/VobParser.cpp 2007-03-10 21:45:28=
UTC (rev 1291)
+++ trunk/DvdMenuXtractor/dmx/vobparser/VobParser.cpp 2007-03-10 21:46:03=
UTC (rev 1292)
@@ -0,0 +1,1351 @@
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// VOBParser class
+// Copyright =A9 2002 : Christophe PARIS (christophe.paris at free.fr)
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+#include <QFileInfo>
+
+#include "IFOFile.h"
+#include "VobParser.h"
+#include "iso/iso_lang.h"
+
+// ---------------------------------------------------------------------=
-------
+
+#define VOB_SLICE 0x00000100
+#define PACK_HEADER 0xBA
+#define SYSTEM_HEADER 0xBB
+#define PROGRAM_STREAM_MAP 0xBC
+#define PRIVATE_STREAM1 0xBD
+#define PADDING_STREAM 0xBE
+#define PRIVATE_STREAM2 0xBF
+#define CURRENT_OFFSET (m_pktindex * DVD_VIDEO_LB_LEN + m_index)
+
+#define INDENT_UNIT 2
+unsigned int indent_lvl =3D 0;
+inline void inc_lvl() { indent_lvl +=3D INDENT_UNIT; }
+inline void dec_lvl() { indent_lvl -=3D INDENT_UNIT; }
+void debug (const QString& str)
+{
+ QString debugStr (indent_lvl, ' ');
+ debugStr +=3D str;
+ qDebug(qPrintable(debugStr));
+}
+
+// ---------------------------------------------------------------------=
-------
+// CompositeDemuxWriter
+// ---------------------------------------------------------------------=
-------
+
+CompositeDemuxWriter::CompositeDemuxWriter()
+{
+ for (int i=3D0; i<256; i++)
+ m_muxers[i] =3D NULL;
+}
+
+CompositeDemuxWriter::~CompositeDemuxWriter()
+{
+ Reset();
+}
+
+bool CompositeDemuxWriter::AddDemuxer(uint8_t streamID, Writer * demuxer=
, QString& CommandLine)
+{
+ if (m_muxers[streamID] !=3D NULL)
+ return false;
+ m_muxers[streamID] =3D demuxer;
+ m_strings[streamID] =3D CommandLine;
+ return true;
+}
+
+void CompositeDemuxWriter::ProcessStream(int streamID, uint8_t* buff, ui=
nt32_t size, int32_t start_time, int32_t end_time, const QString& debug)
+{
+ if (m_muxers[streamID] !=3D NULL)
+ m_muxers[streamID]->ProcessStream(buff, size, start_time, end_time, de=
bug);
+}
+
+void CompositeDemuxWriter::Reset()
+{
+ for (int i=3D0; i<256; i++)
+ {
+ if (m_muxers[i] !=3D NULL)
+ {
+ delete m_muxers[i];
+ m_muxers[i] =3D NULL;
+ }
+ }
+}
+
+void CompositeDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t=
duration, const CellListElem *cell)
+{
+ for (int i=3D0; i<256; i++)
+ {
+ if (m_muxers[i] !=3D NULL)
+ {
+ m_muxers[i]->SetBoundary(start_timecode, duration, cell);
+ }
+ }
+}
+
+// ---------------------------------------------------------------------=
-------
+
+VobParser::VobParser(const char* dirname, int16_t title, bool menu)
+ :m_title(title)
+ ,m_dvdhandle(NULL)
+ ,m_stream(NULL)
+ ,m_language(menu)
+ ,m_bFirstPacket(true)
+{
+ m_pktcount =3D 0;
+
+ QFileInfo _tmpDirName(dirname);
+
+ // handle all parts of this title (VIDEO_TS.vob or VTS_XX_Y.vob)
+ m_dvdhandle =3D DVDOpen(QFile::encodeName(_tmpDirName.canonicalPath()))=
;
+
+ if (m_dvdhandle)
+ {
+ if (m_language)
+ m_stream =3D DVDOpenFile(m_dvdhandle, title, DVD_READ_MENU_VOBS);
+ else
+ m_stream =3D DVDOpenFile(m_dvdhandle, title, DVD_READ_TITLE_VOBS);
+ }
+
+ if(!m_stream)
+ {
+ throw VobParserFileNotFoundException(dirname);
+ }
+ else
+ {
+ m_pktcount =3D DVDFileSize(m_stream);
+ }
+
+ Reset();
+}
+
+// ---------------------------------------------------------------------=
-------
+
+VobParser::~VobParser()
+{
+ if (m_stream)
+ DVDCloseFile(m_stream);
+
+ if (m_dvdhandle)
+ DVDClose(m_dvdhandle);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint32_t VobParser::GetPacketCount() const
+{
+ return m_pktcount;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint32_t VobParser::GetPacketIndex() const
+{
+ return m_pktindex;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+char* VobParser::GetCurrentPacketData() const
+{
+ return (char*)m_buff;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+bool VobParser::ParseNextPacket(const CellsListType & Cells)
+{
+ if(GetNextPacket())
+ {=09
+ pktinfo.identifier =3D GetNext32Bits();
+ if((pktinfo.identifier & VOB_SLICE) !=3D VOB_SLICE || (pktinfo.identif=
ier & PACK_HEADER) !=3D PACK_HEADER)
+ {
+ // Invalid block start code
+ throw VobParserInvalidPacketException(CURRENT_OFFSET-4);
+ }
+ =09
+ ParseSCR(); // System Clock Reference
+
+ // Program Mux Rate (measured in units of 50 bytes/second)
+ pktinfo.program_mux_rate =3D (GetNext8Bits() << 14) |=20
+ (GetNext8Bits() << 6) | (GetNext8Bits() >> 2);
+
+ // Skip Pack stuffing length
+ int stuffing_nb =3D GetNext8Bits() & 0x07;
+ SkipNBytes(stuffing_nb);
+ =09
+ uint32_t _Header =3D GetNext32Bits();
+ int _StreamID;
+ if ((_Header & VOB_SLICE) =3D=3D VOB_SLICE)
+ {
+ _StreamID =3D _Header & 0xFF;
+ if (_StreamID =3D=3D SYSTEM_HEADER)
+ {
+ // skip the system header data
+ uint16_t _size =3D GetNext16Bits();
+ SkipNBytes(_size);
+
+ while (AvailablePacketData())
+ {
+ _Header =3D GetNext32Bits();
+ uint8_t _StreamId =3D _Header & 0xFF;
+ if (_StreamId =3D=3D PRIVATE_STREAM2)
+ {
+ debug("Navigation pack {\n");
+ inc_lvl();
+ debug(QString("SCR: %1.%2\n").arg(pktinfo.scr).arg(pktinfo.scr_ext=
));
+ debug(QString("Program mux rate: %1 (%2 bps)\n").arg(pktinfo.progr=
am_mux_rate).arg(pktinfo.program_mux_rate * 50 * 8));
+ ParseNavPacket();
+ dec_lvl();
+ debug("}\n");
+ }
+ else
+ {
+ // skip these data
+ uint16_t _size =3D GetNext16Bits();
+ SkipNBytes(_size);
+ }
+ }
+ if (IsNewCell()) {
+ CellListElem* cell =3D Cells.at(GetVobID(), GetCellID());
+
+ if (cell !=3D NULL)
+ {
+ cell->found =3D true;
+ if (m_dsi.nv_pck_scr =3D=3D 0)
+ m_pci_vob_timecode_offset =3D m_pci.vobu_s_ptm / 90;
+ m_demuxer.SetBoundary(m_pci.vobu_s_ptm/90 - m_pci_vob_timecode_off=
set, cell->nb_frames * cell->frame_dur, cell);
+ }
+ }
+ if (m_pci.btn_ns !=3D 0)
+ { // there are some buttons
+ uint32_t t3 =3D m_pci.vobu_s_ptm/90 - m_pci_vob_timecode_offset;
+ uint32_t t4 =3D m_pci.vobu_e_ptm/90 - m_pci_vob_timecode_offset;
+ m_demuxer.ProcessStream(SUBSTREAM_PCI, &m_buff[m_pci_position], m_p=
ci_size+2, t3, t4,=20
+ QString("# %1 -> %2 / %3 / %4 / %5 / %6 / off %7\n")
+ .arg(m_pci.vobu_s_ptm/90).arg(m_pci.vobu_e_ptm/90)
+ .arg(m_dsi.c_eltm, 0, 16).arg(m_pci.c_eltm, 0, 16)
+ .arg(t3).arg(t4).arg(m_pci_vob_timecode_offset));
+ =09
+ }
+ }
+ else if ((_StreamID & VIDEO_STREAM) =3D=3D VIDEO_STREAM)
+ {
+ debug("Video pack {}\n");
+ ParseVideoPacket();
+ }
+ else if ((_StreamID & AUDIO_STREAM) =3D=3D AUDIO_STREAM)
+ {
+ debug("Audio pack {}\n");
+ ParseAudioPacket(_StreamID);
+ }
+ else if (_StreamID =3D=3D PRIVATE_STREAM1)
+ {
+ debug("Private stream 1 pack {\n");
+ inc_lvl();
+ ParsePrivateStream1();
+ dec_lvl();
+ debug("}\n");
+ }
+ else
+ {
+ uint16_t _size =3D GetNext16Bits();
+ SkipNBytes(_size);
+ debug("Unknown slice type\n");
+ }
+
+ if (m_bFirstPacket && _StreamID !=3D SYSTEM_HEADER)
+ {
+ m_bFirstPacket =3D false;
+ m_startdts =3D pktinfo.dts;
+ m_startpts =3D pktinfo.pts;
+ }
+ }
+ else
+ {
+ debug("Unknown start code\n");
+ }
+ =09
+ m_pktindex++;
+ }
+ else
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+bool VobParser::AvailablePacketData() const
+{
+ return (m_index < DVD_VIDEO_LB_LEN);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+bool VobParser::GetNextPacket()
+{
+ m_index =3D 0;
+
+ return (DVDReadBlocks(m_stream, m_pktindex, 1, m_buff) =3D=3D 1);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint32_t VobParser::GetNext32Bits()
+{
+ uint32_t result =3D 0;
+ result |=3D m_buff[m_index++];
+ result <<=3D 8;
+ result |=3D m_buff[m_index++];
+ result <<=3D 8;
+ result |=3D m_buff[m_index++];
+ result <<=3D 8;
+ result |=3D m_buff[m_index++];
+ return result;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint16_t VobParser::GetNext16Bits()
+{
+ uint32_t result =3D 0;
+ result |=3D m_buff[m_index++];
+ result <<=3D 8;
+ result |=3D m_buff[m_index++];
+ return result;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint8_t VobParser::GetNext8Bits()
+{
+ return m_buff[m_index++];
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::SkipNBytes(int n)
+{
+ m_index +=3D n;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParseSCR()
+{
+
+/* From http://dvd.sourceforge.net/dvdinfo/packhdr.html
+
+ Byte 4 Byte 5
+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
+ | 7| 6| 5| 4| 3| 2| 1| 0| | 7| 6| 5| 4| 3| 2| 1| 0|
+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
+SCR bits |f0|f1|32|31|30|f1|29|28| |27|26|25|24|23|22|21|20|
+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
+
+ Byte 6 Byte 7
+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
+ | 7| 6| 5| 4| 3| 2| 1| 0| | 7| 6| 5| 4| 3| 2| 1| 0|
+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
+SCR bits |19|18|17|16|15|f1|14|13| |12|11|10| 9| 8| 7| 6| 5|
+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
+
+ Byte 8 Byte 9
+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
+ | 7| 6| 5| 4| 3| 2| 1| 0| | 7| 6| 5| 4| 3| 2| 1| 0|
+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
+SCR bits | 4| 3| 2| 1| 0|f1|e8|e7| |e6|e5|e4|e3|e2|f1|e0|c1|
+ +--+--+--+--+--+--+--+--+ +--+--+--+--+--+--+--+--+
+
+ fx =3D bit value fixed to x
+ ex =3D bit x of scr_ext
+*/
+
+ uint8_t byte4, byte5, byte6, byte7, byte8, byte9;
+ byte4 =3D GetNext8Bits(); byte5 =3D GetNext8Bits();
+ byte6 =3D GetNext8Bits(); byte7 =3D GetNext8Bits();
+ byte8 =3D GetNext8Bits(); byte9 =3D GetNext8Bits();
+
+ assert((byte4 & 0xc4) =3D=3D 0x44);
+ assert(byte6 & 0x04);
+ assert(byte8 & 0x04);
+ assert(byte9 & 0x01);
+ =09
+ uint64_t scr =3D 0;
+ scr |=3D ((((byte4 & 0x38) >> 1) | (byte4 & 0x03)) << 28);
+ scr |=3D (byte5 << 20);
+ scr |=3D ((((byte6 & 0xf8) >> 1) | (byte6 & 0x03)) << 13);
+ scr |=3D (byte7 << 5);
+ scr |=3D ((byte8 & 0xf8) >> 3);
+
+ uint16_t scr_ext =3D 0;
+ scr_ext |=3D ((byte8 & 0x03) << 7);
+ scr_ext |=3D ((byte9 & 0xfe) >> 1);
+
+ pktinfo.scr =3D scr;
+ pktinfo.scr_ext =3D scr_ext;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParseNavPacket()
+{
+ uint32_t endStreamIndex =3D 0;
+ uint32_t position =3D m_index;
+ uint16_t length =3D GetNext16Bits();
+ endStreamIndex =3D m_index + length;
+ uint8_t substreamID =3D GetNext8Bits();
+=09
+ switch(substreamID)
+ {
+ case SUBSTREAM_PCI:
+ debug("PCI {\n");
+ inc_lvl();
+ ParsePCI();
+ m_pci_position =3D position-4; // keep the Private Stream 2 header
+ m_pci_size =3D length+4;
+ dec_lvl();
+ debug("}\n");
+ break;
+ case SUBSTREAM_DSI:
+ debug("DSI {\n");
+ inc_lvl();
+ ParseDSI();
+ dec_lvl();
+ debug("}\n");
+ break;
+ default:
+ debug(QString("ParseNavPacket: unknown substream id @LBA=3D%1\n").arg=
(m_pktindex));
+ }
+=09
+ m_index =3D endStreamIndex;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParsePCI()
+{
+ int i,j;
+ uint8_t onebyte;
+
+ // PCI General Information
+ m_pci.nv_pck_lbn =3D GetNext32Bits();
+ m_pci.vobu_cat =3D GetNext16Bits();
+ m_pci.reserved1 =3D GetNext16Bits();
+ m_pci.vobu_uop_ctl =3D GetNext32Bits();
+ m_pci.vobu_s_ptm =3D GetNext32Bits();
+ m_pci.vobu_e_ptm =3D GetNext32Bits();
+ m_pci.vobu_se_e_ptm =3D GetNext32Bits();
+ m_pci.c_eltm =3D GetNext32Bits();
+ memcpy(m_pci.vobu_isrc, &m_buff[m_index],32*1);=09
+ SkipNBytes(32*1);
+
+ // Non Seamless Angle Information
+ memcpy(m_pci.nsml_agli_dsta, &m_buff[m_index], 9*4);
+ SkipNBytes(9*4);
+
+ // Highlight General Information=20
+ m_pci.hli_ss =3D GetNext16Bits();
+ m_pci.hli_s_ptm =3D GetNext32Bits();
+ m_pci.hli_e_ptm =3D GetNext32Bits();
+ m_pci.btn_sl_e_ptm =3D GetNext32Bits();
+ m_pci.btn_md =3D GetNext16Bits();
+ m_pci.btn_sn =3D GetNext8Bits();
+ m_pci.btn_ns =3D GetNext8Bits();
+ m_pci.nsl_btn_ns =3D GetNext8Bits();
+ m_pci.reserved1 =3D GetNext8Bits();
+ m_pci.fosl_btnn =3D GetNext8Bits();
+ m_pci.foac_btnn =3D GetNext8Bits();
+=09
+ // Button Color Information Table=20
+ for(i =3D 0; i < 3; i++)
+ for(j =3D 0; j < 2; j++)
+ m_pci.btn_coli[i][j] =3D GetNext32Bits();
+
+ // Button Information
+ for(i =3D 0; i < 36; i++)
+ {
+ onebyte =3D GetNext8Bits();
+ m_pci.btnit[i].btn_coln =3D (onebyte & 0xC0) >> 6;
+ m_pci.btnit[i].start_x =3D (onebyte & 0x3F) << 4;
+
+ onebyte =3D GetNext8Bits();
+ m_pci.btnit[i].start_x |=3D (onebyte & 0xF0) >> 4;
+ m_pci.btnit[i].end_x =3D (onebyte & 0x03) << 8;
+
+ onebyte =3D GetNext8Bits();
+ m_pci.btnit[i].end_x |=3D onebyte;
+
+ onebyte =3D GetNext8Bits();
+ m_pci.btnit[i].auto_action_flag =3D (onebyte & 0xC0) >> 6;
+ m_pci.btnit[i].start_y =3D (onebyte & 0x3F) << 4;
+ =09
+ onebyte =3D GetNext8Bits();
+ m_pci.btnit[i].start_y |=3D (onebyte & 0xF0) >> 4;
+ m_pci.btnit[i].end_y =3D (onebyte & 0x03) << 8;
+ =09
+ onebyte =3D GetNext8Bits();
+ m_pci.btnit[i].end_y |=3D onebyte;
+
+ m_pci.btnit[i].up =3D GetNext8Bits() & 0x3F;
+ m_pci.btnit[i].down =3D GetNext8Bits() & 0x3F;
+ m_pci.btnit[i].left =3D GetNext8Bits() & 0x3F;
+ m_pci.btnit[i].right =3D GetNext8Bits() & 0x3F;
+ =09
+ memcpy(m_pci.btnit[i].vm_cmd, &m_buff[m_index],8*1);
+ SkipNBytes(8*1);
+ }
+
+ debug(QString("nv_pck_lbn: %1\n").arg(m_pci.nv_pck_lbn));
+ debug(QString("vobu_cat: %1\n").arg(m_pci.vobu_cat));
+ debug(QString("reserved1: %1\n").arg(m_pci.reserved1));
+ debug(QString("vobu_uop_ctl: %1\n").arg(m_pci.vobu_uop_ctl));
+ debug(QString("vobu_s_ptm: %1\n").arg(m_pci.vobu_s_ptm));
+ debug(QString("vobu_e_ptm: %1\n").arg(m_pci.vobu_e_ptm));
+ debug(QString("vobu_se_e_ptm: %1\n").arg(m_pci.vobu_se_e_ptm));
+ debug(QString("e_eltm: %1\n").arg(m_pci.c_eltm));
+ debug(QString("vobu_isrc: ...\n").toAscii());
+ debug(QString("nsml_agli_dsta: ...\n").toAscii());
+ debug(QString("hli_ss: %1\n").arg(m_pci.hli_ss));
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParseDSI()
+{
+ m_dsi.nv_pck_scr =3D GetNext32Bits();
+ m_dsi.nv_pck_lbn =3D GetNext32Bits();
+ m_dsi.vobu_ea =3D GetNext32Bits();
+ m_dsi.vobu_1stref_ea =3D GetNext32Bits();
+ m_dsi.vobu_2ndref_ea =3D GetNext32Bits();
+ m_dsi.vobu_3rdref_ea =3D GetNext32Bits();
+ m_dsi.vobu_vob_idn =3D GetNext16Bits();
+ m_dsi.reserved =3D GetNext8Bits();
+ m_dsi.vobu_c_idn =3D GetNext8Bits();
+ m_dsi.c_eltm =3D GetNext32Bits();
+
+ debug(QString("nv_pck_scr: %1\n").arg(m_dsi.nv_pck_scr));
+ debug(QString("nv_pck_lbn: %1\n").arg(m_dsi.nv_pck_lbn));
+ debug(QString("vobu_ea: %1\n").arg(m_dsi.vobu_ea));
+ debug(QString("vobu_1stref_ea: %1\n").arg(m_dsi.vobu_1stref_ea));
+ debug(QString("vobu_2ndref_ea: %1\n").arg(m_dsi.vobu_2ndref_ea));
+ debug(QString("vobu_3rdref_ea: %1\n").arg(m_dsi.vobu_3rdref_ea));
+ debug(QString("vobu_vob_idn: %1\n").arg(m_dsi.vobu_vob_idn));
+ debug(QString("reserved: %1\n").arg(m_dsi.reserved));
+ debug(QString("vobu_c_idn: %1\n").arg(m_dsi.vobu_c_idn));
+ debug(QString("c_eltm: %1\n").arg(m_dsi.c_eltm));
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint8_t GetBit(uint32_t data, uint8_t n)
+{
+ return ((data >> n) & 0x01);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParsePESHeaderDataContentFlag()
+{=09
+ uint8_t byte6 =3D GetNext8Bits();
+ assert((byte6 & 0xC0) =3D=3D 0x80);
+ pes_header_data_content.PES_scrambling_control =3D (byte6 & 0x30) >> 4;
+ pes_header_data_content.PES_priority =3D GetBit(byte6,3);
+ pes_header_data_content.data_alignment_indicator =3D GetBit(byte6,2);
+ pes_header_data_content.copyright =3D GetBit(byte6,1);
+ pes_header_data_content.original_or_copy =3D GetBit(byte6,0);
+
+ uint8_t byte7 =3D GetNext8Bits();
+ pes_header_data_content.PTS_flag =3D GetBit(byte7,7);
+ pes_header_data_content.DTS_flag =3D GetBit(byte7,6);
+ pes_header_data_content.ESCR_flag =3D GetBit(byte7,5);
+ pes_header_data_content.ES_rate_flag =3D GetBit(byte7,4);
+ pes_header_data_content.DSM_trick_mode_flag =3D GetBit(byte7,3);
+ pes_header_data_content.additionnal_copy_info_flag =3D GetBit(byte7,2);
+ pes_header_data_content.PES_CRC_flag =3D GetBit(byte7,1);
+ pes_header_data_content.PES_extension_flag =3D GetBit(byte7,0);
+=09
+ pes_header_data_content.PES_header_data_len =3D GetNext8Bits();
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint64_t VobParser::ParsePTS_DTS()
+{
+ // PTS and DTS have same format
+ uint64_t result =3D 0;
+
+ uint8_t byte0 =3D GetNext8Bits();
+ uint16_t word0 =3D GetNext16Bits();
+ uint16_t word1 =3D GetNext16Bits();
+
+ assert(word0 & 0x01);
+ assert(word1 & 0x01);
+
+ result |=3D (((byte0 & 0x0E) >> 1) << 30);
+ result |=3D ((word0 >> 1) << 15);
+ result |=3D (word1 >> 1);
+
+ return result;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParsePESHeaderData()
+{
+ uint8_t bytesLeft =3D pes_header_data_content.PES_header_data_len;
+ if(pes_header_data_content.PTS_flag)
+ {
+ // PTS : Presentation Time Stamp
+ pktinfo.pts =3D ParsePTS_DTS();
+ bytesLeft -=3D 5;
+ if (m_bFirstPacket)
+ {
+ m_startpts =3D pktinfo.pts;
+ }
+ pktinfo.pts -=3D m_startpts;
+ }
+ if(pes_header_data_content.DTS_flag)
+ {
+ // DTS : Decoding Time Stamp
+ pktinfo.dts =3D ParsePTS_DTS();
+ bytesLeft -=3D 5;
+ if (m_bFirstPacket)
+ {
+ m_startdts =3D pktinfo.dts;
+ }
+ pktinfo.dts -=3D m_startdts;
+ }
+ m_bFirstPacket =3D false;
+
+ // Skip the rest
+ SkipNBytes(bytesLeft);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParseVideoPacket()
+{
+ uint16_t length =3D GetNext16Bits();
+ ParsePESHeaderDataContentFlag();
+ ParsePESHeaderData();
+
+ m_demuxer.ProcessStream(VIDEO_STREAM, &m_buff[m_index],
+ length - 3 - pes_header_data_content.PES_header_data_len, pktinfo.dts/=
90, pktinfo.pts/90,
+ QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startpts/9=
0).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+}
+
+void VobParser::ParseAudioPacket(int StreamID)
+{
+ uint16_t length =3D GetNext16Bits();
+ ParsePESHeaderDataContentFlag();
+ ParsePESHeaderData();
+
+ m_demuxer.ProcessStream(StreamID, &m_buff[m_index],
+ length - 3 - pes_header_data_content.PES_header_data_len, pktinfo.pts/=
90, pktinfo.dts/90,
+ QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startpts/9=
0).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParsePrivateStream1()
+{
+ uint16_t length =3D GetNext16Bits();=09
+ uint16_t dataStartIndex =3D m_index;
+ // PES : Packetized Elementary Stream
+ ParsePESHeaderDataContentFlag();
+ ParsePESHeaderData();
+ uint8_t substreamID =3D GetNext8Bits();
+
+ uint32_t t3 =3D m_pci.vobu_s_ptm/90 - m_pci_vob_timecode_offset;
+ uint32_t t4 =3D m_pci.vobu_e_ptm/90 - m_pci_vob_timecode_offset;
+ if(substreamID >=3D SUBSTREAM_SUB_LOW && substreamID < SUBSTREAM_SUB_HI=
GH)
+ {
+ debug(QString("Subtitles streamID =3D 0x%1\n").arg(substreamID, 0, 16)=
);
+
+ // .sub files the VobSub way (includes the whole packet)
+ m_demuxer.ProcessStream(substreamID, m_buff, DVD_VIDEO_LB_LEN, t3, t4,=
=20
+ QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startp=
ts/90).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+ }
+ else if(substreamID >=3D SUBSTREAM_AC3_LOW && substreamID < SUBSTREAM_A=
C3_HIGH)
+ {
+ debug(QString("AC3 streamID =3D 0x%1\n").arg(substreamID, 0, 16));
+
+ // Skip frame header number
+ SkipNBytes(1);
+ // Skip first access unit pointer
+ SkipNBytes(2);
+
+ uint16_t ac3DataLen =3D length - (m_index - dataStartIndex);
+ m_demuxer.ProcessStream(substreamID, &m_buff[m_index], ac3DataLen, t3,=
t4,=20
+ QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startp=
ts/90).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+ }
+ else if(substreamID >=3D SUBSTREAM_DTS_LOW && substreamID < SUBSTREAM_D=
TS_HIGH)
+ {
+ debug(QString("DTS streamID =3D 0x%1\n").arg(substreamID, 0, 16));
+ =09
+ // Skip frame header number
+ SkipNBytes(1);
+ // Skip first access unit pointer
+ SkipNBytes(2);
+
+ uint16_t ac3DataLen =3D length - (m_index - dataStartIndex);
+ m_demuxer.ProcessStream(substreamID, &m_buff[m_index], ac3DataLen, t3,=
t4,=20
+ QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startp=
ts/90).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+ }
+ else if(substreamID >=3D SUBSTREAM_PCM_LOW && substreamID < SUBSTREAM_P=
CM_HIGH)
+ {
+ debug(QString("LPCM streamID =3D 0x%1\n").arg(substreamID, 0, 16));
+
+ // Skip unknown data
+ SkipNBytes(6);
+
+ uint16_t ac3DataLen =3D length - (m_index - dataStartIndex);
+ m_demuxer.ProcessStream(substreamID, &m_buff[m_index], ac3DataLen, t3,=
t4,=20
+ QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startpts/=
90).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+ }
+ else
+ {
+ debug("Unknown\n");
+ }
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::Reset()
+{
+ memset(&m_dsi, 0, sizeof(m_dsi));
+ memset(&pktinfo, 0, sizeof(pktinfo));
+ memset(&pes_header_data_content, 0, sizeof(pes_header_data_content));
+ previous_vobid =3D -1;
+ previous_cellid =3D -1;
+ m_index =3D 0;
+ m_pktindex =3D 0;
+ DVDFileSeek(m_stream,0);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+bool VobParser::IsNewCell()
+{
+ bool result =3D (GetVobID() !=3D previous_vobid ||
+ GetCellID() !=3D previous_cellid);
+=09
+ previous_vobid =3D GetVobID();
+ previous_cellid =3D GetCellID();
+ if (result)
+ m_bFirstPacket =3D true;
+
+ return result;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+inline uint8_t VobParser::GetVobID() const
+{
+ return m_dsi.vobu_vob_idn;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+inline uint8_t VobParser::GetCellID() const
+{
+ return m_dsi.vobu_c_idn;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint32_t VobParser::GetCellSCR() const
+{
+ return m_dsi.nv_pck_scr;
+}
+
+// ---------------------------------------------------------------------=
-------
+=20
+void SubDemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t end=
_time, uint64_t filepos, const QString& debug)
+{
+ int i;
+
+ if (!m_TimecodeFile)
+ {
+ QString m_filename (m_Filename);
+ m_filename +=3D ".idx";
+ m_TimecodeFile =3D fopen(QFile::encodeName(m_filename),"w");
+
+ fwrite("# VobSub index file, v7 (do not modify this line!)\n#\n", 1, 5=
3, m_TimecodeFile);
+ fwrite("# Settings\n\n# Original frame size\nsize: ", 1, 40, m_Timecod=
eFile);
+ fprintf(m_TimecodeFile, "%dx%d\n\n", m_width, m_height);
+ fwrite("# Origin, relative to the upper-left corner, can be overloaded=
by aligment\n"
+ "org: 0, 0\n\n"
+ "# Image scaling (hor,ver), origin is at the upper-left corner =
or at the alignment coord (x, y)\n"
+ "scale: 100%, 100%\n\n"
+ "# Alpha blending\n"
+ "alpha: 100%\n\n"
+ "# Smoothing for very blocky images (use OLD for no filtering)\=
n"
+ "smooth: OFF\n\n"
+ "# In millisecs\n"
+ "fadein/out: 50, 50\n\n"
+ "# Force subtitle placement relative to (org.x, org.y)\n"
+ "align: OFF at LEFT TOP\n\n"
+ "# For correcting non-progressive desync. (in millisecs or hh:m=
m:ss:ms)\n"
+ "# Note: Not effective in DirectVobSub, use \"delay: ... \" ins=
tead.\n"
+ "time offset: 0\n\n"
+ "# ON: displays only forced subtitles, OFF: shows everything\n"
+ "forced subs: OFF\n\n"
+ "# The original palette of the DVD\n"
+ "palette: ", 1, 692, m_TimecodeFile);
+ for (i=3D0; i<15; i++)
+ {
+ fprintf(m_TimecodeFile, "%06x, ", m_palette[i]);
+ }
+ fprintf(m_TimecodeFile, "%06x\n\n", m_palette[i]);
+ fwrite("# Custom colors (transp idxs and the four colors)\n"
+ "custom colors: OFF, tridx: 0000, colors: 000000, 000000, 00000=
0, 000000\n\n"
+ "# Language index in use\n"
+ "langidx: 0\n\n"
+ "id: ", 1, 163, m_TimecodeFile);
+ if (m_language)
+ fprintf(m_TimecodeFile, "%c%c", m_language >> 8, m_language);
+ else
+ fwrite("un", 1, 2, m_TimecodeFile);
+ fwrite(", index: 0\n"
+ "# Decomment next line to activate alternative name in DirectVo=
bSub / Windows Media Player 6.x\n"
+ "# alt: ", 1, 112, m_TimecodeFile);
+ fprintf(m_TimecodeFile, "%s\n\n", DecodeLanguage(m_language));
+ }
+ int32_t delay =3D start_time + m_start_timecode;
+ int millisecond =3D delay % 1000;
+ delay /=3D 1000;
+ int second =3D delay % 60;
+ delay /=3D 60;
+ int minute =3D delay % 60;
+ delay /=3D 60;
+ fprintf(m_TimecodeFile, "timestamp: %02d:%02d:%02d:%03d, filepos: %09x\=
n", delay,minute,second,millisecond,filepos);
+}
+
+void BtnDemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t end=
_time, uint64_t filepos, const QString& debug)
+{
+//static uint32_t time =3D0;
+ m_TimecodeFile =3D GetTimecodeFile();
+
+ if (start_time > m_last_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_last_start_t=
imecode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (start_time - m_last_end_timecode=
) / 1000.0);
+ m_start_timecode =3D start_time;
+ }
+//fwrite(debug.c_str(), debug.size(), 1, m_TimecodeFile);
+//fprintf(m_TimecodeFile, "# %d =3D> %d\n",time, time + end_time - start=
_time);
+//time +=3D end_time - start_time;
+ m_last_start_timecode =3D start_time;
+ m_last_end_timecode =3D end_time;
+}
+
+void DTSDemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t end=
_time, uint64_t filepos, const QString& debug)
+{
+ m_TimecodeFile =3D GetTimecodeFile();
+
+ if (start_time > m_last_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_last_start_t=
imecode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (start_time - m_last_end_timecode=
) / 1000.0);
+ m_start_timecode =3D start_time;
+ }
+ m_last_start_timecode =3D start_time;
+ m_last_end_timecode =3D end_time;
+}
+
+void LPCMDemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t en=
d_time, uint64_t filepos, const QString& debug)
+{
+ m_TimecodeFile =3D GetTimecodeFile();
+
+ if (start_time > m_last_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timeco=
de) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (start_time - m_last_end_timecode=
) / 1000.0);
+ m_start_timecode =3D start_time;
+ }
+ m_last_start_timecode =3D start_time;
+ m_last_end_timecode =3D end_time;
+}
+
+void MPADemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t end=
_time, uint64_t filepos, const QString& debug)
+{
+ m_TimecodeFile =3D GetTimecodeFile();
+}
+
+void AC3DemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t end=
_time, uint64_t filepos, const QString& debug)
+{
+ m_TimecodeFile =3D GetTimecodeFile();
+
+ if (start_time > m_last_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_last_start_t=
imecode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (start_time - m_last_end_timecode=
) / 1000.0);
+ m_start_timecode =3D start_time;
+ }
+ m_last_start_timecode =3D start_time;
+ m_last_end_timecode =3D end_time;
+}
+
+void VideoDemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t e=
nd_time, uint64_t filepos, const QString& debug)
+{
+ // TODO detect gaps in the stream
+}
+
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+void VideoDemuxWriter::ProcessStream(uint8_t* buff, uint32_t size, uint3=
2_t start_time, uint32_t end_time, const QString& debug)
+{
+ if (m_parser =3D=3D NULL)
+ m_parser =3D new M2VParser;
+=09
+ m_parser->WriteData(buff, size);
+
+ MPEG2ParserState state =3D m_parser->GetState();
+
+ while (state =3D=3D MPV_PARSER_STATE_FRAME)=20
+ {
+ delete m_parser->ReadFrame();
+ state =3D m_parser->GetState();
+ }
+
+ Write(buff, size, start_time, end_time, debug);=20
+}
+
+void VideoDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t dur=
ation, const CellListElem *cell)
+{
+ if (m_parser !=3D NULL)
+ {
+ m_parser->SetEOS();
+
+ MPEG2ParserState state =3D m_parser->GetState();
+
+ while (state =3D=3D MPV_PARSER_STATE_FRAME)=20
+ {
+ MPEGFrame* current_frame =3D m_parser->ReadFrame();
+ if ((current_frame->timecode + current_frame->duration) / 1000000 > m=
_last_end_timecode)
+ {
+ m_last_start_timecode =3D current_frame->timecode / 1000000;
+ m_last_end_timecode =3D (current_frame->timecode + current_frame->du=
ration) / 1000000;
+ }
+ delete current_frame;
+
+ state =3D m_parser->GetState();
+ }
+ =09
+ delete m_parser;
+ }
+=09
+ m_parser =3D new M2VParser();
+
+ m_TimecodeFile =3D GetTimecodeFile();
+
+ if (m_end_timecode !=3D 0)
+ {
+ if (m_is_still) {
+ fwrite(" (Still)\n", 1, 9, m_TimecodeFile);
+ fprintf(m_TimecodeFile, "%lf,%lf\n", (m_end_timecode - m_start_timeco=
de) / 1000.0, 1000.0 / (m_end_timecode - m_start_timecode));
+ }
+ else if (m_last_end_timecode < m_end_timecode)
+ {
+ fprintf(m_TimecodeFile, "\n%lf\n", (m_last_end_timecode - m_start_tim=
ecode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_tim=
ecode) / 1000.0);
+ }
+ else
+ {
+ if (m_last_end_timecode > m_end_timecode)
+ qWarning("There is more video that indicated in the cell.");
+ fprintf(m_TimecodeFile, "\n%lf\n", (m_last_end_timecode - m_start_tim=
ecode) / 1000.0);
+ }
+ }
+
+ m_start_timecode =3D start_timecode;
+ m_end_timecode =3D start_timecode + duration;
+ m_last_end_timecode =3D start_timecode;
+ m_is_still =3D cell->isStill;
+
+ fprintf(m_TimecodeFile, "\n# VOB %d Cell %d", cell->vobid, cell->cellid=
);
+}
+
+void AC3DemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t durat=
ion, const CellListElem *cell)
+{
+ m_TimecodeFile =3D GetTimecodeFile();
+
+ // handle ending of the previous cell
+ if (m_last_end_timecode < m_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+ }
+ else
+ {
+ if (m_end_timecode !=3D 0)
+ {
+ if (m_last_end_timecode > m_end_timecode)
+ qWarning("There is more AC3 audio that indicated in the cell.");
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ }
+ }
+
+ m_start_timecode =3D start_timecode;
+ m_end_timecode =3D start_timecode + duration;
+ m_last_end_timecode =3D start_timecode;
+ m_last_start_timecode =3D start_timecode;
+
+ fprintf(m_TimecodeFile, "\n# VOB %d Cell %d\n", cell->vobid, cell->cell=
id);
+}
+
+void DTSDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t durat=
ion, const CellListElem *cell)
+{
+ m_TimecodeFile =3D GetTimecodeFile();
+
+ // handle ending of the previous cell
+ if (m_last_end_timecode < m_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+ }
+ else
+ {
+ if (m_end_timecode !=3D 0)
+ {
+ if (m_last_end_timecode > m_end_timecode)
+ qWarning("There is more DTS audio that indicated in the cell.");
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ }
+ }
+
+ m_start_timecode =3D start_timecode;
+ m_end_timecode =3D start_timecode + duration;
+ m_last_end_timecode =3D start_timecode;
+ m_last_start_timecode =3D start_timecode;
+
+ fprintf(m_TimecodeFile, "\n# VOB %d Cell %d\n", cell->vobid, cell->cell=
id);
+}
+
+void LPCMDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t dura=
tion, const CellListElem *cell)
+{
+ m_TimecodeFile =3D GetTimecodeFile();
+
+ // handle ending of the previous cell
+ if (m_last_end_timecode < m_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+ }
+ else
+ {
+ if (m_end_timecode !=3D 0)
+ {
+ if (m_last_end_timecode > m_end_timecode)
+ qWarning("There is more PCM audio that indicated in the cell.");
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ }
+ }
+
+ m_start_timecode =3D start_timecode;
+ m_end_timecode =3D start_timecode + duration;
+ m_last_end_timecode =3D start_timecode;
+ m_last_start_timecode =3D start_timecode;
+
+ fprintf(m_TimecodeFile, "\n# VOB %d Cell %d\n", cell->vobid, cell->cell=
id);
+}
+
+void MPADemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t durat=
ion, const CellListElem *cell)
+{
+}
+
+void SubDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t durat=
ion, const CellListElem *cell)
+{
+ if (start_timecode =3D=3D 0)
+ m_start_timecode =3D m_end_timecode;
+ m_end_timecode +=3D duration;
+}
+
+void BtnDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t durat=
ion, const CellListElem *cell)
+{
+ m_TimecodeFile =3D GetTimecodeFile();
+
+ // handle ending of the previous cell
+ if (m_last_end_timecode < m_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+ }
+ else
+ {
+ if (m_end_timecode !=3D 0)
+ {
+ if (m_last_end_timecode > m_end_timecode)
+ qWarning("There is more Button data that indicated in the cell.");
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ }
+ }
+
+ m_start_timecode =3D start_timecode;
+ m_end_timecode =3D start_timecode + duration;
+ m_last_end_timecode =3D start_timecode;
+ m_last_start_timecode =3D start_timecode;
+
+ fprintf(m_TimecodeFile, "\n# VOB %d Cell %d\n", cell->vobid, cell->cell=
id);
+}
+
+VideoDemuxWriter::~VideoDemuxWriter()
+{
+ try
+ {
+ m_TimecodeFile =3D GetTimecodeFile();
+ }
+ catch (VobParserException&)
+ {
+ m_TimecodeFile =3D 0;
+ }
+=09
+ if (m_parser !=3D NULL)
+ {
+ m_parser->SetEOS();
+
+ MPEG2ParserState state =3D m_parser->GetState();
+
+ while (state =3D=3D MPV_PARSER_STATE_FRAME)=20
+ {
+ MPEGFrame* current_frame =3D m_parser->ReadFrame();
+ if ((current_frame->timecode + current_frame->duration) / 1000000 > m=
_last_end_timecode)
+ {
+ m_last_start_timecode =3D current_frame->timecode / 1000000;
+ m_last_end_timecode =3D (current_frame->timecode + current_frame->du=
ration) / 1000000;
+ }
+ delete current_frame;
+
+ state =3D m_parser->GetState();
+ }
+ delete m_parser;
+ }
+
+
+ if ((m_end_timecode !=3D 0) && m_TimecodeFile)
+ {
+ if (m_is_still) {
+ fwrite(" (Still)\n", 1, 9, m_TimecodeFile);
+ fprintf(m_TimecodeFile, "%lf,%lf\n", (m_end_timecode - m_start_timeco=
de) / 1000.0, 1000.0 / (m_end_timecode - m_start_timecode));
+ }
+ else if (m_last_end_timecode < m_end_timecode)
+ {
+ fprintf(m_TimecodeFile, "\n%lf\n", (m_last_end_timecode - m_start_tim=
ecode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_tim=
ecode) / 1000.0);
+ }
+ else
+ fprintf(m_TimecodeFile, "\n%lf\n", (m_end_timecode - m_start_timecode=
) / 1000.0);
+ }
+}
+
+AC3DemuxWriter::~AC3DemuxWriter()
+{
+ try
+ {
+ m_TimecodeFile =3D GetTimecodeFile();
+ }
+ catch (VobParserException&)
+ {
+ return;
+ }
+
+ // handle ending of the previous cell
+ if (m_last_end_timecode < m_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+ }
+ else
+ {
+ if (m_end_timecode !=3D 0)
+ fprintf(m_TimecodeFile, "%lf\n", (m_end_timecode - m_start_timecode) =
/ 1000.0);
+ }
+}
+
+DTSDemuxWriter::~DTSDemuxWriter()
+{
+ try
+ {
+ m_TimecodeFile =3D GetTimecodeFile();
+ }
+ catch (VobParserException&)
+ {
+ return;
+ }
+
+ // handle ending of the previous cell
+ if (m_last_end_timecode < m_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+ }
+ else
+ {
+ if (m_end_timecode !=3D 0)
+ fprintf(m_TimecodeFile, "%lf\n", (m_end_timecode - m_start_timecode) =
/ 1000.0);
+ }
+}
+
+LPCMDemuxWriter::~LPCMDemuxWriter()
+{
+ try
+ {
+ m_TimecodeFile =3D GetTimecodeFile();
+ }
+ catch (VobParserException&)
+ {
+ return;
+ }
+
+ // handle ending of the previous cell
+ if (m_last_end_timecode < m_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+ }
+ else
+ {
+ if (m_end_timecode !=3D 0)
+ fprintf(m_TimecodeFile, "%lf\n", (m_end_timecode - m_start_timecode) =
/ 1000.0);
+ }
+}
+
+BtnDemuxWriter::~BtnDemuxWriter()
+{
+ try
+ {
+ m_TimecodeFile =3D GetTimecodeFile();
+ }
+ catch (VobParserException&)
+ {
+ return;
+ }
+
+ // handle ending of the previous cell
+ if (m_last_end_timecode < m_end_timecode)
+ {
+ if (m_last_end_timecode > m_start_timecode)
+ fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+ fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+ }
+ else
+ {
+ if (m_end_timecode !=3D 0)
+ fprintf(m_TimecodeFile, "%lf\n", (m_end_timecode - m_start_timecode) =
/ 1000.0);
+ }
+}
+
+WavWriter::~WavWriter()
+{
+ if (m_file)
+ {
+ uint8_t _tinteger[4];
+
+ fseek(m_file, m_size_position2, SEEK_SET);
+ _tinteger[0] =3D m_size & 0xFF;
+ _tinteger[1] =3D (m_size >> 8) & 0xFF;
+ _tinteger[2] =3D (m_size >> 16) & 0xFF;
+ _tinteger[3] =3D (m_size >> 24) & 0xFF;
+ fwrite(_tinteger,4,1, m_file);
+ =09
+ m_size +=3D 36;
+ fseek(m_file, m_size_position1, SEEK_SET);
+ _tinteger[0] =3D m_size & 0xFF;
+ _tinteger[1] =3D (m_size >> 8) & 0xFF;
+ _tinteger[2] =3D (m_size >> 16) & 0xFF;
+ _tinteger[3] =3D (m_size >> 24) & 0xFF;
+ fwrite(_tinteger,4,1, m_file);
+ }
+}
+
+void WavWriter::Write(uint8_t* buff, uint32_t size, uint32_t start_time,=
uint32_t end_time, const QString& debug)
+{
+ if (m_bit_depth !=3D 16) // not supported
+ return;
+ if (m_file =3D=3D NULL)
+ {
+ uint8_t _tinteger[4];
+ m_file =3D OpenOuputFile();
+
+ // create the WAV header
+ // RIFF head
+ fwrite("RIFF",4,1, m_file);
+ m_size_position1 =3D ftell(m_file);
+ fwrite("0000",4,1, m_file);
+ fwrite("WAVE",4,1, m_file);
+ =09
+ // Format head
+ fwrite("fmt ",4,1, m_file);
+ _tinteger[0] =3D 16;
+ _tinteger[1] =3D 0;
+ _tinteger[2] =3D 0;
+ _tinteger[3] =3D 0;
+ fwrite(_tinteger,4,1, m_file);
+ =09
+ _tinteger[0] =3D 1;
+ fwrite(_tinteger,2,1, m_file); // PCM
+ =09
+ _tinteger[0] =3D m_channel_nb;
+ _tinteger[1] =3D 0;
+ fwrite(_tinteger,2,1, m_file); // Channels
+ =09
+ _tinteger[0] =3D m_sample_rate & 0xFF;
+ _tinteger[1] =3D (m_sample_rate >> 8) & 0xFF;
+ _tinteger[2] =3D (m_sample_rate >> 16) & 0xFF;
+ _tinteger[3] =3D (m_sample_rate >> 24) & 0xFF;
+ fwrite(_tinteger,4,1, m_file); // Sampling freq
+ =09
+ uint32_t _byte_rate =3D (m_sample_rate * m_channel_nb * m_bit_depth) >=
> 3;
+ _tinteger[0] =3D _byte_rate & 0xFF;
+ _tinteger[1] =3D (_byte_rate >> 8) & 0xFF;
+ _tinteger[2] =3D (_byte_rate >> 16) & 0xFF;
+ _tinteger[3] =3D (_byte_rate >> 24) & 0xFF;
+ fwrite(_tinteger,4,1, m_file); // Byte Rate
+ =09
+ uint16_t _block_align =3D (m_channel_nb * m_bit_depth) >> 3;
+ _tinteger[0] =3D _block_align & 0xFF;
+ _tinteger[1] =3D (_block_align >> 8) & 0xFF;
+ fwrite(_tinteger,2,1, m_file); // Block Align
+ =09
+ _tinteger[0] =3D m_bit_depth;
+ _tinteger[1] =3D 0;
+ fwrite(_tinteger,2,1, m_file); // Block Align
+ =09
+ // Data head
+ fwrite("data",4,1, m_file);
+ m_size_position2 =3D ftell(m_file);
+ fwrite("0000",4,1, m_file);
+ m_size =3D 0;
+ }
+ uint16_t _tmp;
+ for (size_t i=3D0; i < size; i+=3D2) {
+ _tmp =3D buff[i];
+ _tmp <<=3D 8;
+ _tmp +=3D buff[i+1];
+ buff[i] =3D _tmp & 0xFF;
+ buff[i+1] =3D _tmp >> 8;
+ }
+ Writer::Write(buff, size, start_time, end_time, debug);
+ m_size +=3D size;
+}
Added: trunk/DvdMenuXtractor/dmx/vobparser/VobParser.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx/vobparser/VobParser.h 2007-03-10 21:45:28 U=
TC (rev 1291)
+++ trunk/DvdMenuXtractor/dmx/vobparser/VobParser.h 2007-03-10 21:46:03 U=
TC (rev 1292)
@@ -0,0 +1,621 @@
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// VOBParser class
+// Copyright =A9 2002 : Christophe PARIS (christophe.paris at free.fr)
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+#ifndef _VOB_PARSER_H_
+#define _VOB_PARSER_H_
+// ---------------------------------------------------------------------=
-------
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdexcept>
+
+#include "dvdread/ifo_read.h"
+#include "mpegparser/M2VParser.h"
+
+#include <QList>
+#include <QFile>
+#include <QString>
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+#define VIDEO_STREAM_TYPE 0x01
+#define AUDIO_STREAM_TYPE 0x02
+#define SUB_STREAM_TYPE 0x04
+
+#define AC3_STREAM_TYPE (AUDIO_STREAM_TYPE | 0x08)
+#define DTS_STREAM_TYPE (AUDIO_STREAM_TYPE | 0x10)
+#define PCM_STREAM_TYPE (AUDIO_STREAM_TYPE | 0x20)
+
+
+#define AUDIO_STREAM 0xC0
+#define VIDEO_STREAM 0xE0
+
+#define SUBSTREAM_PCI 0x00
+#define SUBSTREAM_DSI 0x01
+
+#define SUBSTREAM_SUB_LOW 0x20
+#define SUBSTREAM_SUB_HIGH (SUBSTREAM_SUB_LOW + 32)
+
+#define SUBSTREAM_AC3_LOW 0x80
+#define SUBSTREAM_AC3_HIGH (SUBSTREAM_AC3_LOW + 8)
+
+#define SUBSTREAM_DTS_LOW 0x88
+#define SUBSTREAM_DTS_HIGH (SUBSTREAM_DTS_LOW + 8)
+
+#define SUBSTREAM_PCM_LOW 0xA0
+#define SUBSTREAM_PCM_HIGH (SUBSTREAM_PCM_LOW + 8)
+
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// Type
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+typedef struct=20
+{
+ unsigned int vobid;
+ unsigned int cellid;
+ unsigned int start_frame;
+ unsigned int end_frame;
+ unsigned int nb_frames;
+ uint32_t start_sector;
+ uint32_t last_sector;
+ double frame_dur;
+ uint64_t start_time;
+ uint64_t duration;
+ bool isStill;
+ bool selected;
+ bool found;
+ //ButtonsListType btt_list;
+} CellListElem;
+
+typedef struct {
+ uint16_t start_x; // Starting X position
+ uint16_t start_y; // Starting Y position
+ uint16_t end_x; // Ending X position
+ uint16_t end_y; // Ending Y position
+ uint8_t btn_coln; // Button color table number, 0=3Dnone
+ uint8_t auto_action_flag; // Auto Action flag 0=3Dno, 1=3Dyes
+ uint8_t up; // Button number to select if "Up" is pressed
+ uint8_t down; // Button number to select if "Down" is pressed
+ uint8_t left; // Button number to select if "Left" is pressed
+ uint8_t right; // Button number to select if "Right" is pressed
+ uint8_t vm_cmd[8]; // One vm command to be executed on "action" of t=
his button
+} btni;
+
+typedef struct {
+ uint32_t nv_pck_lbn : 32; // Logical Block Number (sector) of this blo=
ck
+ uint16_t vobu_cat : 16; // Flags, including APS (Analog Protection Sys=
tem)
+ uint16_t reserved1 : 16; // Reserved
+ uint32_t vobu_uop_ctl : 32; // bitmask for prohibited user operations
+ uint32_t vobu_s_ptm : 32; // Vobu Start Presentation Time (90KHz clk)
+ uint32_t vobu_e_ptm : 32; // Vobu End Presentation Time (PTM)
+ uint32_t vobu_se_e_ptm : 32; // End PTM of VOBU if Sequence_End_Code
+ uint32_t c_eltm : 32; // Cell elapsed time (BCD)
+ uint8_t vobu_isrc[32]; // International Standard Recording Code (roy=
alty management)
+ uint32_t nsml_agli_dsta[9]; // Non-seamless angle 1 relative offset to=
VOBU for CURRENT ILVU=20
+ uint16_t hli_ss; // Highlight status (lower 2 bits only)
+ uint32_t hli_s_ptm; // Highlight start time
+ uint32_t hli_e_ptm; // Highlight end time
+ uint32_t btn_sl_e_ptm; // Button selection end time (ignore user afte=
r this)
+ uint16_t btn_md; // 4 nibbles which describe the grouping of the but=
tons
+ uint8_t btn_sn; // Starting button number
+ uint8_t btn_ns; // Number of buttons
+ uint8_t nsl_btn_ns; // Number of numerically selected buttons
+ uint8_t reserved2; // Reserved
+ uint8_t fosl_btnn; // Force select button number
+ uint8_t foac_btnn; // Force action button number
+ uint32_t btn_coli[3][2]; // Selection and action color and contrast va=
lues
+ btni btnit[36];
+} nav_pci_gi;
+
+typedef struct {
+ uint32_t nv_pck_scr : 32; // System clock reference
+ uint32_t nv_pck_lbn : 32; // Logical Block Number (sector) of this blo=
ck
+ uint32_t vobu_ea : 32; // VOBU end address - relative offset to last s=
ector of VOBU
+ uint32_t vobu_1stref_ea : 32; // First reference frame end block, relat=
ive - used for fast playing
+ uint32_t vobu_2ndref_ea : 32; // Second reference frame end block, rela=
tive - used for fast playing
+ uint32_t vobu_3rdref_ea : 32; // Third reference frame end block, relat=
ive - used for fast playing
+ uint16_t vobu_vob_idn : 16; // VOB number
+ uint8_t reserved : 8; // Reserved
+ uint8_t vobu_c_idn : 8; // CELL number within VOB
+ uint32_t c_eltm : 32; // Cell elapsed time (BCD)
+} nav_dsi_gi;
+
+typedef struct {
+ uint8_t PES_scrambling_control : 2;
+ uint8_t PES_priority : 1;
+ uint8_t data_alignment_indicator : 1;
+ uint8_t copyright : 1;
+ uint8_t original_or_copy : 1;
+ uint8_t PTS_flag : 1;
+ uint8_t DTS_flag : 1;
+ uint8_t ESCR_flag : 1;
+ uint8_t ES_rate_flag : 1;
+ uint8_t DSM_trick_mode_flag : 1;
+ uint8_t additionnal_copy_info_flag : 1;
+ uint8_t PES_CRC_flag : 1;
+ uint8_t PES_extension_flag : 1;
+ uint8_t PES_header_data_len;
+} PES_header_data_content;
+
+typedef struct {
+ uint32_t identifier;
+ uint64_t scr;
+ uint16_t scr_ext;
+ uint32_t program_mux_rate;
+ int64_t pts;
+ int64_t dts;
+} packet_info;
+
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// Exception
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+class VobParserException : public std::runtime_error
+{
+public:
+ VobParserException(const char* message) : std::runtime_error(message) {=
}
+ virtual ~VobParserException() throw() {}
+};
+
+class VobParserFileNotFoundException : public VobParserException
+{
+public:
+ VobParserFileNotFoundException(const char* filename)
+ : VobParserException(qPrintable(QString("File not found exception : %1=
").arg(filename)))
+ {
+ }
+};
+
+class VobParserFileOpenException : public VobParserException
+{
+public:
+ VobParserFileOpenException(const char* filename)
+ : VobParserException(qPrintable(QString("Could not open/create file: %=
1").arg(filename)))
+ {
+ }
+};
+
+class VobParserInvalidPacketException : public VobParserException
+{
+public:
+ VobParserInvalidPacketException(int offset)
+ : VobParserException(qPrintable(QString("Invalid packet exception @LBA=
%1").arg(offset)))
+ {
+ }
+};
+
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// Demuxer class
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+class Demuxer
+{
+public:
+ virtual ~Demuxer() {}
+ virtual void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start=
_time, uint32_t end_time, const QString & debug) =3D 0;
+ virtual void SetBoundary(uint32_t start_timecode, uint32_t duration, co=
nst CellListElem *cell) =3D 0;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class Writer : public Demuxer
+{
+public:
+ Writer(const QString& filenamePrefix, const QString& extension, double =
fps)
+ :m_Filename(filenamePrefix)
+ ,m_fileExtension(extension)
+ ,m_file(NULL)
+ ,m_TimecodeFile(NULL)
+ ,m_fps(fps)
+ {
+ }
+
+ virtual ~Writer()
+ {
+ if(m_file)
+ {
+ fclose(m_file);
+ }
+ if (m_TimecodeFile)
+ fclose(m_TimecodeFile);
+ }
+
+ virtual void Write(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+ {
+ m_file =3D OpenOuputFile();
+ WriteTimecodeInfo(start_time, end_time, ftell(m_file), debug);
+ fwrite(buff, 1, size, m_file);
+ }
+
+ bool FileExists() const {
+ return m_file !=3D NULL;
+ }
+
+protected:
+ inline FILE* GetTimecodeFile()
+ {
+ if (!m_TimecodeFile)
+ {
+ QString m_filename =3D QString("%1_%2.tmc").arg(m_Filename).arg(m_fil=
eExtension);
+ m_TimecodeFile =3D fopen(QFile::encodeName(m_filename),"w");
+ =09
+ if (!m_TimecodeFile)
+ throw VobParserFileOpenException(QFile::encodeName(m_filename));
+ =09
+ fwrite("# timecode format v3\n", 1, 21, m_TimecodeFile);
+ fprintf(m_TimecodeFile, "assume %lf\n", m_fps);
+ }
+ return m_TimecodeFile;
+ }
+
+ inline FILE* OpenOuputFile()
+ {
+ if(!m_file)
+ {
+ QString m_filename =3D QString("%1.%2").arg(m_Filename).arg(m_fileExt=
ension);
+ m_file =3D fopen(QFile::encodeName(m_filename),"wb");
+
+ if (!m_file)
+ throw VobParserFileOpenException(QFile::encodeName(m_filename));
+ }
+ return m_file;
+ }
+
+ QString m_Filename;
+ QString m_fileExtension;
+ FILE* m_file;
+ FILE* m_TimecodeFile;
+ double m_fps;
+
+ virtual void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, =
uint64_t filepos, const QString& debug) =3D 0;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class VideoDemuxWriter : public Writer
+{
+public:
+ VideoDemuxWriter(const QString& filenamePrefix, double fps)
+ :Writer(filenamePrefix, "m2v", fps)=20
+ ,m_end_timecode(0)
+ ,m_last_start_timecode(0)
+ ,m_last_end_timecode(0)
+ ,m_is_still(false)
+ ,m_parser(NULL)
+ {}
+ void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug);
+ void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+ ~VideoDemuxWriter();
+protected:
+ void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
filepos, const QString& debug);
+ uint32_t m_start_timecode;
+ uint32_t m_end_timecode;
+ uint32_t m_last_start_timecode;
+ uint32_t m_last_end_timecode;
+ bool m_is_still;
+
+ M2VParser * m_parser;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class AC3DemuxWriter : public Writer
+{
+public:
+ AC3DemuxWriter(const QString& filenamePrefix, const uint8_t streamID)
+ :Writer(filenamePrefix, "ac3", 0.0)
+ ,m_streamID(streamID)
+ ,m_end_timecode(0)
+ ,m_last_start_timecode(0)
+ ,m_last_end_timecode(0)
+ {}
+ ~AC3DemuxWriter();
+ void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+ {
+ Write(buff,size, start_time, end_time, debug);
+ }
+ void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+private:
+ uint8_t m_streamID;
+protected:
+ void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
filepos, const QString& debug);
+ uint32_t m_start_timecode;
+ uint32_t m_end_timecode;
+ uint32_t m_last_start_timecode;
+ uint32_t m_last_end_timecode;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class DTSDemuxWriter : public Writer
+{
+public:
+ DTSDemuxWriter(const QString& filenamePrefix, const uint8_t streamID)
+ :Writer(filenamePrefix, "dts",0.0)
+ ,m_streamID(streamID)
+ ,m_end_timecode(0)
+ ,m_last_start_timecode(0)
+ ,m_last_end_timecode(0)
+ {}
+ ~DTSDemuxWriter();
+ void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+ {
+ Write(buff,size, start_time, end_time, debug);
+ }
+ void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+private:
+ uint8_t m_streamID;
+protected:
+ void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
filepos, const QString& debug);
+ uint32_t m_start_timecode;
+ uint32_t m_end_timecode;
+ uint32_t m_last_start_timecode;
+ uint32_t m_last_end_timecode;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class WavWriter : public Writer
+{
+ public:
+ WavWriter(const QString& filenamePrefix, double fps, uint32_t sample_r=
ate, uint8_t bit_depth, uint8_t channel_nb)
+ :Writer(filenamePrefix, "wav", fps)
+ ,m_sample_rate(sample_rate)
+ ,m_bit_depth(bit_depth)
+ ,m_channel_nb(channel_nb)
+ {}
+ ~WavWriter();
+ void Write(uint8_t* buff, uint32_t size, uint32_t start_time, uint32_t=
end_time, const QString& debug);
+ protected:
+ uint32_t m_sample_rate;
+ uint8_t m_bit_depth, m_channel_nb;
+ size_t m_size_position1,m_size_position2, m_size;
+};
+
+class LPCMDemuxWriter : public WavWriter
+{
+public:
+ LPCMDemuxWriter(const QString& filenamePrefix, const uint8_t streamID, =
uint32_t sample_rate, uint8_t bit_depth, uint8_t channel_nb)
+ :WavWriter(filenamePrefix,0.0, sample_rate, bit_depth, channel_nb)
+ ,m_streamID(streamID)
+ ,m_end_timecode(0)
+ ,m_last_start_timecode(0)
+ ,m_last_end_timecode(0)
+ {}
+ ~LPCMDemuxWriter();
+ void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+ {
+ Write(buff,size, start_time, end_time, debug);
+ }
+ void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+private:
+ uint8_t m_streamID;
+protected:
+ void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
filepos, const QString& debug);
+ uint32_t m_start_timecode;
+ uint32_t m_end_timecode;
+ uint32_t m_last_start_timecode;
+ uint32_t m_last_end_timecode;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class MPADemuxWriter : public Writer
+{
+public:
+ MPADemuxWriter(const QString& filenamePrefix, const uint8_t streamID) :
+ Writer(filenamePrefix, "mpa",0.0), m_streamID(streamID) {}
+ void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+ {
+ Write(buff,size, start_time, end_time, debug);
+ }
+ void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+private:
+ uint8_t m_streamID;
+protected:
+ void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
filepos, const QString& debug);
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class SubDemuxWriter : public Writer
+{
+public:
+ SubDemuxWriter(const QString& filenamePrefix, const uint8_t streamID, u=
int16_t width, uint16_t height, const uint32_t * palette, uint16_t langua=
ge, bool forced)
+ :Writer(filenamePrefix, "sub",0.0)
+ ,m_width(width)
+ ,m_height(height)
+ ,m_forced(forced)
+ ,m_palette(palette)
+ ,m_language(language)
+ ,m_start_timecode(0)
+ ,m_end_timecode(0)
+ {}
+ void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+ {
+ Write(buff,size, start_time, end_time, debug);
+ }
+ void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+protected:
+ void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
filepos, const QString& debug);
+private:
+ uint16_t m_width;
+ uint16_t m_height;
+ bool m_forced;
+ const uint32_t * m_palette;
+ uint16_t m_language;
+ uint32_t m_start_timecode;
+ uint32_t m_end_timecode;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class BtnDemuxWriter : public Writer
+{
+public:
+ BtnDemuxWriter(const QString& filenamePrefix, uint16_t width, uint16_t =
height)
+ :Writer(filenamePrefix, "btn",0.0)
+ ,m_width(width)
+ ,m_height(height)
+ ,m_end_timecode(0)
+ ,m_last_start_timecode(0)
+ ,m_last_end_timecode(0)
+ {}
+ void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+ {
+ if (!m_file) {
+ m_file =3D OpenOuputFile();
+ fwrite("butonDVD", 8, 1, m_file);
+ uint8_t _tmp[4];
+ // width & height
+ _tmp[0] =3D m_width >> 8;
+ _tmp[1] =3D m_width & 0xFF;
+ _tmp[2] =3D m_height >> 8;
+ _tmp[3] =3D m_height & 0xFF;
+ fwrite(_tmp, 4, 1, m_file);
+ // pad to 16 bytes
+ _tmp[0] =3D 0;
+ _tmp[1] =3D 0;
+ _tmp[2] =3D 0;
+ _tmp[3] =3D 0;
+ fwrite(_tmp, 4, 1, m_file);
+ }
+ Write(buff,size, start_time, end_time, debug);
+ }
+ void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+ ~BtnDemuxWriter();
+protected:
+ void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
filepos, const QString& debug);
+ uint16_t m_width, m_height;
+ uint32_t m_start_timecode;
+ uint32_t m_end_timecode;
+ uint32_t m_last_start_timecode;
+ uint32_t m_last_end_timecode;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class CompositeDemuxWriter
+{
+public:
+ CompositeDemuxWriter();
+ ~CompositeDemuxWriter();
+ bool AddDemuxer(uint8_t streamID, Writer * demuxer, QString& CommandLin=
e);
+ void ProcessStream(int streamID, uint8_t* buff, uint32_t size, int32_t =
start_time, int32_t end_time, const QString& debug);
+ void Reset();
+ void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+
+ bool FileExists(uint8_t streamID) const {
+ return (m_muxers[streamID] !=3D NULL && m_muxers[streamID]->FileExists=
());
+ }
+
+ const QString& GetString(uint8_t streamID) const {
+ return m_strings[streamID];
+ }
+
+protected:
+ Writer * m_muxers[256];
+ QString m_strings[256];
+};
+
+// ---------------------------------------------------------------------=
-------
+
+struct stream_info_node
+{
+ uint8_t id;
+ uint32_t type;
+ stream_info_node* next;
+};
+
+
+// ---------------------------------------------------------------------=
-------
+
+typedef struct=20
+{
+ int x1;
+ int y1;
+ int x2;
+ int y2;
+} ButtonListElem;
+
+typedef QList<ButtonListElem *> ButtonListType;
+
+
+// ---------------------------------------------------------------------=
-------
+
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// Main class
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+class IFOFile;
+class CellsListType;
+
+class VobParser
+{
+public:
+ VobParser(const char* dirname, int16_t title, bool menu);
+ void Reset();
+ bool ParseNextPacket(const CellsListType & Cells);
+ uint32_t GetPacketCount() const;
+ uint32_t GetPacketIndex() const;
+ char* GetCurrentPacketData() const;
+ inline uint8_t GetVobID() const;
+ inline uint8_t GetCellID() const;
+ bool IsNewCell();
+ virtual ~VobParser();
+ inline CompositeDemuxWriter & GetDemuxer()
+ {
+ return m_demuxer;
+ }
+ uint32_t GetCellSCR() const;
+
+ nav_dsi_gi m_dsi;
+ nav_pci_gi m_pci;
+ packet_info pktinfo;
+ PES_header_data_content pes_header_data_content;
+protected:
+ void ParseNavPacket();
+ void ParseAudioPacket(int StreamID);
+ void ParseVideoPacket();
+ void ParsePrivateStream1();
+
+ void ParseSCR();
+ void ParsePCI();
+ void ParseDSI();
+ void ParsePESHeaderDataContentFlag();
+ void ParsePESHeaderData();
+ uint64_t ParsePTS_DTS();
+
+ // Buffer management
+ bool AvailablePacketData() const;
+ bool GetNextPacket();
+ uint32_t GetNext32Bits();
+ uint16_t GetNext16Bits();
+ uint8_t GetNext8Bits();
+ void SkipNBytes(int n);
+
+private:
+ int16_t m_title;
+ dvd_reader_t *m_dvdhandle;
+ dvd_file_t *m_stream;
+ bool m_language;
+ uint8_t m_buff[DVD_VIDEO_LB_LEN];
+ uint32_t m_index;
+ uint32_t m_pktindex;
+ uint32_t m_pktcount;
+ bool m_bFirstPacket;
+ int64_t m_startpts;
+ int64_t m_startdts;
+ uint16_t m_pci_position;
+ uint16_t m_pci_size;
+ uint32_t m_pci_vob_timecode_offset;
+=09
+ CompositeDemuxWriter m_demuxer;
+
+ int previous_vobid, previous_cellid;
+};
+
+// ---------------------------------------------------------------------=
-------
+#endif
+// ---------------------------------------------------------------------=
-------
Added: trunk/DvdMenuXtractor/dmx/vobparser/iso/iso-639.def
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx/vobparser/iso/iso-639.def 2007-03-10 21:45:=
28 UTC (rev 1291)
+++ trunk/DvdMenuXtractor/dmx/vobparser/iso/iso-639.def 2007-03-10 21:46:=
03 UTC (rev 1292)
@@ -0,0 +1,173 @@
+/*
+ * Defines the languages codes and abbreviations according to ISO 639-[1=
2].
+ * This is used in iso_lang.cpp and is taken from the GNU glibc 2.2.5 ta=
rball.
+ * It has been partially completed with native language name.
+ *
+ * Format is: ("English name", 639-1-code, 639-2/T-code, 639-2/B-code)
+ * If you find something missing or wrong contact <bug-glibc at gnu.org>
+ */
+
+DEFINE_LANGUAGE_CODE ("Afar", "", aa, aar, aar)
+DEFINE_LANGUAGE_CODE ("Abkhazian", "", ab, abk, abk)
+DEFINE_LANGUAGE_CODE ("Afrikaans", "", af, afr, afr)
+DEFINE_LANGUAGE_CODE ("Albanian", "", sq, sqi, alb)
+DEFINE_LANGUAGE_CODE ("Amharic", "", am, amh, amh)
+DEFINE_LANGUAGE_CODE ("Arabic", "", ar, ara, ara)
+DEFINE_LANGUAGE_CODE ("Armenian", "", hy, hye, arm)
+DEFINE_LANGUAGE_CODE ("Assamese", "", as, asm, asm)
+DEFINE_LANGUAGE_CODE ("Avestan", "", ae, ave, ave)
+DEFINE_LANGUAGE_CODE ("Aymara", "", ay, aym, aym)
+DEFINE_LANGUAGE_CODE ("Azerbaijani", "", az, aze, aze)
+DEFINE_LANGUAGE_CODE ("Bashkir", "", ba, bak, bak)
+DEFINE_LANGUAGE_CODE ("Basque", "", eu, eus, baq)
+DEFINE_LANGUAGE_CODE ("Belarusian", "", be, bel, bel)
+DEFINE_LANGUAGE_CODE ("Bengali", "", bn, ben, ben)
+DEFINE_LANGUAGE_CODE ("Bihari", "", bh, bih, bih)
+DEFINE_LANGUAGE_CODE ("Bislama", "", bi, bis, bis)
+DEFINE_LANGUAGE_CODE ("Bosnian", "", bs, bos, bos)
+DEFINE_LANGUAGE_CODE ("Breton", "", br, bre, bre)
+DEFINE_LANGUAGE_CODE ("Bulgarian", "", bg, bul, bul)
+DEFINE_LANGUAGE_CODE ("Burmese", "", my, mya, bur)
+DEFINE_LANGUAGE_CODE ("Catalan", "", ca, cat, cat)
+DEFINE_LANGUAGE_CODE ("Chamorro", "", ch, cha, cha)
+DEFINE_LANGUAGE_CODE ("Chechen", "", ce, che, che)
+DEFINE_LANGUAGE_CODE ("Chinese", "", zh, zho, chi)
+DEFINE_LANGUAGE_CODE ("Church Slavic", "", cu, chu, chu)
+DEFINE_LANGUAGE_CODE ("Chuvash", "", cv, chv, chv)
+DEFINE_LANGUAGE_CODE ("Cornish", "", kw, cor, cor)
+DEFINE_LANGUAGE_CODE ("Corsican", "", co, cos, cos)
+DEFINE_LANGUAGE_CODE ("Czech", "", cs, ces, cze)
+DEFINE_LANGUAGE_CODE ("Danish", "Dansk", da, dan, dan)
+DEFINE_LANGUAGE_CODE ("Dutch", "Nederlands", nl, nld, dut)
+DEFINE_LANGUAGE_CODE ("Dzongkha", "", dz, dzo, dzo)
+DEFINE_LANGUAGE_CODE ("English", "English", en, eng, eng)
+DEFINE_LANGUAGE_CODE ("Esperanto", "", eo, epo, epo)
+DEFINE_LANGUAGE_CODE ("Estonian", "", et, est, est)
+DEFINE_LANGUAGE_CODE ("Faroese", "", fo, fao, fao)
+DEFINE_LANGUAGE_CODE ("Fijian", "", fj, fij, fij)
+DEFINE_LANGUAGE_CODE ("Finnish", "Suomi", fi, fin, fin)
+DEFINE_LANGUAGE_CODE ("French", "Francais", fr, fra, fre)
+DEFINE_LANGUAGE_CODE ("Frisian", "", fy, fry, fry)
+DEFINE_LANGUAGE_CODE ("Georgian", "", ka, kat, geo)
+DEFINE_LANGUAGE_CODE ("German", "Deutsch", de, deu, ger)
+DEFINE_LANGUAGE_CODE ("Gaelic (Scots)", "", gd, gla, gla)
+DEFINE_LANGUAGE_CODE ("Irish", "", ga, gle, gle)
+DEFINE_LANGUAGE_CODE ("Gallegan", "", gl, glg, glg)
+DEFINE_LANGUAGE_CODE ("Manx", "", gv, glv, glv)
+DEFINE_LANGUAGE_CODE ("Greek, Modern ()", "", el, gre, ell)
+DEFINE_LANGUAGE_CODE ("Guarani", "", gn, grn, grn)
+DEFINE_LANGUAGE_CODE ("Gujarati", "", gu, guj, guj)
+DEFINE_LANGUAGE_CODE ("Hebrew", "", he, heb, heb)
+DEFINE_LANGUAGE_CODE ("Herero", "", hz, her, her)
+DEFINE_LANGUAGE_CODE ("Hindi", "", hi, hin, hin)
+DEFINE_LANGUAGE_CODE ("Hiri Motu", "", ho, hmo, hmo)
+DEFINE_LANGUAGE_CODE ("Hungarian", "Magyar", hu, hun, hun)
+DEFINE_LANGUAGE_CODE ("Icelandic", "Islenska", is, isl, ice)
+DEFINE_LANGUAGE_CODE ("Inuktitut", "", iu, iku, iku)
+DEFINE_LANGUAGE_CODE ("Interlingue", "", ie, ile, ile)
+DEFINE_LANGUAGE_CODE ("Interlingua", "", ia, ina, ina)
+DEFINE_LANGUAGE_CODE ("Indonesian", "", id, ind, ind)
+DEFINE_LANGUAGE_CODE ("Inupiaq", "", ik, ipk, ipk)
+DEFINE_LANGUAGE_CODE ("Italian", "Italiano", it, ita, ita)
+DEFINE_LANGUAGE_CODE ("Javanese", "", jv, jaw, jav)
+DEFINE_LANGUAGE_CODE ("Japanese", "", ja, jpn, jpn)
+DEFINE_LANGUAGE_CODE ("Kalaallisut (Greenlandic)", "", kl, kal, kal)
+DEFINE_LANGUAGE_CODE ("Kannada", "", kn, kan, kan)
+DEFINE_LANGUAGE_CODE ("Kashmiri", "", ks, kas, kas)
+DEFINE_LANGUAGE_CODE ("Kazakh", "", kk, kaz, kaz)
+DEFINE_LANGUAGE_CODE ("Khmer", "", km, khm, khm)
+DEFINE_LANGUAGE_CODE ("Kikuyu", "", ki, kik, kik)
+DEFINE_LANGUAGE_CODE ("Kinyarwanda", "", rw, kin, kin)
+DEFINE_LANGUAGE_CODE ("Kirghiz", "", ky, kir, kir)
+DEFINE_LANGUAGE_CODE ("Komi", "", kv, kom, kom)
+DEFINE_LANGUAGE_CODE ("Korean", "", ko, kor, kor)
+DEFINE_LANGUAGE_CODE ("Kuanyama", "", kj, kua, kua)
+DEFINE_LANGUAGE_CODE ("Kurdish", "", ku, kur, kur)
+DEFINE_LANGUAGE_CODE ("Lao", "", lo, lao, lao)
+DEFINE_LANGUAGE_CODE ("Latin", "", la, lat, lat)
+DEFINE_LANGUAGE_CODE ("Latvian", "", lv, lav, lav)
+DEFINE_LANGUAGE_CODE ("Lingala", "", ln, lin, lin)
+DEFINE_LANGUAGE_CODE ("Lithuanian", "", lt, lit, lit)
+DEFINE_LANGUAGE_CODE ("Letzeburgesch", "", lb, ltz, ltz)
+DEFINE_LANGUAGE_CODE ("Macedonian", "", mk, mkd, mac)
+DEFINE_LANGUAGE_CODE ("Marshall", "", mh, mah, mah)
+DEFINE_LANGUAGE_CODE ("Malayalam", "", ml, mal, mal)
+DEFINE_LANGUAGE_CODE ("Maori", "", mi, mri, mao)
+DEFINE_LANGUAGE_CODE ("Marathi", "", mr, mar, mar)
+DEFINE_LANGUAGE_CODE ("Malay", "", ms, msa, may)
+DEFINE_LANGUAGE_CODE ("Malagasy", "", mg, mlg, mlg)
+DEFINE_LANGUAGE_CODE ("Maltese", "", mt, mlt, mlt)
+DEFINE_LANGUAGE_CODE ("Moldavian", "", mo, mol, mol)
+DEFINE_LANGUAGE_CODE ("Mongolian", "", mn, mon, mon)
+DEFINE_LANGUAGE_CODE ("Nauru", "", na, nau, nau)
+DEFINE_LANGUAGE_CODE ("Navajo", "", nv, nav, nav)
+DEFINE_LANGUAGE_CODE ("Ndebele, South", "", nr, nbl, nbl)
+DEFINE_LANGUAGE_CODE ("Ndebele, North", "", nd, nde, nde)
+DEFINE_LANGUAGE_CODE ("Ndonga", "", ng, ndo, ndo)
+DEFINE_LANGUAGE_CODE ("Nepali", "", ne, nep, nep)
+DEFINE_LANGUAGE_CODE ("Norwegian", "Norsk", no, nor, nor)
+DEFINE_LANGUAGE_CODE ("Norwegian Nynorsk", "", nn, nno, nno)
+DEFINE_LANGUAGE_CODE ("Norwegian Bokm=E5l", "", nb, nob, nob)
+DEFINE_LANGUAGE_CODE ("Chichewa; Nyanja", "", ny, nya, nya)
+DEFINE_LANGUAGE_CODE ("Occitan (post 1500); Proven=E7al", "", oc, oci, o=
ci)
+DEFINE_LANGUAGE_CODE ("Oriya", "", or, ori, ori)
+DEFINE_LANGUAGE_CODE ("Oromo", "", om, orm, orm)
+DEFINE_LANGUAGE_CODE ("Ossetian; Ossetic", "", os, oss, oss)
+DEFINE_LANGUAGE_CODE ("Panjabi", "", pa, pan, pan)
+DEFINE_LANGUAGE_CODE ("Persian", "", fa, fas, per)
+DEFINE_LANGUAGE_CODE ("Pali", "", pi, pli, pli)
+DEFINE_LANGUAGE_CODE ("Polish", "", pl, pol, pol)
+DEFINE_LANGUAGE_CODE ("Portuguese", "Portugues", pt, por, por)
+DEFINE_LANGUAGE_CODE ("Pushto", "", ps, pus, pus)
+DEFINE_LANGUAGE_CODE ("Quechua", "", qu, que, que)
+DEFINE_LANGUAGE_CODE ("Raeto-Romance", "", rm, roh, roh)
+DEFINE_LANGUAGE_CODE ("Romanian", "", ro, ron, rum)
+DEFINE_LANGUAGE_CODE ("Rundi", "", rn, run, run)
+DEFINE_LANGUAGE_CODE ("Russian", "", ru, rus, rus)
+DEFINE_LANGUAGE_CODE ("Sango", "", sg, sag, sag)
+DEFINE_LANGUAGE_CODE ("Sanskrit", "", sa, san, san)
+DEFINE_LANGUAGE_CODE ("Serbian", "", sr, srp, scc)
+DEFINE_LANGUAGE_CODE ("Croatian", "Hrvatski", hr, hrv, scr)
+DEFINE_LANGUAGE_CODE ("Sinhalese", "", si, sin, sin)
+DEFINE_LANGUAGE_CODE ("Slovak", "", sk, slk, slo)
+DEFINE_LANGUAGE_CODE ("Slovenian", "", sl, slv, slv)
+DEFINE_LANGUAGE_CODE ("Northern Sami", "", se, sme, sme)
+DEFINE_LANGUAGE_CODE ("Samoan", "", sm, smo, smo)
+DEFINE_LANGUAGE_CODE ("Shona", "", sn, sna, sna)
+DEFINE_LANGUAGE_CODE ("Sindhi", "", sd, snd, snd)
+DEFINE_LANGUAGE_CODE ("Somali", "", so, som, som)
+DEFINE_LANGUAGE_CODE ("Sotho, Southern", "", st, sot, sot)
+DEFINE_LANGUAGE_CODE ("Spanish", "Espanol", es, spa, spa)
+DEFINE_LANGUAGE_CODE ("Sardinian", "", sc, srd, srd)
+DEFINE_LANGUAGE_CODE ("Swati", "", ss, ssw, ssw)
+DEFINE_LANGUAGE_CODE ("Sundanese", "", su, sun, sun)
+DEFINE_LANGUAGE_CODE ("Swahili", "", sw, swa, swa)
+DEFINE_LANGUAGE_CODE ("Swedish", "Svenska", sv, swe, swe)
+DEFINE_LANGUAGE_CODE ("Tahitian", "", ty, tah, tah)
+DEFINE_LANGUAGE_CODE ("Tamil", "", ta, tam, tam)
+DEFINE_LANGUAGE_CODE ("Tatar", "", tt, tat, tat)
+DEFINE_LANGUAGE_CODE ("Telugu", "", te, tel, tel)
+DEFINE_LANGUAGE_CODE ("Tajik", "", tg, tgk, tgk)
+DEFINE_LANGUAGE_CODE ("Tagalog", "", tl, tgl, tgl)
+DEFINE_LANGUAGE_CODE ("Thai", "", th, tha, tha)
+DEFINE_LANGUAGE_CODE ("Tibetan", "", bo, bod, tib)
+DEFINE_LANGUAGE_CODE ("Tigrinya", "", ti, tir, tir)
+DEFINE_LANGUAGE_CODE ("Tonga (Tonga Islands)", "", to, ton, ton)
+DEFINE_LANGUAGE_CODE ("Tswana", "", tn, tsn, tsn)
+DEFINE_LANGUAGE_CODE ("Tsonga", "", ts, tso, tso)
+DEFINE_LANGUAGE_CODE ("Turkish", "", tr, tur, tur)
+DEFINE_LANGUAGE_CODE ("Turkmen", "", tk, tuk, tuk)
+DEFINE_LANGUAGE_CODE ("Twi", "", tw, twi, twi)
+DEFINE_LANGUAGE_CODE ("Uighur", "", ug, uig, uig)
+DEFINE_LANGUAGE_CODE ("Ukrainian", "", uk, ukr, ukr)
+DEFINE_LANGUAGE_CODE ("Urdu", "", ur, urd, urd)
+DEFINE_LANGUAGE_CODE ("Uzbek", "", uz, uzb, uzb)
+DEFINE_LANGUAGE_CODE ("Vietnamese", "", vi, vie, vie)
+DEFINE_LANGUAGE_CODE ("Volap=FCk", "", vo, vol, vol)
+DEFINE_LANGUAGE_CODE ("Welsh", "", cy, cym, wel)
+DEFINE_LANGUAGE_CODE ("Wolof", "", wo, wol, wol)
+DEFINE_LANGUAGE_CODE ("Xhosa", "", xh, xho, xho)
+DEFINE_LANGUAGE_CODE ("Yiddish", "", yi, yid, yid)
+DEFINE_LANGUAGE_CODE ("Yoruba", "", yo, yor, yor)
+DEFINE_LANGUAGE_CODE ("Zhuang", "", za, zha, zha)
+DEFINE_LANGUAGE_CODE ("Zulu", "", zu, zul, zul)
Added: trunk/DvdMenuXtractor/dmx/vobparser/iso/iso_lang.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx/vobparser/iso/iso_lang.c 2007-03-10 21:45:2=
8 UTC (rev 1291)
+++ trunk/DvdMenuXtractor/dmx/vobparser/iso/iso_lang.c 2007-03-10 21:46:0=
3 UTC (rev 1292)
@@ -0,0 +1,113 @@
+/***********************************************************************=
******
+ * iso_lang.c: function to decode language code (in dvd or a52 for insta=
nce).
+ ***********************************************************************=
******
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: iso_lang.c,v 1.6 2002/06/01 12:32:01 sam Exp $
+ *
+ * Author: St=E9phane Borel <stef at via.ecp.fr>
+ * Arnaud de Bossoreille de Ribou <bozo at via.ecp.fr>
+ *
+ * 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.
+ *=20
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA=
.
+ ***********************************************************************=
******/
+
+/***********************************************************************=
******
+ * Preamble
+ ***********************************************************************=
******/
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include "iso_lang.h"
+
+/***********************************************************************=
******
+ * Local tables
+ ***********************************************************************=
******/
+
+#define DEFINE_LANGUAGE_CODE(engName, nativeName, iso1, iso2T, iso2B) \
+ { engName, nativeName, #iso1, #iso2T, #iso2B },
+
+static const iso639_lang_t p_languages[] =3D
+{
+#include "iso-639.def"
+ { NULL, NULL, NULL, NULL, NULL }
+};
+
+static const iso639_lang_t unknown_language =3D
+ { "Unknown", "Unknown", "??", "???", "???" };
+
+/***********************************************************************=
******
+ * DecodeLanguage: gives the long language name from the two-letter
+ * ISO-639 code
+ ***********************************************************************=
******/
+const char * DecodeLanguage( uint16_t i_code )
+{
+ const iso639_lang_t * p_lang;
+ uint8_t psz_code[3];
+
+ if (i_code !=3D 0)
+ {
+ psz_code[0] =3D (uint8_t)(i_code >> 8);
+ psz_code[1] =3D (uint8_t)i_code;
+ psz_code[2] =3D '\0';
+
+ for( p_lang =3D p_languages; p_lang->psz_eng_name; p_lang++ )
+ {
+ if( !strncmp( p_lang->psz_iso639_1, psz_code, 2 ) )
+ {
+ if( *p_lang->psz_native_name )
+ {
+ return p_lang->psz_native_name;
+ }
+
+ return p_lang->psz_eng_name;
+ }
+ }
+ }
+
+ return "Unknown";
+}
+
+const iso639_lang_t * GetLang_1( const char * psz_code )
+{
+ const iso639_lang_t *p_lang;
+
+ for( p_lang =3D p_languages; p_lang->psz_eng_name; p_lang++ )
+ if( !strncmp( p_lang->psz_iso639_1, psz_code, 2 ) )
+ return p_lang;
+
+ return &unknown_language;
+}
+
+const iso639_lang_t * GetLang_2T( const char * psz_code )
+{
+ const iso639_lang_t *p_lang;
+ =20
+ for( p_lang =3D p_languages; p_lang->psz_eng_name; p_lang++ )
+ if( !strncmp( p_lang->psz_iso639_2T, psz_code, 3 ) )
+ return p_lang;
+
+ return &unknown_language;
+}
+
+const iso639_lang_t * GetLang_2B( const char * psz_code )
+{
+ const iso639_lang_t *p_lang;
+
+ for( p_lang =3D p_languages; p_lang->psz_eng_name; p_lang++ )
+ if( !strncmp( p_lang->psz_iso639_2B, psz_code, 3 ) )
+ return p_lang;
+
+ return &unknown_language;
+}
+
Added: trunk/DvdMenuXtractor/dmx/vobparser/iso/iso_lang.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx/vobparser/iso/iso_lang.h 2007-03-10 21:45:2=
8 UTC (rev 1291)
+++ trunk/DvdMenuXtractor/dmx/vobparser/iso/iso_lang.h 2007-03-10 21:46:0=
3 UTC (rev 1292)
@@ -0,0 +1,51 @@
+/***********************************************************************=
******
+ * iso_lang.h: function to decode language code (in dvd or a52 for insta=
nce).
+ ***********************************************************************=
******
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: iso_lang.h,v 1.5 2002/05/20 22:36:42 sam Exp $
+ *
+ * Author: St=E9phane Borel <stef at via.ecp.fr>
+ * Arnaud de Bossoreille de Ribou <bozo at via.ecp.fr>
+ *
+ * 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.
+ *=20
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA=
.
+ ***********************************************************************=
******/
+
+#ifndef _ISO_LANG_H_
+#define _ISO_LANG_H_
+
+struct iso639_lang_s
+{
+ char * psz_eng_name; /* Description in English */
+ char * psz_native_name; /* Description in native language */
+ char * psz_iso639_1; /* ISO-639-1 (2 characters) code */
+ char * psz_iso639_2T; /* ISO-639-2/T (3 characters) English co=
de */
+ char * psz_iso639_2B; /* ISO-639-2/B (3 characters) native cod=
e */
+};
+
+typedef struct iso639_lang_s iso639_lang_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const iso639_lang_t * GetLang_1( const char * psz_iso639_1 );
+const iso639_lang_t * GetLang_2T( const char * psz_iso639_2T );
+const iso639_lang_t * GetLang_2B( const char * psz_iso639_2B );
+const char * DecodeLanguage( uint16_t );
+
+#ifdef __cplusplus
+};
+#endif
+#endif // _ISO_LANG_H_
Added: trunk/DvdMenuXtractor/dmx/vobparser/vobparser.proj
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx/vobparser/vobparser.proj 2007-03-10 21:45:2=
8 UTC (rev 1291)
+++ trunk/DvdMenuXtractor/dmx/vobparser/vobparser.proj 2007-03-10 21:46:0=
3 UTC (rev 1292)
@@ -0,0 +1,14 @@
+GROUP vobparser
+{
+ SOURCE IFOContent.cpp
+ SOURCE IFOFile.cpp
+ SOURCE VobParser.cpp
+ SOURCE iso/iso_lang.c
+
+ HEADER IFOContent.h
+ HEADER IFOFile.h
+ HEADER VobParser.h
+ HEADER iso/iso_lang.h
+ =20
+ INCLUDE ..
+}
More information about the Matroska-cvs
mailing list