[matroska] r1291 - in trunk/DvdMenuXtractor/dmx: . mpegparser

[email protected] Sun, 11 Mar 2007 00:45:49 +0300 (MSK)
Newsgroups gmane.comp.multimedia.matroska.cvs
Message-ID <[email protected]>
Author: smssms
Date: 2007-03-11 00:45:28 +0300 (Sun, 11 Mar 2007)
New Revision: 1291

Added:
   trunk/DvdMenuXtractor/dmx/mpegparser/
   trunk/DvdMenuXtractor/dmx/mpegparser/CircBuffer.cpp
   trunk/DvdMenuXtractor/dmx/mpegparser/CircBuffer.h
   trunk/DvdMenuXtractor/dmx/mpegparser/M2VParser.cpp
   trunk/DvdMenuXtractor/dmx/mpegparser/M2VParser.h
   trunk/DvdMenuXtractor/dmx/mpegparser/MPEGVideoBuffer.cpp
   trunk/DvdMenuXtractor/dmx/mpegparser/MPEGVideoBuffer.h
   trunk/DvdMenuXtractor/dmx/mpegparser/Types.h
   trunk/DvdMenuXtractor/dmx/mpegparser/mpegparser.proj
Log:


Added: trunk/DvdMenuXtractor/dmx/mpegparser/CircBuffer.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/mpegparser/CircBuffer.cpp	2007-03-10 21:41:=
34 UTC (rev 1290)
+++ trunk/DvdMenuXtractor/dmx/mpegparser/CircBuffer.cpp	2007-03-10 21:45:=
28 UTC (rev 1291)
@@ -0,0 +1,110 @@
+/***********************************************************************=
******
+
+    Circular/Ring Buffer
+
+    Copyright(C) 2004 John Cannon <[email protected]>
+
+    This program is free software ; you can redistribute it and/or modif=
y
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation ; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY ; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program ; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307=
 USA
+
+ **/
+
+#include "CircBuffer.h"
+#include <string.h>
+#include <cassert>
+
+CircBuffer::CircBuffer(uint32_t size){
+  m_buf =3D new binary[size];
+  read_ptr =3D m_buf;
+  write_ptr =3D m_buf;
+  buf_capacity =3D size;
+  bytes_in_buf =3D 0;
+}
+
+CircBuffer::~CircBuffer(){
+  if(m_buf)
+    delete [] m_buf;
+}
+
+int32_t CircBuffer::Skip(uint32_t numBytes){
+  assert(numBytes > 0);
+  if(can_read(numBytes)){
+    uint32_t bbw =3D bytes_before_wrap_read(); //how many bytes we have =
before the buffer must be wrapped
+    if(bbw >=3D numBytes){
+      move_pointer(&read_ptr, numBytes);
+      bytes_in_buf -=3D numBytes;
+    }else{
+      if(bbw !=3D 0){
+        numBytes -=3D bbw;
+        bytes_in_buf -=3D bbw;
+        move_pointer(&read_ptr, bbw); //Reset to beginning
+      }
+      bytes_in_buf -=3D numBytes;
+      move_pointer(&read_ptr, numBytes);
+    }
+    return 0;
+  }else{
+    return -1;
+  }
+}
+
+int32_t CircBuffer::Read(binary* dest, uint32_t numBytes){
+  if(can_read(numBytes)){
+    uint32_t bbw =3D bytes_before_wrap_read(); //how many bytes we have =
before the buffer must be wrapped
+    if(bbw >=3D numBytes){
+      memcpy(dest, read_ptr, numBytes);
+      move_pointer(&read_ptr, numBytes);
+      bytes_in_buf -=3D numBytes;
+    }else{
+      if(bbw !=3D 0){
+        memcpy(dest,read_ptr,bbw);
+        numBytes -=3D bbw;
+        bytes_in_buf -=3D bbw;
+        dest +=3D bbw;
+        move_pointer(&read_ptr, bbw); //Reset to beginning
+      }
+      memcpy(dest, read_ptr,numBytes);
+      bytes_in_buf -=3D numBytes;
+      move_pointer(&read_ptr, numBytes);
+    }
+    return 0;
+  }else{
+    return -1;
+  }
+}
+
+int32_t CircBuffer::Write(binary* data, uint32_t length){
+  if(can_write(length)){
+    uint32_t bbw =3D bytes_before_wrap_write();
+    if(bbw >=3D length){
+      memcpy(write_ptr, data, length);
+      move_pointer(&write_ptr, length);
+      bytes_in_buf +=3D length;
+    }else{
+      if(bbw !=3D 0){
+        memcpy(write_ptr,data,bbw);
+        length -=3D bbw;
+        bytes_in_buf +=3D bbw;
+        data +=3D bbw;
+        move_pointer(&write_ptr, bbw); //Reset to beginning
+      }
+      memcpy(write_ptr, data,length);
+      bytes_in_buf +=3D length;
+      move_pointer(&write_ptr, length);
+    }
+    return 0;
+  }else{
+    return -1;
+  }
+}

Added: trunk/DvdMenuXtractor/dmx/mpegparser/CircBuffer.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/mpegparser/CircBuffer.h	2007-03-10 21:41:34=
 UTC (rev 1290)
+++ trunk/DvdMenuXtractor/dmx/mpegparser/CircBuffer.h	2007-03-10 21:45:28=
 UTC (rev 1291)
@@ -0,0 +1,114 @@
+/***********************************************************************=
******
+
+    Circular/Ring Buffer
+
+    Copyright(C) 2004 John Cannon <[email protected]>
+
+    This program is free software ; you can redistribute it and/or modif=
y
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation ; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY ; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program ; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307=
 USA
+
+ **/
+
+#ifndef __CIRC_BUFFER_H__
+
+#define __CIRC_BUFFER_H__
+
+#include "Types.h"
+
+class CircBuffer {
+private:
+  binary *m_buf;
+  binary *read_ptr;
+  binary *write_ptr;
+
+
+  inline uint32_t bytes_left() {
+    return buf_capacity - bytes_in_buf;
+  }
+
+  inline uint32_t bytes_before_wrap_read() {
+    int32_t a =3D (int32_t) ((m_buf + buf_capacity) - read_ptr);
+    if(a < 0)
+      return 0;
+    else
+      return a;
+  }
+
+  inline uint32_t bytes_before_wrap_write() {
+    int32_t a =3D (int32_t)((m_buf + buf_capacity) - write_ptr);
+    if(a < 0)
+      return 0;
+    else
+      return a;
+  }
+
+  inline bool can_write(uint32_t numBytes){
+    return (buf_capacity - bytes_in_buf) >=3D numBytes;
+  }
+
+  inline bool can_read(uint32_t numBytes){
+    return (bytes_in_buf) >=3D numBytes;
+  }
+
+  inline void move_pointer(binary** ptr, uint32_t numBytes){
+    *ptr +=3D numBytes;
+    if(((m_buf + buf_capacity) - *ptr) =3D=3D 0){
+      *ptr =3D m_buf;
+      //printf("Buffer wrapped\n");
+    }
+  }
+
+public:
+
+  uint32_t buf_capacity;
+  uint32_t bytes_in_buf;
+
+  CircBuffer(uint32_t size);
+  ~CircBuffer();
+
+  const binary* GetReadPtr(){
+    return read_ptr;
+  }
+
+  const binary* GetWritePtr(){
+    return read_ptr;
+  }
+
+  const binary* GetBufPtr(){
+    return read_ptr;
+  }
+
+  binary& operator[](unsigned int i){
+    if(i > bytes_in_buf){
+      return read_ptr[0];
+    }
+    uint32_t bbw =3D bytes_before_wrap_read();
+    if(i < bbw)
+      return read_ptr[i];
+    else
+      return m_buf[i - bbw];
+  }
+
+  int32_t Read(binary* dest, uint32_t numBytes);
+  int32_t Skip(uint32_t numBytes);
+  int32_t Write(binary* data, uint32_t numBytes);
+
+  uint32_t GetLength(){
+    return bytes_in_buf;
+  }
+
+};
+
+#endif // __CIRC_BUFFER_H__
+

Added: trunk/DvdMenuXtractor/dmx/mpegparser/M2VParser.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/mpegparser/M2VParser.cpp	2007-03-10 21:41:3=
4 UTC (rev 1290)
+++ trunk/DvdMenuXtractor/dmx/mpegparser/M2VParser.cpp	2007-03-10 21:45:2=
8 UTC (rev 1291)
@@ -0,0 +1,396 @@
+/***********************************************************************=
******
+
+    MPEG Video Packetizer
+
+    Copyright(C) 2004 John Cannon <[email protected]>
+
+    This program is free software ; you can redistribute it and/or modif=
y
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation ; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY ; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program ; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307=
 USA
+
+ **/
+
+#include "M2VParser.h"
+
+//#include "common.h"
+#define safemalloc(x) malloc(x)
+#define safefree(x)   free(x)
+
+#define BUFF_SIZE 2*1024*1024
+
+MPEGFrame::MPEGFrame(binary* data, uint32_t size, bool bCopy){
+  if(bCopy){
+    this->data  =3D (binary *)safemalloc(size);
+    memcpy(this->data, data, size);
+  }else{
+    this->data =3D data;
+  }
+  this->bCopy =3D bCopy;
+  this->size =3D size;
+  firstRef =3D -1;
+  secondRef =3D -1;
+  seqHdrData =3D NULL;
+  seqHdrDataSize =3D 0;
+}
+
+MPEGFrame::~MPEGFrame(){
+  safefree(data);
+  safefree(seqHdrData);
+}
+
+void M2VParser::SetEOS(){
+  MPEGChunk * c;
+  while((c =3D mpgBuf->ReadChunk())){
+    chunks.push_back(c);
+  }
+  mpgBuf->ForceFinal();  //Force the last frame out.
+  c =3D mpgBuf->ReadChunk();
+  if(c) chunks.push_back(c);
+  FillQueues();
+  m_eos =3D true;
+}
+
+
+int32_t M2VParser::WriteData(binary* data, uint32_t dataSize){
+  //If we are at EOS
+  if(m_eos)
+    return -1;
+
+  if(mpgBuf->Feed(data, dataSize)){
+    return -1;
+  }
+
+  //Fill the chunks buffer
+  while(mpgBuf->GetState() =3D=3D MPEG2_BUFFER_STATE_CHUNK_READY){
+    MPEGChunk * c =3D mpgBuf->ReadChunk();
+    if(c) chunks.push_back(c);
+  }
+
+  if(needInit){
+    if(InitParser() =3D=3D 0)
+      needInit =3D false;
+  }
+
+  FillQueues();
+  if(buffers.empty()){
+    parserState =3D MPV_PARSER_STATE_NEED_DATA;
+  }else{
+    parserState =3D MPV_PARSER_STATE_FRAME;
+  }
+
+  return 0;
+}
+
+void M2VParser::DumpQueues(){
+  while(!chunks.empty()){
+    delete chunks.front();
+    chunks.erase(chunks.begin());
+  }
+  while(!buffers.empty()){
+    delete buffers.front();
+    buffers.pop();
+  }
+}
+
+/*Fraction ConvertFramerateToFraction(float frameRate){
+  if(frameRate =3D=3D 24000/1001.0f)
+  return Fraction(24000,1001);
+  else if(frameRate =3D=3D 30000/1001.0f)
+  return Fraction(30000,1001);
+  else
+  return Fraction(frameRate);
+  }*/
+
+M2VParser::M2VParser(){
+
+  mpgBuf =3D new MPEGVideoBuffer(BUFF_SIZE);
+
+  notReachedFirstGOP =3D true;
+  currentStampingTime =3D 0;
+  position =3D 0;
+  m_eos =3D false;
+  mpegVersion =3D 1;
+  needInit =3D true;
+  parserState =3D MPV_PARSER_STATE_NEED_DATA;
+  firstRef =3D -1;
+  secondRef =3D -1;
+  nextSkip =3D -1;
+  nextSkipDuration =3D -1;
+  seqHdrChunk =3D NULL;
+  gopChunk =3D NULL;
+  keepSeqHdrsInBitstream =3D true;
+}
+
+int32_t M2VParser::InitParser(){
+  //Gotta find a sequence header now
+  MPEGChunk* chunk;
+  //MPEGChunk* seqHdrChunk;
+  for(size_t i =3D 0; i < chunks.size(); i++){
+    chunk =3D chunks[i];
+    if(chunk->GetType() =3D=3D MPEG_VIDEO_SEQUENCE_START_CODE){
+      //Copy the header for later, we must copy because the actual chunk=
 will be deleted in a bit
+      binary * hdrData =3D new binary[chunk->GetSize()];
+      memcpy(hdrData, chunk->GetPointer(), chunk->GetSize());
+      seqHdrChunk =3D new MPEGChunk(hdrData, chunk->GetSize()); //Save t=
his for adding as private data...
+      ParseSequenceHeader(chunk, m_seqHdr);
+
+      //Look for sequence extension to identify mpeg2
+      binary* pData =3D chunk->GetPointer();
+      for(size_t j =3D 3; j < chunk->GetSize() - 4; j++){
+        if(pData[j] =3D=3D 0x00 && pData[j+1] =3D=3D 0x00 && pData[j+2] =
=3D=3D 0x01 && pData[j+3] =3D=3D 0xb5 && ((pData[j+4] & 0xF0) =3D=3D 0x10=
)){
+          mpegVersion =3D 2;
+          break;
+        }
+      }
+      return 0;
+    }
+  }
+  return -1;
+}
+
+M2VParser::~M2VParser(){
+  DumpQueues();
+  delete seqHdrChunk;
+  delete gopChunk;
+  delete mpgBuf;
+}
+
+const MediaTime M2VParser::GetPosition(){
+  return position;
+}
+
+MediaTime M2VParser::GetFrameDuration(MPEG2PictureHeader picHdr){
+  if(m_seqHdr.progressiveSequence){
+    if(!picHdr.topFieldFirst && picHdr.repeatFirstField)
+      return 4;
+    else if(picHdr.topFieldFirst && picHdr.repeatFirstField)
+      return 6;
+    else
+      return 2;
+  }
+  if(picHdr.pictureStructure !=3D MPEG2_PICTURE_TYPE_FRAME){
+    return 1;
+  }
+  if(picHdr.progressive && picHdr.repeatFirstField){ //TODO: fix this to=
 support progressive sequences also.
+    return 3;
+  }else{
+    return 2;
+  }
+}
+
+MPEG2ParserState M2VParser::GetState(){
+  FillQueues();
+  if(!buffers.empty())
+    parserState =3D MPV_PARSER_STATE_FRAME;
+  else
+    parserState =3D MPV_PARSER_STATE_NEED_DATA;
+
+  if(m_eos && parserState =3D=3D MPV_PARSER_STATE_NEED_DATA)
+    parserState =3D MPV_PARSER_STATE_EOS;
+  return parserState;
+}
+
+MediaTime M2VParser::CountBFrames(){
+  //We count after the first chunk.
+  MediaTime count =3D 0;
+  if(m_eos) return 0;
+  if(notReachedFirstGOP) return 0;
+  for(size_t i =3D 1; i < chunks.size(); i++){
+    MPEGChunk* c =3D chunks[i];
+    if(c->GetType() =3D=3D MPEG_VIDEO_PICTURE_START_CODE){
+      MPEG2PictureHeader h;
+      ParsePictureHeader(c, h);
+      if(h.frameType =3D=3D MPEG2_B_FRAME){
+        count +=3D GetFrameDuration(h);
+      }else{
+        return count;
+      }
+    }
+  }
+  return -1;
+}
+
+int32_t M2VParser::QueueFrame(MPEGChunk* chunk, MediaTime timecode, MPEG=
2PictureHeader picHdr){
+  MPEGFrame* outBuf;
+  bool bCopy =3D true;
+  binary* pData =3D chunk->GetPointer();
+  uint32_t dataLen =3D chunk->GetSize();
+
+  if ((seqHdrChunk && keepSeqHdrsInBitstream &&
+       (MPEG2_I_FRAME =3D=3D picHdr.frameType)) || gopChunk) {
+    uint32_t pos =3D 0;
+    bCopy =3D false;
+    dataLen +=3D
+      (seqHdrChunk && keepSeqHdrsInBitstream ? seqHdrChunk->GetSize() : =
0) +
+      (gopChunk ? gopChunk->GetSize() : 0);
+    pData =3D (binary *)safemalloc(dataLen);
+    if (seqHdrChunk && keepSeqHdrsInBitstream &&
+        (MPEG2_I_FRAME =3D=3D picHdr.frameType)) {
+      memcpy(pData, seqHdrChunk->GetPointer(), seqHdrChunk->GetSize());
+      pos +=3D seqHdrChunk->GetSize();
+      delete seqHdrChunk;
+      seqHdrChunk =3D NULL;
+    }
+    if (gopChunk) {
+      memcpy(pData + pos, gopChunk->GetPointer(), gopChunk->GetSize());
+      pos +=3D gopChunk->GetSize();
+      delete gopChunk;
+      gopChunk =3D NULL;
+    }
+    memcpy(pData + pos, chunk->GetPointer(), chunk->GetSize());
+  }
+
+  MediaTime duration =3D GetFrameDuration(picHdr);
+
+  outBuf =3D new MPEGFrame(pData, dataLen, bCopy);
+
+  if (seqHdrChunk && !keepSeqHdrsInBitstream &&
+      (MPEG2_I_FRAME =3D=3D picHdr.frameType)) {
+    outBuf->seqHdrData =3D (binary *)safemalloc(seqHdrChunk->GetSize());
+    outBuf->seqHdrDataSize =3D seqHdrChunk->GetSize();
+    memcpy(outBuf->seqHdrData, seqHdrChunk->GetPointer(),
+           outBuf->seqHdrDataSize);
+    delete seqHdrChunk;
+    seqHdrChunk =3D NULL;
+  }
+
+  if(picHdr.frameType =3D=3D MPEG2_I_FRAME){
+    outBuf->frameType =3D 'I';
+  }else if(picHdr.frameType =3D=3D MPEG2_P_FRAME){
+    outBuf->frameType =3D 'P';
+  }else{
+    outBuf->frameType =3D 'B';
+  }
+
+  outBuf->timecode =3D (MediaTime)(timecode * (1000000000/(m_seqHdr.fram=
eRate*2)));
+  outBuf->duration =3D (MediaTime)(duration * (1000000000/(m_seqHdr.fram=
eRate*2)));
+
+  if(outBuf->frameType =3D=3D 'P'){
+    outBuf->firstRef =3D (MediaTime)(firstRef * (1000000000/(m_seqHdr.fr=
ameRate*2)));
+  }else if(outBuf->frameType =3D=3D 'B'){
+    outBuf->firstRef =3D (MediaTime)(firstRef * (1000000000/(m_seqHdr.fr=
ameRate*2)));
+    outBuf->secondRef =3D (MediaTime)(secondRef * (1000000000/(m_seqHdr.=
frameRate*2)));
+  }
+  outBuf->rff =3D (picHdr.repeatFirstField !=3D 0);
+  outBuf->tff =3D (picHdr.topFieldFirst !=3D 0);
+  outBuf->progressive =3D (picHdr.progressive !=3D 0);
+  outBuf->pictureStructure =3D (uint8_t) picHdr.pictureStructure;
+  buffers.push(outBuf);
+  return 0;
+}
+
+void M2VParser::ShoveRef(MediaTime ref){
+  if(firstRef =3D=3D -1){
+    firstRef =3D ref;
+  }else if(secondRef =3D=3D -1){
+    secondRef =3D ref;
+  }else{
+    firstRef =3D secondRef;
+    secondRef =3D ref;
+  }
+}
+
+//Reads frames until it can timestamp them, usually reads until it has
+//an I, P, B+, P...this way it can stamp them all and set references.
+//NOTE: references aren't yet used by our system but they are kept up
+//with in this plugin.
+int32_t M2VParser::FillQueues(){
+  if(chunks.empty()){
+    return -1;
+  }
+  bool done =3D false;
+  while(!done){
+    MediaTime myTime =3D currentStampingTime;
+    MPEGChunk* chunk =3D chunks.front();
+    while (chunk->GetType() !=3D MPEG_VIDEO_PICTURE_START_CODE) {
+      if (chunk->GetType() =3D=3D MPEG_VIDEO_GOP_START_CODE) {
+        if (gopChunk)
+          delete gopChunk;
+        gopChunk =3D chunk;
+
+      } else if (chunk->GetType() =3D=3D MPEG_VIDEO_SEQUENCE_START_CODE)=
 {
+        if (seqHdrChunk)
+          delete seqHdrChunk;
+        ParseSequenceHeader(chunk, m_seqHdr);
+        seqHdrChunk =3D chunk;
+
+      }
+
+      chunks.erase(chunks.begin());
+      if (chunks.empty())
+        return -1;
+      chunk =3D chunks.front();
+    }
+    MPEG2PictureHeader picHdr;
+    ParsePictureHeader(chunk, picHdr);
+    MediaTime bcount;
+    if(myTime =3D=3D nextSkip){
+      myTime+=3DnextSkipDuration;
+      currentStampingTime=3DmyTime;
+    }
+    switch(picHdr.frameType){
+      case MPEG2_I_FRAME:
+        bcount =3D CountBFrames();
+        if(bcount > 0){ //..BBIBB..
+          myTime +=3D bcount;
+          nextSkip =3D myTime;
+          nextSkipDuration =3D GetFrameDuration(picHdr);
+        }else{ //IPBB..
+          if(bcount =3D=3D -1 && !m_eos)
+            return -1;
+          currentStampingTime +=3D GetFrameDuration(picHdr);;
+        }
+        ShoveRef(myTime);
+        QueueFrame(chunk, myTime, picHdr);
+        notReachedFirstGOP =3D false;
+        break;
+      case MPEG2_P_FRAME:
+        bcount =3D CountBFrames();
+        if(firstRef =3D=3D -1) break;
+        if(bcount > 0){ //..PBB..
+          myTime +=3D bcount;
+          nextSkip =3D myTime;
+          nextSkipDuration =3D GetFrameDuration(picHdr);
+        }else{ //..PPBB..
+          if(bcount =3D=3D -1 && !m_eos) return -1;
+          currentStampingTime+=3DGetFrameDuration(picHdr);
+        }
+        ShoveRef(myTime);
+        QueueFrame(chunk, myTime, picHdr);
+        break;
+      default: //B-frames
+        if(firstRef =3D=3D -1 || secondRef =3D=3D -1) break;
+        QueueFrame(chunk, myTime, picHdr);
+        currentStampingTime+=3DGetFrameDuration(picHdr);
+    }
+    chunks.erase(chunks.begin());
+    delete chunk;
+    if (chunks.empty())
+      return -1;
+  }
+  return 0;
+}
+
+MPEGFrame* M2VParser::ReadFrame(){
+  //if(m_eos) return NULL;
+  if(GetState() !=3D MPV_PARSER_STATE_FRAME){
+    return NULL;
+  }
+  if(buffers.empty()){
+    return NULL; // OOPS!
+  }
+  MPEGFrame* frame =3D buffers.front();
+  buffers.pop();
+  return frame;
+}
+

Added: trunk/DvdMenuXtractor/dmx/mpegparser/M2VParser.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/mpegparser/M2VParser.h	2007-03-10 21:41:34 =
UTC (rev 1290)
+++ trunk/DvdMenuXtractor/dmx/mpegparser/M2VParser.h	2007-03-10 21:45:28 =
UTC (rev 1291)
@@ -0,0 +1,130 @@
+/***********************************************************************=
******
+
+    MPEG Video Packetizer
+
+    Copyright(C) 2004 John Cannon <[email protected]>
+
+    This program is free software ; you can redistribute it and/or modif=
y
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation ; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY ; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program ; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307=
 USA
+
+ **/
+
+#ifndef __M2VPARSER_H__
+#define __M2VPARSER_H__
+
+#include "MPEGVideoBuffer.h"
+#include <stdio.h>
+#include <queue>
+
+enum MPEG2ParserState {
+  MPV_PARSER_STATE_FRAME,
+  MPV_PARSER_STATE_NEED_DATA,
+  MPV_PARSER_STATE_EOS,
+  MPV_PARSER_STATE_ERROR
+};
+
+class MPEGFrame {
+public:
+  binary *data;
+  uint32_t size;
+  binary *seqHdrData;
+  uint32_t seqHdrDataSize;
+  MediaTime duration;
+  char frameType;
+  MediaTime timecode;
+  MediaTime firstRef;
+  MediaTime secondRef;
+  bool rff;
+  bool tff;
+  bool progressive;
+  uint8_t pictureStructure;
+  bool bCopy;
+
+  MPEGFrame(binary* data, uint32_t size, bool bCopy);
+  ~MPEGFrame();
+};
+
+class M2VParser {
+private:
+  std::vector<MPEGChunk*> chunks; //Hold the chunks until we can stamp t=
hem
+  std::queue<MPEGFrame*> buffers; //Holds stamped buffers until they are=
 requested.
+  MediaTime position;
+  //Added to allow reading the header's raw data, contains first found s=
eq hdr.
+  MPEGChunk* seqHdrChunk, *gopChunk;
+  MPEG2SequenceHeader m_seqHdr; //current sequence header
+  MediaTime currentStampingTime;
+  MediaTime firstRef;
+  bool needInit;
+  bool m_eos;
+  bool notReachedFirstGOP;
+  bool keepSeqHdrsInBitstream;
+  MediaTime nextSkip;
+  MediaTime nextSkipDuration;
+  MediaTime secondRef;
+  uint8_t mpegVersion;
+  MPEG2ParserState parserState;
+  MPEGVideoBuffer * mpgBuf;
+
+  int32_t InitParser();
+  void DumpQueues();
+  int32_t FillQueues();
+  MediaTime CountBFrames();
+  void ShoveRef(MediaTime ref);
+  MediaTime GetFrameDuration(MPEG2PictureHeader picHdr);
+  int32_t QueueFrame(MPEGChunk* chunk, MediaTime timecode, MPEG2PictureH=
eader picHdr);
+public:
+  M2VParser();
+  virtual ~M2VParser();
+
+  //Returns the current media position
+  virtual const MediaTime GetPosition();
+
+  MPEG2SequenceHeader GetSequenceHeader(){
+    return m_seqHdr;
+  }
+
+  //BE VERY CAREFUL WITH THIS CALL
+  MPEGChunk * GetRealSequenceHeader(){
+    return seqHdrChunk;
+  }
+
+  uint8_t GetMPEGVersion() const{
+    return mpegVersion;
+  }
+
+  //Returns a pointer to a frame that has been read
+  virtual MPEGFrame * ReadFrame();
+
+  //Returns the max amount of data that can be written to the buffer
+  int32_t GetFreeBufferSpace(){
+    return mpgBuf->GetFreeBufferSpace();
+  }
+
+  //Writes data to the internal buffer.
+  int32_t WriteData(binary* data, uint32_t dataSize);
+
+  //Returns the current state of the parser
+  MPEG2ParserState GetState();
+
+  //Sets "end of stream" status on the buffer, forces timestamping of fr=
ames waiting.
+  //Do not call this without good reason.
+  void SetEOS();
+
+  void SeparateSequenceHeaders() {
+    keepSeqHdrsInBitstream =3D false;
+  }
+};
+
+
+#endif //__M2VPARSER_H__

Added: trunk/DvdMenuXtractor/dmx/mpegparser/MPEGVideoBuffer.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/mpegparser/MPEGVideoBuffer.cpp	2007-03-10 2=
1:41:34 UTC (rev 1290)
+++ trunk/DvdMenuXtractor/dmx/mpegparser/MPEGVideoBuffer.cpp	2007-03-10 2=
1:45:28 UTC (rev 1291)
@@ -0,0 +1,269 @@
+/***********************************************************************=
******
+
+    MPEG Video Packetizing Buffer
+
+    Copyright(C) 2004 John Cannon <[email protected]>
+
+    This program is free software ; you can redistribute it and/or modif=
y
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation ; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY ; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program ; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307=
 USA
+
+ **/
+
+#include "MPEGVideoBuffer.h"
+#include <stddef.h>
+
+int32_t MPEGVideoBuffer::FindStartCode(uint32_t startPos){
+  //How many bytes can we look through?
+  uint32_t window =3D myBuffer->GetLength() - startPos;
+
+  if(window < 4) //Make sure we have enough bytes to search.
+    return -1;
+
+  for(unsigned int i =3D startPos; i < (window - 3); i++){
+    CircBuffer& buf =3D *myBuffer;
+    binary a,b,c,d;
+    a =3D buf[i];
+    b =3D buf[i+1];
+    c =3D buf[i+2];
+    d =3D buf[i+3];
+    if((a =3D=3D 0x00) && (b =3D=3D 0x00) && (c =3D=3D 0x01)){
+      switch(d){
+        case MPEG_VIDEO_SEQUENCE_START_CODE:
+        case MPEG_VIDEO_GOP_START_CODE:
+        case MPEG_VIDEO_PICTURE_START_CODE:
+          return i;  //Return our position if we found
+          //one of the codes we want
+
+      }
+    }
+  }
+
+  //If we get here we have no _wanted_ start code found.
+  return -1;
+}
+
+void MPEGVideoBuffer::UpdateState(){
+  assert(myBuffer !=3D NULL);
+  int32_t test =3D 0;
+  if(myBuffer->GetLength() =3D=3D 0){
+    state =3D MPEG2_BUFFER_STATE_EMPTY;
+    return;
+  }
+  if(chunkStart =3D=3D -1){
+    test =3D FindStartCode(0);
+    if(test !=3D -1)  //We found a new startcode
+      chunkStart =3D test;
+  }
+  if(chunkEnd =3D=3D -1){
+    test =3D FindStartCode(chunkStart+4);
+    if(test !=3D -1)  //We found a new startcode
+      chunkEnd =3D test;
+  }
+  if(chunkStart =3D=3D -1 || chunkEnd =3D=3D -1){
+    state =3D MPEG2_BUFFER_STATE_NEED_MORE_DATA;
+  }else{
+    assert(chunkStart >=3D 0 && chunkStart < chunkEnd && chunkEnd > 0);
+    state =3D MPEG2_BUFFER_STATE_CHUNK_READY;
+  }
+}
+
+MPEGChunk * MPEGVideoBuffer::ReadChunk(){
+  MPEGChunk* myChunk =3D NULL;
+  if(state =3D=3D MPEG2_BUFFER_STATE_CHUNK_READY){
+    assert(chunkStart < chunkEnd && chunkStart !=3D -1 && chunkEnd !=3D =
-1);
+    if(chunkStart !=3D 0){ //we have to skip some bytes
+      myBuffer->Skip(chunkStart);
+    }
+    uint32_t chunkLength =3D chunkEnd - chunkStart;
+    binary* chunkData =3D new binary[chunkLength];
+    myBuffer->Read(chunkData, chunkLength);
+    chunkStart =3D 0; //we read up to the next start code
+    chunkEnd =3D -1;
+    UpdateState();
+    myChunk =3D new MPEGChunk(chunkData, chunkLength);
+    return myChunk;
+  }else{
+    return NULL;
+  }
+}
+
+void MPEGVideoBuffer::ForceFinal(){
+  if(state =3D=3D MPEG2_BUFFER_STATE_NEED_MORE_DATA){
+    chunkStart =3D 0;
+    chunkEnd =3D chunkStart + myBuffer->GetLength();
+    UpdateState();
+  }
+}
+
+int32_t MPEGVideoBuffer::Feed(binary* data, uint32_t numBytes){
+  uint32_t res =3D myBuffer->Write(data, numBytes);
+  UpdateState();
+  return res;
+}
+
+void ParseSequenceHeader(MPEGChunk* chunk, MPEG2SequenceHeader & hdr){
+  binary* pos =3D chunk->GetPointer();
+  uint8_t haveSeqExt =3D 0;
+  //Parse out the resolution info, horizontal first
+  pos+=3D4; //Skip the start code
+  hdr.width =3D (((unsigned int)pos[0]) << 4) | (((unsigned int) pos[1])=
>>4);  //xx x0 00
+  pos+=3D1;
+  hdr.height =3D (((unsigned int)pos[0] & 0x0F) << 8) | (((unsigned int)=
 pos[1]));  //00 0x xx
+  pos+=3D2;
+  switch(pos[0] & 0xF0){
+    case 0x10:
+      hdr.aspectRatio =3D 1.0f;
+      break;
+    case 0x20:
+      hdr.aspectRatio =3D (4.0f / 3.0f);
+      break;
+    case 0x30:
+      hdr.aspectRatio =3D (16.0f / 9.0f);
+      //playuing with AR
+      /*pos[0] &=3D0x0F;
+        pos[0] |=3D 0x20;*/
+      break;
+    case 0x40:
+      hdr.aspectRatio =3D 2.21f;
+      break;
+    default:
+      hdr.aspectRatio =3D -1.0f;
+  }
+  switch(pos[0] & 0x0F){
+    case 0x01:
+      hdr.frameRate =3D 24000.0f/1001.0f;//23.976
+      break;
+    case 0x02:
+      hdr.frameRate =3D 24.0f;//24
+      break;
+    case 0x03:
+      hdr.frameRate =3D 25.0f;//25
+      break;
+    case 0x04:
+      hdr.frameRate =3D 30000.0f/1001.0f;//29.97
+      //Let's play some more ;)
+      /*pos[0] &=3D 0xF0; //clear the framerate
+        pos[0] |=3D 0x01;
+        hdr->frameRate =3D 24000.0f/1001.0f;//23.976*/
+      break;
+    case 0x05:
+      hdr.frameRate =3D 30.0f;//30
+      break;
+    case 0x06:
+      hdr.frameRate =3D 50.0f;//50
+      break;
+    case 0x07:
+      hdr.frameRate =3D 60000.0f / 1001.0f;//59.94
+      break;
+    case 0x08:
+      hdr.frameRate =3D 60.0f;//60
+      break;
+    default:
+      hdr.frameRate =3D 0.0f;
+  }
+
+  //Seek to picturecoding extension
+  while(pos < (chunk->GetPointer() + chunk->GetSize() - 4)){
+    if((pos[0] =3D=3D 0x00) && (pos[1] =3D=3D 0x00) && (pos[2] =3D=3D 0x=
01) && (pos[3] =3D=3D MPEG_VIDEO_EXT_START_CODE)){
+      if((pos[4] & 0xF0) =3D=3D 0x01){ //Picture coding extension
+        //printf("Found a picture_coding_extension\n");
+        haveSeqExt =3D 1;
+        pos+=3D4;
+        break;
+      }
+    }
+    pos++;
+  }
+
+  if(haveSeqExt){
+    pos++;
+    hdr.progressiveSequence =3D (pos[0] & 0x80);
+  }else{
+    hdr.progressiveSequence =3D 0;
+  }
+}
+
+bool ParseGOPHeader(MPEGChunk* chunk, MPEG2GOPHeader & hdr){
+  if(chunk->GetType() !=3D MPEG_VIDEO_GOP_START_CODE){
+    //printf("Don't feed parse_gop_header a chunk that isn't a gop heade=
r!!!\n");
+    return false;
+  }
+  binary* pos =3D chunk->GetPointer();
+  uint32_t timecode;
+  pos+=3D4; //skip the startcode
+  //Parse GOP timecode structure
+  timecode =3D ((uint32_t)pos[0] << 24) |
+    ((uint32_t)pos[1] << 16) |
+    ((uint32_t)pos[2] << 8) |
+    ((uint32_t)pos[3]);
+  hdr.timeHours =3D (timecode << 1) >> 27;
+  hdr.timeMinutes=3D (timecode << 6)>>26;
+  hdr.timeSeconds =3D (timecode << 13) >> 26;
+  hdr.timeFrames =3D (timecode << 19) >> 26;
+  pos+=3D3;
+  if(pos[0] & 0x40){ //Check second bit
+    hdr.closedGOP =3D 1;
+  }else{
+    hdr.closedGOP =3D 0;
+  }
+  return true;
+}
+
+bool ParsePictureHeader(MPEGChunk* chunk, MPEG2PictureHeader & hdr){
+  if(chunk->GetType() !=3D MPEG_VIDEO_PICTURE_START_CODE){
+    //printf("Don't feed parse_picture_header a chunk that isn't a pictu=
re!!!\n");
+    return false;
+  }
+  binary* pos =3D chunk->GetPointer();
+  int havePicExt =3D 0;
+  uint32_t temp =3D 0;
+  pos+=3D4;
+  temp =3D (((uint32_t)pos[0]) << 8) | (pos[1] & 0xC0);
+  hdr.temporalReference =3D temp >> 6;
+  pos+=3D1;
+  temp =3D ((uint32_t)(pos[0] & 0x38)) >> 3 ;
+  hdr.frameType =3D (uint8_t) temp;
+
+  //Seek to picturecoding extension
+  while(pos < (chunk->GetPointer() + chunk->GetSize() - 4)){
+    if((pos[0] =3D=3D 0x00) && (pos[1] =3D=3D 0x00) && (pos[2] =3D=3D 0x=
01) && (pos[3] =3D=3D MPEG_VIDEO_EXT_START_CODE)){
+      if((pos[4] & 0xF0) =3D=3D 0x80){ //Picture coding extension
+        //printf("Found a picture_coding_extension\n");
+        havePicExt =3D 1;
+        break;
+      }
+    }
+    pos++;
+  }
+  if(!havePicExt){
+    hdr.pictureStructure =3D MPEG2_PICTURE_TYPE_FRAME;
+    hdr.repeatFirstField =3D 0;
+    hdr.topFieldFirst =3D 1;
+    hdr.progressive =3D 1;
+  }else{
+    pos+=3D4;//skip start code
+    pos+=3D2;//skip f_code shit
+    hdr.pictureStructure =3D (pos[0] & 0x03);
+    pos++;
+    hdr.topFieldFirst =3D (pos[0] & 0x80);
+    //pos++;
+    hdr.repeatFirstField =3D (pos[0] & 0x02);
+    /*//let's play ;)
+      hdr->repeatFirstField =3D (pos[0] =3D pos[0] & 0xFD) & 0x02;*/
+    pos++;
+    hdr.progressive =3D (pos[0] & 0x80);
+  }
+
+  return true;
+}

Added: trunk/DvdMenuXtractor/dmx/mpegparser/MPEGVideoBuffer.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/mpegparser/MPEGVideoBuffer.h	2007-03-10 21:=
41:34 UTC (rev 1290)
+++ trunk/DvdMenuXtractor/dmx/mpegparser/MPEGVideoBuffer.h	2007-03-10 21:=
45:28 UTC (rev 1291)
@@ -0,0 +1,155 @@
+/***********************************************************************=
******
+
+    MPEG Video Packetizing Buffer
+
+    Copyright(C) 2004 John Cannon <[email protected]>
+
+    This program is free software ; you can redistribute it and/or modif=
y
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation ; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY ; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program ; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307=
 USA
+
+ **/
+
+#ifndef __MPEGVIDEOBUFFER_H__
+#define __MPEGVIDEOBUFFER_H__
+
+#include "Types.h"
+#include "CircBuffer.h"
+#include <cassert>
+
+#define MPEG_VIDEO_PICTURE_START_CODE  0x00
+#define MPEG_VIDEO_SEQUENCE_START_CODE  0xb3
+#define MPEG_VIDEO_EXT_START_CODE  0xb5
+#define MPEG_VIDEO_GOP_START_CODE  0xb8
+#define MPEG_VIDEO_USER_START_CODE  0xb2
+
+enum MPEG2BufferState {
+  MPEG2_BUFFER_STATE_NEED_MORE_DATA,
+  MPEG2_BUFFER_STATE_CHUNK_READY,
+  MPEG2_BUFFER_STATE_EMPTY,
+  MPEG2_BUFFER_INVALID
+};
+
+#define MPEG2_I_FRAME 1
+#define MPEG2_P_FRAME 2
+#define MPEG2_B_FRAME 3
+
+typedef struct MPEG2SequenceHeader{
+  uint32_t width;
+  uint32_t height;
+  float aspectRatio;
+  float frameRate;
+  uint8_t progressiveSequence;
+}MPEG2SequenceHeader;
+
+typedef struct MPEG2GOPHeader{
+  uint8_t closedGOP;
+  uint32_t timeFrames;
+  uint32_t timeSeconds;
+  uint32_t timeMinutes;
+  uint32_t timeHours;
+}MPEG2GOPHeader;
+
+#define MPEG2_PICTURE_TYPE_FRAME  0x03
+#define MPEG2_PICTURE_TYPE_TOP_FIELD  0x01
+#define MPEG2_PICTURE_TYPE_BOTTOM_FIELD  0x02
+
+typedef struct MPEG2PictureHeader{
+  uint32_t temporalReference;
+  uint8_t frameType;
+  uint32_t pictureStructure;
+  uint8_t repeatFirstField;
+  uint8_t topFieldFirst;
+  uint8_t progressive;
+}MPEG2PictureHeader;
+
+class MPEGChunk{
+private:
+  binary * data;
+  uint32_t size;
+  uint8_t type;
+public:
+  MPEGChunk(binary* data, uint32_t dataSize){
+    assert(data);
+    this->data =3D data;
+    assert(dataSize > 4);
+    this->size =3D dataSize;
+    type =3D data[3];
+  }
+
+  ~MPEGChunk(){
+    if(data)
+      delete [] data;
+  }
+
+  inline uint8_t GetType() const {
+    return type;
+  }
+
+  inline uint32_t GetSize() const{
+    return size;
+  }
+
+  binary & operator[](unsigned int i){
+    return data[i];
+  }
+
+  binary & at(unsigned int i) {
+    return data[i];
+  }
+
+  inline binary * GetPointer(){
+    return data;
+  }
+};
+
+void ParseSequenceHeader(MPEGChunk* chunk, MPEG2SequenceHeader & hdr);
+bool ParsePictureHeader(MPEGChunk* chunk, MPEG2PictureHeader & hdr);
+bool ParseGOPHeader(MPEGChunk* chunk, MPEG2GOPHeader & hdr);
+
+class MPEGVideoBuffer{
+private:
+  CircBuffer * myBuffer;
+  MPEG2BufferState state;
+  int32_t chunkStart;
+  int32_t chunkEnd;
+  void UpdateState();
+  int32_t FindStartCode(uint32_t startPos =3D 0);
+public:
+  MPEGVideoBuffer(uint32_t size){
+    myBuffer =3D new CircBuffer(size);
+    state =3D MPEG2_BUFFER_STATE_EMPTY;
+    chunkStart =3D -1;
+    chunkEnd =3D -1;
+  }
+
+  ~MPEGVideoBuffer(){
+    delete myBuffer;
+  }
+
+  inline MPEG2BufferState GetState() const { return state; }
+
+  int32_t GetFreeBufferSpace(){
+    return (myBuffer->buf_capacity - myBuffer->bytes_in_buf);
+  }
+
+  void SetEndOfData(){
+    chunkEnd =3D myBuffer->GetLength() - 1;
+  }
+
+  void ForceFinal();  //prepares the remaining data as a chunk
+  MPEGChunk * ReadChunk();
+  int32_t Feed(binary* data, uint32_t numBytes);
+};
+
+#endif //__MPEGVIDEOBUFFER_H__

Added: trunk/DvdMenuXtractor/dmx/mpegparser/Types.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/mpegparser/Types.h	2007-03-10 21:41:34 UTC =
(rev 1290)
+++ trunk/DvdMenuXtractor/dmx/mpegparser/Types.h	2007-03-10 21:45:28 UTC =
(rev 1291)
@@ -0,0 +1,9 @@
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+#include <stdint.h>
+
+typedef int64_t MediaTime;
+typedef uint8_t binary;
+
+#endif // __TYPES_H__

Added: trunk/DvdMenuXtractor/dmx/mpegparser/mpegparser.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/mpegparser/mpegparser.proj	2007-03-10 21:41=
:34 UTC (rev 1290)
+++ trunk/DvdMenuXtractor/dmx/mpegparser/mpegparser.proj	2007-03-10 21:45=
:28 UTC (rev 1291)
@@ -0,0 +1,11 @@
+GROUP mpegparser
+{
+  SOURCE CircBuffer.cpp
+  SOURCE M2VParser.cpp
+  SOURCE MPEGVideoBuffer.cpp
+
+  HEADER CircBuffer.h
+  HEADER M2VParser.h
+  HEADER MPEGVideoBuffer.h
+  HEADER Types.h
+}