dslinux/user/pixil/packages/dvdview/dvdview/src/video12 constants.hh dctblk.cc macroblock.hh output.hh vdecoder.cc vdecoder.hh viddec_mods.cc viddec_mods.hh vidsyntax.cc vidsyntax.hh vlc.cc vlc.hh

amadeus dslinux_amadeus at user.in-berlin.de
Tue Oct 3 13:26:03 CEST 2006


Update of /cvsroot/dslinux/dslinux/user/pixil/packages/dvdview/dvdview/src/video12
In directory antilope:/tmp/cvs-serv11916/packages/dvdview/dvdview/src/video12

Added Files:
	constants.hh dctblk.cc macroblock.hh output.hh vdecoder.cc 
	vdecoder.hh viddec_mods.cc viddec_mods.hh vidsyntax.cc 
	vidsyntax.hh vlc.cc vlc.hh 
Log Message:
adding pristine copy of pixil to HEAD so I can branch from it

--- NEW FILE: viddec_mods.hh ---
/********************************************************************************
  video12/viddec_mods.hh
    Main video decoder. Abstract classes for decoding modules.

  purpose:
    Abstract base classes declarations that encapsulate computation intensive
    parts of the MPEG decoding process. So you can subclass these classes and
    create implementations that are optimized for specific architectures.

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   05/Sep/2000 - Dirk Farin
     - removed Init() method
   04/Oct/1999 - Dirk Farin
     - first revision
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_VIDEO12_VIDDEC_MODS_HH
#define DVDVIEW_VIDEO12_VIDDEC_MODS_HH

#include "types.hh"
#include "libvideogfx/graphics/basic/image.hh"

struct PixPtrs
{
  Pixel* y;
  Pixel* cr;
  Pixel* cb;
};
struct PixPtrs_const
{
  const Pixel* y;
  const Pixel* cr;
  const Pixel* cb;
};

// Do not change these bit positions, as they are hard-coded in parts of the video decoder.
#define MC_Last_HalfV 1
#define MC_Last_HalfH 2
#define MC_Next_HalfV 4
#define MC_Next_HalfH 8

class MotionCompensation_SglMB
{
public:
  virtual ~MotionCompensation_SglMB() { }

  struct MCData
  {
    PixPtrs_const  lastimg;
    PixPtrs        currimg;
    PixPtrs_const  nextimg;

    int     bytesperline_lum;
    int     bytesperline_chr;

    int     blkheight;
    int     blkheight_chr;

    int     LumaHalfFlags;
    int     ChromaHalfFlags;
  };

  static MotionCompensation_SglMB* Create();

  typedef void MCompFunc(MCData*);

  virtual MCompFunc*const* AskMCompFunc_Sgl_Luma()   const = 0;  // Returns array of 16 func.pointers.
  virtual MCompFunc*const* AskMCompFunc_Dbl_Luma()   const = 0;  // Returns array of 4 func.pointers.
  virtual MCompFunc*const* AskMCompFunc_Sgl_Chroma(uint2 chroma) const = 0;
  virtual MCompFunc*const* AskMCompFunc_Dbl_Chroma(uint2 chroma) const = 0;

  void CallSglLuma(MCData* d) const { (AskMCompFunc_Sgl_Luma())[d->LumaHalfFlags](d); }
  void CallDblLuma(MCData* d) const { (AskMCompFunc_Dbl_Luma())[d->LumaHalfFlags](d); }
  void CallSglChroma(uint2 chroma,MCData* d)const{(AskMCompFunc_Sgl_Chroma(chroma))[d->ChromaHalfFlags](d);}
  void CallDblChroma(uint2 chroma,MCData* d)const{(AskMCompFunc_Dbl_Chroma(chroma))[d->ChromaHalfFlags](d);}
};

#endif

--- NEW FILE: vidsyntax.hh ---
/*********************************************************************
  video12/vidsyntax.hh
    Main video decoder

  purpose:

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   07/set/2000 - Dirk Farin
     - Changed type of Framerate field in SequenceHeader from double to int
       to overcome MMX problems.
   05/Sep/2000 - Dirk Farin
     - Syntax decoding functions extracted from vdecoder.cc.
   30/Sep/1999 - Dirk Farin
     - Integrated code into CVS.
   05/May/1999 - Dirk Farin
     - Took structure definitions out of viddec.hh
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_VIDEO12_VIDSYNTAX_HH
#define DVDVIEW_VIDEO12_VIDSYNTAX_HH

#include "types.hh"
#include "video12/macroblock.hh"
#include "libvideogfx/containers/array2.hh"


struct VideoSyntaxData
{
  virtual ~VideoSyntaxData() { }
};


struct SequenceHeader : public VideoSyntaxData
{
  uint32 m_Width,m_Height;
  uint4  m_AspectRatio;
  int    m_Framerate;     // *10000
  uint32 m_Bitrate;
  uint32 m_VBVBufferSize;
  bool   m_Constrained;


  // MPEG-2 only data

  uint4  m_Profile;
  uint4  m_Level;
  bool   m_ProgressiveSequence;
  uint2  m_ChromaFormat;
  bool   m_LowDelay;

  // deduced data

  bool   m_IsMPEG2;
  uint32 m_MBWidth,m_MBHeight; // width and height in macroblocks
};


struct QuantMatrices : public VideoSyntaxData
{
  int  m_LumIntra[64];
  int  m_LumInter[64];
  int  m_ChrIntra[64];
  int  m_ChrInter[64];
};

struct GOPHeader : public VideoSyntaxData
{
  bool  m_TimeCode_DropFrameFlag;
  uint5 m_TimeCode_Hours;
  uint6 m_TimeCode_Minutes;
  uint6 m_TimeCode_Seconds;
  uint6 m_TimeCode_Pictures;

  bool m_ClosedGOP;
  bool m_BrokenLink;
};


struct PictureHeader : public VideoSyntaxData
{
  uint16 m_temporal_reference;
  uint3  m_picture_coding_type;
  uint16 m_vbv_delay;
  bool   m_fullpel_fw;
  bool   m_fullpel_bw;
  uint3  m_fcode[2][2];  // [ 0 fw, 1 bw ]  [ 0 h, 1 v ]

  // MPEG2 only fields follow

  bool   m_IsMPEG2;
  
  uint4  m_intra_dc_precision;
  uint2  m_picture_structure;
  bool   m_top_field_first;
  bool   m_frame_pred_frame_dct;
  bool   m_concealment_motion_vectors;
  uint1  m_q_scale_type;
  uint1  m_intra_vlc_format;
  bool   m_alternate_scan;
  bool   m_repeat_first_field;
  uint1  m_chroma420type;
  bool   m_progressive_frame;

  bool   m_composite_display_flag;
  uint1  m_v_axis;
  uint3  m_field_sequence;
  uint1  m_sub_carrier;
  uint7  m_burst_amplitude;
  uint8  m_sub_carrier_phase;


  // precalculated values

  int m_intra_dc_precision_shift;


  // extra data

  int m_picturedata_length;
};


struct PictureData
{
  Array2<Macroblock> m_codedimage;


  // efficient allocation

  static PictureData* GetPictureData(int mb_w,int mb_h);
  static void FreePictureData(PictureData*);

  void operator delete(void*) { Assert(0); /* Use FreePictureData() to delete PictureData objects.
					      Calling ::delete is safe but very inefficient. */ }
};



struct EndOfVideoStream : public VideoSyntaxData
{
};



void DecodeSequenceHeader(class MemBitstreamReader& bs,SequenceHeader& sh,QuantMatrices& qmat);
void DecodeSequenceHeaderExt(class MemBitstreamReader& bs2,SequenceHeader& sh);
void TraceSequenceHeader(const SequenceHeader& sh);

void DecodeGOPHeader(class MemBitstreamReader&,GOPHeader&);
void TraceGOPHeader(const GOPHeader&);

void DecodePictureHeader(class MemBitstreamReader&,PictureHeader&);
void DecodePictureCodingExt(class MemBitstreamReader&,PictureHeader&);
void TracePictureHeader(const PictureHeader&);

#endif

--- NEW FILE: dctblk.cc ---


typedef struct {
  uint8 run;
  uint8 level;
  uint8 len;
} DCTtabb;



static DCTtabb DCT_16 [] = {
    {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
    {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
    {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
    {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
    {  2,18, 0}, {  2,17, 0}, {  2,16, 0}, {  2,15, 0},
    {  7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0},
    { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0},
    { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0}
};

static DCTtabb DCT_15 [] = {
    {  1,40,15}, {  1,39,15}, {  1,38,15}, {  1,37,15},
    {  1,36,15}, {  1,35,15}, {  1,34,15}, {  1,33,15},
    {  1,32,15}, {  2,14,15}, {  2,13,15}, {  2,12,15},
    {  2,11,15}, {  2,10,15}, {  2, 9,15}, {  2, 8,15},
    {  1,31,14}, {  1,31,14}, {  1,30,14}, {  1,30,14},
    {  1,29,14}, {  1,29,14}, {  1,28,14}, {  1,28,14},
    {  1,27,14}, {  1,27,14}, {  1,26,14}, {  1,26,14},
    {  1,25,14}, {  1,25,14}, {  1,24,14}, {  1,24,14},
    {  1,23,14}, {  1,23,14}, {  1,22,14}, {  1,22,14},
    {  1,21,14}, {  1,21,14}, {  1,20,14}, {  1,20,14},
    {  1,19,14}, {  1,19,14}, {  1,18,14}, {  1,18,14},
    {  1,17,14}, {  1,17,14}, {  1,16,14}, {  1,16,14}
};

static DCTtabb DCT_13 [] = {
    { 11, 2,13}, { 10, 2,13}, {  6, 3,13}, {  4, 4,13},
    {  3, 5,13}, {  2, 7,13}, {  2, 6,13}, {  1,15,13},
    {  1,14,13}, {  1,13,13}, {  1,12,13}, { 27, 1,13},
    { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13},
    {  1,11,12}, {  1,11,12}, {  9, 2,12}, {  9, 2,12},
    {  5, 3,12}, {  5, 3,12}, {  1,10,12}, {  1,10,12},
    {  3, 4,12}, {  3, 4,12}, {  8, 2,12}, {  8, 2,12},
    { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12},
    {  1, 9,12}, {  1, 9,12}, { 20, 1,12}, { 20, 1,12},
    { 19, 1,12}, { 19, 1,12}, {  2, 5,12}, {  2, 5,12},
    {  4, 3,12}, {  4, 3,12}, {  1, 8,12}, {  1, 8,12},
    {  7, 2,12}, {  7, 2,12}, { 18, 1,12}, { 18, 1,12}
};

static DCTtabb DCT_B14_10 [] = {
    { 17, 1,10}, {  6, 2,10}, {  1, 7,10}, {  3, 3,10},
    {  2, 4,10}, { 16, 1,10}, { 15, 1,10}, {  5, 2,10}
};

static DCTtabb DCT_B14_8 [] = {
    { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
    {  3, 2, 7}, {  3, 2, 7}, { 10, 1, 7}, { 10, 1, 7},
    {  1, 4, 7}, {  1, 4, 7}, {  9, 1, 7}, {  9, 1, 7},
    {  8, 1, 6}, {  8, 1, 6}, {  8, 1, 6}, {  8, 1, 6},
    {  7, 1, 6}, {  7, 1, 6}, {  7, 1, 6}, {  7, 1, 6},
    {  2, 2, 6}, {  2, 2, 6}, {  2, 2, 6}, {  2, 2, 6},
    {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6},
    { 14, 1, 8}, {  1, 6, 8}, { 13, 1, 8}, { 12, 1, 8},
    {  4, 2, 8}, {  2, 3, 8}, {  1, 5, 8}, { 11, 1, 8}
};

static DCTtabb DCT_B14AC_5 [] = {
		 {  1, 3, 5}, {  5, 1, 5}, {  4, 1, 5},
    {  1, 2, 4}, {  1, 2, 4}, {  3, 1, 4}, {  3, 1, 4},
    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
    {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
    {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}
};

static DCTtabb DCT_B14DC_5 [] = {
		 {  1, 3, 5}, {  5, 1, 5}, {  4, 1, 5},
    {  1, 2, 4}, {  1, 2, 4}, {  3, 1, 4}, {  3, 1, 4},
    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
    {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1},
    {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1},
    {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1},
    {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}
};

static DCTtabb DCT_B15_10 [] = {
    {  6, 2, 9}, {  6, 2, 9}, { 15, 1, 9}, { 15, 1, 9},
    {  3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9}
};

static DCTtabb DCT_B15_8 [] = {
    { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
    {  8, 1, 7}, {  8, 1, 7}, {  9, 1, 7}, {  9, 1, 7},
    {  7, 1, 7}, {  7, 1, 7}, {  3, 2, 7}, {  3, 2, 7},
    {  1, 7, 6}, {  1, 7, 6}, {  1, 7, 6}, {  1, 7, 6},
    {  1, 6, 6}, {  1, 6, 6}, {  1, 6, 6}, {  1, 6, 6},
    {  5, 1, 6}, {  5, 1, 6}, {  5, 1, 6}, {  5, 1, 6},
    {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6},
    {  2, 5, 8}, { 12, 1, 8}, {  1,11, 8}, {  1,10, 8},
    { 14, 1, 8}, { 13, 1, 8}, {  4, 2, 8}, {  2, 4, 8},
    {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5},
    {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5},
    {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5},
    {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5},
    {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5},
    {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5},
    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
    {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
    {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
    {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
    {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
    {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
    {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
    {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
    {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
    {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
    {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
    {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5},
    {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5},
    {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5},
    {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5},
    { 10, 1, 7}, { 10, 1, 7}, {  2, 3, 7}, {  2, 3, 7},
    { 11, 1, 7}, { 11, 1, 7}, {  1, 8, 7}, {  1, 8, 7},
    {  1, 9, 7}, {  1, 9, 7}, {  1,12, 8}, {  1,13, 8},
    {  3, 3, 8}, {  5, 2, 8}, {  1,14, 8}, {  1,15, 8}
};


inline int DequantizeIntra(int value,int qscale,int matrix)
{
#if MMX_DCT
  return value*qscale*matrix;
#else
  return value*qscale*matrix/16;
#endif
}

inline int DequantizeInter(int value,int qscale,int matrix)
{
  // Assert(value>0);
#if MMX_DCT
  return (2*value+1) * matrix * qscale / 2;
#else
  return (2*value+1) * matrix * qscale / 32;
#endif
}

inline void Saturate(int& value)
{
#if MMX_DCT
       if (value<-2048*16) value=-2048*16;
  else if (value> 2047*16) value= 2047*16;
#else
       if (value<-2048) value=-2048;
  else if (value> 2047) value= 2047;
#endif
}


static void get_mpeg1_intra_block(class FastBitBuf& bs,short* coeff,const int* scan,
				  int quantizer_scale,
				  const int* quant_matrix)
{
  int i;
  int j;
  int val;
  DCTtabb * tab;
  uint32 bit_buf;
  int bits;

  i = 0;
  bs.MakeLocalCopy(bit_buf,bits);

  NEEDBITS (bit_buf, bits);

  while (1) {
    if (bit_buf >= 0x28000000) {

      tab = DCT_B14AC_5 - 5 + UBITS (bit_buf, 5);

      i += tab->run;
      if (i >= 64)
	break;  // end of block

    normal_code:
      j = scan[i];
      bit_buf <<= tab->len;
      bits += tab->len + 1;
      val = DequantizeIntra(tab->level,quantizer_scale,quant_matrix[i]);

      // if (bitstream_get (1)) val = -val;
      val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);

      Saturate(val);
      coeff[j] = val;

      bit_buf <<= 1;
      NEEDBITS (bit_buf, bits);

      continue;

    } else if (bit_buf >= 0x04000000) {

      tab = DCT_B14_8 - 4 + UBITS (bit_buf, 8);

      i += tab->run;
      if (i < 64)
	goto normal_code;

      // escape code

      i += UBITS (bit_buf << 6, 6) - 64;
      if (i >= 64)
	break;  // illegal, but check needed to avoid buffer overflow

      j = scan[i];

      DUMPBITS (bit_buf, bits, 12);
      NEEDBITS (bit_buf, bits);
      val = SBITS (bit_buf, 8);
      if (! (val & 0x7f)) {
	DUMPBITS (bit_buf, bits, 8);
	val = UBITS (bit_buf, 8) + 2 * val;
      }
      val = DequantizeIntra(val,quantizer_scale,quant_matrix[i]);

      Saturate(val);
      coeff[j] = val;

      DUMPBITS (bit_buf, bits, 8);
      NEEDBITS (bit_buf, bits);

      continue;

    } else if (bit_buf >= 0x02000000) {
      tab = DCT_B14_10 - 8 + UBITS (bit_buf, 10);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else if (bit_buf >= 0x00800000) {
      tab = DCT_13 - 16 + UBITS (bit_buf, 13);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else if (bit_buf >= 0x00200000) {
      tab = DCT_15 - 16 + UBITS (bit_buf, 15);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else {
      tab = DCT_16 + UBITS (bit_buf, 16);
      bit_buf <<= 16;
      bit_buf |= bs.GetNextWord() << (bits + 16);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    }
    break;  // illegal, but check needed to avoid buffer overflow
  }
  DUMPBITS (bit_buf, bits, 2);        // dump end of block code

  bs.RestoreFromLocal(bit_buf,bits);
}




static void get_mpeg1_non_intra_block(class FastBitBuf& bs,short* coeff,const int* scan,
				      int quantizer_scale,
				      const int* quant_matrix)
{
  int i;
  int j;
  int val;
  DCTtabb * tab;
  uint32 bit_buf;
  int bits;

  i = -1;

  bs.MakeLocalCopy(bit_buf,bits);

  NEEDBITS (bit_buf, bits);
  if (bit_buf >= 0x28000000) {
    tab = DCT_B14DC_5 - 5 + UBITS (bit_buf, 5);
    goto entry_1;
  } else
    goto entry_2;

  while (1) {
    if (bit_buf >= 0x28000000) {

      tab = DCT_B14AC_5 - 5 + UBITS (bit_buf, 5);

    entry_1:
      i += tab->run;
      if (i >= 64)
	break;  // end of block

    normal_code:
      j = scan[i];
      bit_buf <<= tab->len;
      bits += tab->len + 1;
      val = DequantizeInter(tab->level,quantizer_scale,quant_matrix[i]);

      // if (bitstream_get (1)) val = -val;
      val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);

      Saturate (val);
      coeff[j] = val;

      bit_buf <<= 1;
      NEEDBITS (bit_buf, bits);

      continue;

    }

  entry_2:
    if (bit_buf >= 0x04000000) {

      tab = DCT_B14_8 - 4 + UBITS (bit_buf, 8);

      i += tab->run;
      if (i < 64)
	goto normal_code;

      // escape code

      i += UBITS (bit_buf << 6, 6) - 64;
      if (i >= 64)
	break;  // illegal, but check needed to avoid buffer overflow

      j = scan[i];

      DUMPBITS (bit_buf, bits, 12);
      NEEDBITS (bit_buf, bits);
      val = SBITS (bit_buf, 8);
      if (! (val & 0x7f)) {
	DUMPBITS (bit_buf, bits, 8);
	val = UBITS (bit_buf, 8) + 2 * val;
      }
      val = DequantizeInter(val + SBITS (val, 1),quantizer_scale,quant_matrix[i]);

      Saturate (val);
      coeff[j] = val;

      DUMPBITS (bit_buf, bits, 8);
      NEEDBITS (bit_buf, bits);

      continue;

    } else if (bit_buf >= 0x02000000) {
      tab = DCT_B14_10 - 8 + UBITS (bit_buf, 10);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else if (bit_buf >= 0x00800000) {
      tab = DCT_13 - 16 + UBITS (bit_buf, 13);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else if (bit_buf >= 0x00200000) {
      tab = DCT_15 - 16 + UBITS (bit_buf, 15);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else {
      tab = DCT_16 + UBITS (bit_buf, 16);
      bit_buf <<= 16;
      bit_buf |= bs.GetNextWord() << (bits + 16);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    }
    break;  // illegal, but check needed to avoid buffer overflow
  }
  DUMPBITS (bit_buf, bits, 2);        // dump end of block code
  bs.RestoreFromLocal(bit_buf,bits);
}


static void get_intra_block_B14(class FastBitBuf& bs,short* coeff,const int* scan,
				int quantizer_scale,
				const int* quant_matrix)
{
  int i;
  int j;
  int val;
  int mismatch;
  DCTtabb * tab;
  uint32 bit_buf;
  int bits;

  i = 0;
  mismatch = ~coeff[0];

  bs.MakeLocalCopy(bit_buf,bits);

  NEEDBITS (bit_buf, bits);

  while (1) {
    if (bit_buf >= 0x28000000) {

      tab = DCT_B14AC_5 - 5 + UBITS (bit_buf, 5);

      i += tab->run;
      if (i >= 64)
	break;  // end of block

    normal_code:
      j = scan[i];
      bit_buf <<= tab->len;
      bits += tab->len + 1;
      val = DequantizeIntra(tab->level , quantizer_scale , quant_matrix[i]);

      // if (bitstream_get (1)) val = -val;
      val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);

      Saturate (val);
      coeff[j] = val;
      mismatch ^= val;

      bit_buf <<= 1;
      NEEDBITS (bit_buf, bits);

      continue;

    } else if (bit_buf >= 0x04000000) {

      tab = DCT_B14_8 - 4 + UBITS (bit_buf, 8);

      i += tab->run;
      if (i < 64)
	goto normal_code;

      // escape code

      i += UBITS (bit_buf << 6, 6) - 64;
      if (i >= 64)
	break;  // illegal, but check needed to avoid buffer overflow

      j = scan[i];

      DUMPBITS (bit_buf, bits, 12);
      NEEDBITS (bit_buf, bits);
      val = DequantizeIntra(SBITS (bit_buf, 12) , quantizer_scale , quant_matrix[i]);

      Saturate(val);
      coeff[j] = val;
      mismatch ^= val;

      DUMPBITS (bit_buf, bits, 12);
      NEEDBITS (bit_buf, bits);

      continue;

    } else if (bit_buf >= 0x02000000) {
      tab = DCT_B14_10 - 8 + UBITS (bit_buf, 10);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else if (bit_buf >= 0x00800000) {
      tab = DCT_13 - 16 + UBITS (bit_buf, 13);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else if (bit_buf >= 0x00200000) {
      tab = DCT_15 - 16 + UBITS (bit_buf, 15);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else {
      tab = DCT_16 + UBITS (bit_buf, 16);
      bit_buf <<= 16;
      bit_buf |= bs.GetNextWord () << (bits + 16);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    }
    break;  // illegal, but check needed to avoid buffer overflow
  }
  coeff[63] ^= mismatch & 1;
  DUMPBITS (bit_buf, bits, 2);        // dump end of block code
  bs.RestoreFromLocal(bit_buf,bits);
}


static void get_intra_block_B15(class FastBitBuf& bs,short* coeff,const int* scan,
				int quantizer_scale,
				const int* quant_matrix)
{
  int i;
  int j;
  int val;
  int mismatch;
  DCTtabb * tab;
  uint32 bit_buf;
  int bits;

  i = 0;
  mismatch = ~coeff[0];

  bs.MakeLocalCopy(bit_buf,bits);

  NEEDBITS (bit_buf, bits);

  while (1) {
    if (bit_buf >= 0x04000000) {

      tab = DCT_B15_8 - 4 + UBITS (bit_buf, 8);

      i += tab->run;
      if (i < 64) {

      normal_code:
	j = scan[i];
	bit_buf <<= tab->len;
	bits += tab->len + 1;
	val = DequantizeIntra(tab->level , quantizer_scale , quant_matrix[i]);

	// if (bitstream_get (1)) val = -val;
	val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);

	Saturate(val);
	coeff[j] = val;
	mismatch ^= val;

	bit_buf <<= 1;
	NEEDBITS (bit_buf, bits);

	continue;

      } else {

	// end of block. I commented out this code because if we
	// dont exit here we will still exit at the later test :)

	//if (i >= 128) break;  // end of block

	// escape code

	i += UBITS (bit_buf << 6, 6) - 64;
	if (i >= 64)
	  break;      // illegal, but check against buffer overflow

	j = scan[i];

	DUMPBITS (bit_buf, bits, 12);
	NEEDBITS (bit_buf, bits);
	val = DequantizeIntra(SBITS (bit_buf, 12) , quantizer_scale , quant_matrix[i]);

	Saturate(val);
	coeff[j] = val;
	mismatch ^= val;

	DUMPBITS (bit_buf, bits, 12);
	NEEDBITS (bit_buf, bits);

	continue;

      }
    } else if (bit_buf >= 0x02000000) {
      tab = DCT_B15_10 - 8 + UBITS (bit_buf, 10);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else if (bit_buf >= 0x00800000) {
      tab = DCT_13 - 16 + UBITS (bit_buf, 13);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else if (bit_buf >= 0x00200000) {
      tab = DCT_15 - 16 + UBITS (bit_buf, 15);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else {
      tab = DCT_16 + UBITS (bit_buf, 16);
      bit_buf <<= 16;
      bit_buf |= bs.GetNextWord() << (bits + 16);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    }
    break;  // illegal, but check needed to avoid buffer overflow
  }
  coeff[63] ^= mismatch & 1;
  DUMPBITS (bit_buf, bits, 4);        // dump end of block code
  bs.RestoreFromLocal(bit_buf,bits);
}


static void get_non_intra_block(class FastBitBuf& bs,short* coeff,const int* scan,
				int quantizer_scale,
				const int* quant_matrix)
{
  int i;
  int j;
  int val;
  int mismatch;
  DCTtabb * tab;
  uint32 bit_buf;
  int bits;

  i = -1;
  mismatch = 1;

  bs.MakeLocalCopy(bit_buf,bits);

  NEEDBITS (bit_buf, bits);
  if (bit_buf >= 0x28000000) {
    tab = DCT_B14DC_5 - 5 + UBITS (bit_buf, 5);
    goto entry_1;
  } else
    goto entry_2;

  while (1) {
    if (bit_buf >= 0x28000000) {

      tab = DCT_B14AC_5 - 5 + UBITS (bit_buf, 5);

    entry_1:
      i += tab->run;
      if (i >= 64)
	break;  // end of block

    normal_code:
      j = scan[i];
      bit_buf <<= tab->len;
      bits += tab->len + 1;
      val = DequantizeInter(tab->level , quantizer_scale , quant_matrix[i]);

      // if (bitstream_get (1)) val = -val;
      val = (val ^ SBITS (bit_buf, 1)) - SBITS (bit_buf, 1);

      Saturate(val);
      coeff[j] = val;
      mismatch ^= val;

      bit_buf <<= 1;
      NEEDBITS (bit_buf, bits);

      continue;

    }

  entry_2:
    if (bit_buf >= 0x04000000) {

      tab = DCT_B14_8 - 4 + UBITS (bit_buf, 8);

      i += tab->run;
      if (i < 64)
	goto normal_code;

      // escape code

      i += UBITS (bit_buf << 6, 6) - 64;
      if (i >= 64)
	break;  // illegal, but check needed to avoid buffer overflow

      j = scan[i];

      DUMPBITS (bit_buf, bits, 12);
      NEEDBITS (bit_buf, bits);
      val = DequantizeInter(SBITS (bit_buf, 12) + SBITS (bit_buf, 1) , quantizer_scale, quant_matrix[i]);

      Saturate(val);
      coeff[j] = val;
      mismatch ^= val;

      DUMPBITS (bit_buf, bits, 12);
      NEEDBITS (bit_buf, bits);

      continue;

    } else if (bit_buf >= 0x02000000) {
      tab = DCT_B14_10 - 8 + UBITS (bit_buf, 10);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else if (bit_buf >= 0x00800000) {
      tab = DCT_13 - 16 + UBITS (bit_buf, 13);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else if (bit_buf >= 0x00200000) {
      tab = DCT_15 - 16 + UBITS (bit_buf, 15);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    } else {
      tab = DCT_16 + UBITS (bit_buf, 16);
      bit_buf <<= 16;
      bit_buf |= bs.GetNextWord () << (bits + 16);
      i += tab->run;
      if (i < 64)
	goto normal_code;
    }
    break;  // illegal, but check needed to avoid buffer overflow
  }
  coeff[63] ^= mismatch & 1;
  DUMPBITS (bit_buf, bits, 2);        // dump end of block code
  bs.RestoreFromLocal(bit_buf,bits);
}

--- NEW FILE: vidsyntax.cc ---
/********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#include "video12/vidsyntax.hh"
#include "video12/constants.hh"
#include "libvideogfx/utility/bitstream/membitsread.hh"

#include <iostream.h>
#include <iomanip.h>


const int PoolSize = 10;

static PictureData* pdpool[PoolSize];
static int pdpoolsize=0;


PictureData* PictureData::GetPictureData(int w,int h)
{
  if (pdpoolsize==0)
    {
      PictureData* picdata = new PictureData;

      if (w>0)
	picdata->m_codedimage.Create(w,h);

      return picdata;
    }
  else
    {
      pdpoolsize--;
      PictureData* picdata = pdpool[pdpoolsize];

      if (picdata->m_codedimage.AskWidth()  != w ||
	  picdata->m_codedimage.AskHeight() != h)
	{
	  if (w!=0)
	    picdata->m_codedimage.Create(w,h);
	}

      return picdata;
    }
}


void PictureData::FreePictureData(PictureData* p)
{
  if (pdpoolsize==PoolSize)
    ::delete p;
  else
    pdpool[pdpoolsize++] = p;
}



static const int frameratecode2framerate[16] =
{
   0, 24000*10000/1001, 24*10000,25*10000, 30000*10000/1001, 30*10000,50*10000,60000*10000/1001,
  60*10000, 0,0,0,0,0,0,0
};

#if 0
static const uint8 default_intra_matrix[8][8] = {
  {  8, 16, 19, 22, 26, 27, 29, 34 },
  { 16, 16, 22, 24, 27, 29, 34, 37 },
  { 19, 22, 26, 27, 29, 34, 34, 38 },
  { 22, 22, 26, 27, 29, 34, 37, 40 },
  { 22, 26, 27, 29, 32, 35, 40, 48 },
  { 26, 27, 29, 32, 35, 40, 48, 58 },
  { 26, 27, 29, 34, 38, 46, 56, 69 },
  { 27, 29, 35, 38, 46, 56, 69, 83 }
};
#endif

static const uint8 default_intra_matrix_zigzag[64] = {
   8,16,16,19,16,19,22,22,22,22,22,22,26,24,26,27,27,27,26,26,26,26,27,27,29,29,29,34,34,
  34,37,34,34,32,32,29,29,35,34,35,35,37,38,40,40,40,38,38,46,46,48,48,58,56,56,69,69,83
};


void DecodeSequenceHeader(class MemBitstreamReader& bs,SequenceHeader& sh,QuantMatrices& qmat)
{
  SequenceHeader* seqh = &sh;


  /**** Read sequence header ****/

  Assert(bs.PeekBits(32)==STARTCODE_SEQUENCE_HEADER);
  bs.SkipBits(32);

  seqh->m_IsMPEG2 = false; /* This will be set to "true" if there is a Sequence-Extension following */
  seqh->m_Width  = bs.GetBits(12);
  seqh->m_Height = bs.GetBits(12);
  seqh->m_AspectRatio = bs.GetBits(4);
  seqh->m_Framerate = frameratecode2framerate[bs.GetBits(4)];

  /* TODO
     if (seqh->m_Framerate == 0.0)
     ShowNote(ErrSev_Warning,"MPEG stream error: framerate set to invalid value !");
  */

  seqh->m_Bitrate = bs.GetBits(18);
  bs.SkipBits(1);
  seqh->m_VBVBufferSize = bs.GetBits(10);
  seqh->m_Constrained = bs.GetBits(1);


  // Reset qmatrices or set them to new values.

  // Set Intra-Matrix
  if (bs.GetBits(1))
    {
      for (int i=0;i<64;i++)
	qmat.m_LumIntra[i] = qmat.m_ChrIntra[i] = bs.GetBits(8);
    }
  else
    {
      for (int i=0;i<64;i++)
	qmat.m_LumIntra[i] = qmat.m_ChrIntra[i] = default_intra_matrix_zigzag[i];
    }

  // Set Inter-Matrix
  if (bs.GetBits(1))
    {
      for (int i=0;i<64;i++)
	qmat.m_LumInter[i] = qmat.m_ChrInter[i] = bs.GetBits(8);
    }
  else
    {
      for (int i=0;i<64;i++)
	qmat.m_LumInter[i] = qmat.m_ChrInter[i] = 16;
    }

  // fill MPEG-2 entries to match MPEG-1 semantics

  seqh->m_ProgressiveSequence = false;
  seqh->m_ChromaFormat = CHROMA_420;
  seqh->m_LowDelay = false;
}


void DecodeSequenceHeaderExt(class MemBitstreamReader& bs2,SequenceHeader& sh)
{
  SequenceHeader* seqh = &sh;

  /**** Decode Sequence-Extension ****/
    
  seqh->m_IsMPEG2 = true;
    
  seqh->m_Profile = bs2.GetBits(4);
  seqh->m_Level   = bs2.GetBits(4);
  seqh->m_ProgressiveSequence = bs2.GetBits(1);
  seqh->m_ChromaFormat = bs2.GetBits(2);
  seqh->m_Width  |= bs2.GetBits(2)<<12;
  seqh->m_Height |= bs2.GetBits(2)<<12;
  seqh->m_Bitrate |= bs2.GetBits(12)<<18;
  bs2.SkipBits(1);
  seqh->m_VBVBufferSize |= bs2.GetBits(8)<<10;
  seqh->m_LowDelay = bs2.GetBits(1);
  seqh->m_Framerate *= bs2.GetBits(2)+1;
  seqh->m_Framerate /= bs2.GetBits(5)+1;
}


void TraceSequenceHeader(const SequenceHeader& sh)
{
#ifndef NDEBUG
  const SequenceHeader* seqh = &sh;

    {
      cout << "SequenceHeader:\n"
           << "  MPEG-2:       " << (seqh->m_IsMPEG2?"true":"false") << endl
           << "  width:        " << seqh->m_Width << endl
           << "  height:       " << seqh->m_Height << endl
           << "  aspect code:  " << ((int)seqh->m_AspectRatio) << endl
           << "  framerate:    " << seqh->m_Framerate/10000 << '.' << seqh->m_Framerate%10000 << endl
           << "  bitrate:      " << seqh->m_Bitrate << endl
           << "  VBV buf.size: " << seqh->m_VBVBufferSize << endl
           << "  constrained:  " << (seqh->m_Constrained?"true":"false") << endl
	;
      //           << "  load intra qm:" << (!seqh->m_qmatrices.m_Hint_Std_Intra_Lum?"true":"false") << endl
      //           << "  load inter qm:" << (!seqh->m_qmatrices.m_Hint_Std_Inter_Lum?"true":"false") << endl;

      if (seqh->m_IsMPEG2)
        {
          cout << "  profile:      ";
          switch (seqh->m_Profile)
            {
            case PROFILE_Simple: cout << "Simple\n"; break;
            case PROFILE_Main:   cout << "Main\n";   break;
            case PROFILE_SNRScalable: cout << "SNR\n"; break;
            case PROFILE_SpatiallyScalable: cout << "Spatial\n"; break;
            case PROFILE_High:   cout << "High\n"; break;
            default: cout << "UNKNOWN !\n"; break;
            }

          cout << "  level:        ";
          switch (seqh->m_Level)
            {
            case LEVEL_Low:    cout << "Low\n"; break;
            case LEVEL_Main:   cout << "Main\n"; break;
            case LEVEL_High1440: cout << "High1440\n"; break;
            case LEVEL_High:   cout << "High\n"; break;
            default: cout << "UNKNOWN !\n"; break;
            }

          cout << "  progr. seq.:  " << (seqh->m_ProgressiveSequence?"true":"false") << endl;
          cout << "  chroma format:";
          switch (seqh->m_ChromaFormat)
            {
            case CHROMA_420: cout << "4:2:0\n"; break;
            case CHROMA_422: cout << "4:2:2\n"; break;
            case CHROMA_444: cout << "4:4:4\n"; break;
            default: cout << "UNKNOWN !\n"; break;
            }

          cout << "  low delay:    " << (seqh->m_LowDelay?"true":"false") << endl;
        }
    }
#endif
}



void DecodeGOPHeader(class MemBitstreamReader& bs,GOPHeader& gopdata)
{
  /**** Read GOP-Header ****/

  Assert(bs.PeekBits(32)==STARTCODE_GROUP_START);
  bs.SkipBits(32);

  GOPHeader* goph = &gopdata;

  goph->m_TimeCode_DropFrameFlag = bs.GetBits(1);
  goph->m_TimeCode_Hours         = bs.GetBits(5);
  goph->m_TimeCode_Minutes       = bs.GetBits(6);
  bs.SkipBits(1);
  goph->m_TimeCode_Seconds       = bs.GetBits(6);
  goph->m_TimeCode_Pictures      = bs.GetBits(6);

  goph->m_ClosedGOP = bs.GetBits(1);
  goph->m_BrokenLink= bs.GetBits(1);
}


void TraceGOPHeader(const GOPHeader& gopdata)
{
  const GOPHeader* goph = &gopdata;

#ifndef NDEBUG
  cout << "GOP-Header:\n"
       << "  Timecode:    " << ((int)goph->m_TimeCode_Hours)
       << ':' << setfill('0') << setw(2) << ((int)goph->m_TimeCode_Minutes)
       << ':' << setw(2) << ((int)goph->m_TimeCode_Seconds)
       << '.' << setw(2) << ((int)goph->m_TimeCode_Pictures);
  if (goph->m_TimeCode_DropFrameFlag) cout << " drop-frame-flag set";
  cout << "\n  closed GOP:  " << (goph->m_ClosedGOP?"true":"false") << endl
       << "  broken link: " << (goph->m_BrokenLink?"true":"false") << endl;
#endif
}


void DecodePictureHeader(class MemBitstreamReader& bs,PictureHeader& pichdr)
{
  Assert(bs.PeekBits(32)==STARTCODE_PICTURE_START);
  bs.SkipBits(32);

  pichdr.m_temporal_reference  = bs.GetBits(10);
  pichdr.m_picture_coding_type = bs.GetBits(3);
  pichdr.m_vbv_delay           = bs.GetBits(16);

  pichdr.m_fullpel_fw = false;
  pichdr.m_fullpel_bw = false;
  pichdr.m_fcode[0][0] = 7;
  pichdr.m_fcode[0][1] = 7;
  pichdr.m_fcode[1][0] = 7;
  pichdr.m_fcode[1][1] = 7;

  if (pichdr.m_picture_coding_type == 2 ||
      pichdr.m_picture_coding_type == 3)
    {
      pichdr.m_fullpel_fw = bs.GetBits(1);
      pichdr.m_fcode[0][0] =
	pichdr.m_fcode[0][1] = bs.GetBits(3);
    }

  if (pichdr.m_picture_coding_type == 3)
    {
      pichdr.m_fullpel_bw = bs.GetBits(1);
      pichdr.m_fcode[1][0] =
	pichdr.m_fcode[1][1] = bs.GetBits(3);
    }

  while (bs.GetBits(1)==1)
    {
      bs.SkipBits(8);
    }


  // Set fields that are variable in MPEG-2 but constant in MPEG-1.
  // These will be overwritten again, when decoding MPEG-2 Picture Coding Extension.

  pichdr.m_IsMPEG2 = false;
  pichdr.m_intra_dc_precision = 8;
  pichdr.m_picture_structure  = PICSTRUCT_FramePicture;
  pichdr.m_concealment_motion_vectors = false;
  pichdr.m_progressive_frame  = true;
  pichdr.m_q_scale_type       = 0;
  pichdr.m_intra_vlc_format   = 0;
  pichdr.m_alternate_scan     = false;
  pichdr.m_progressive_frame  = true;
  pichdr.m_composite_display_flag = false;
  pichdr.m_frame_pred_frame_dct = true;

  pichdr.m_intra_dc_precision_shift = 11-pichdr.m_intra_dc_precision;
}


void DecodePictureCodingExt(class MemBitstreamReader& bs2,PictureHeader& pichdr)
{
  pichdr.m_IsMPEG2 = true;

  pichdr.m_fullpel_fw = false;
  pichdr.m_fullpel_bw = false;
  pichdr.m_fcode[0][0] = bs2.GetBits(4);
  pichdr.m_fcode[0][1] = bs2.GetBits(4);
  pichdr.m_fcode[1][0] = bs2.GetBits(4);
  pichdr.m_fcode[1][1] = bs2.GetBits(4);

  pichdr.m_intra_dc_precision   = bs2.GetBits(2)+8;
  pichdr.m_picture_structure    = bs2.GetBits(2);
  pichdr.m_top_field_first      = bs2.GetBits(1);
  pichdr.m_frame_pred_frame_dct = bs2.GetBits(1);
  pichdr.m_concealment_motion_vectors = bs2.GetBits(1);
  pichdr.m_q_scale_type         = bs2.GetBits(1);
  pichdr.m_intra_vlc_format     = bs2.GetBits(1);
  pichdr.m_alternate_scan       = bs2.GetBits(1);
  pichdr.m_repeat_first_field   = bs2.GetBits(1);
  pichdr.m_chroma420type        = bs2.GetBits(1);
  pichdr.m_progressive_frame    = bs2.GetBits(1);

  pichdr.m_composite_display_flag = bs2.GetBits(1);
  if (pichdr.m_composite_display_flag)
    {
      pichdr.m_v_axis           = bs2.GetBits(1);
      pichdr.m_field_sequence   = bs2.GetBits(3);
      pichdr.m_sub_carrier      = bs2.GetBits(1);
      pichdr.m_burst_amplitude  = bs2.GetBits(7);
      pichdr.m_sub_carrier_phase= bs2.GetBits(8);
    }

  pichdr.m_intra_dc_precision_shift = 11-pichdr.m_intra_dc_precision;
}


void TracePictureHeader(const PictureHeader& pichdr)
{
  cout << "PictureHeader:\n"
       << "  temporal reference:    " << pichdr.m_temporal_reference << endl
       << "  picture_coding_type:   ";
  switch (pichdr.m_picture_coding_type)
    {
    case PICTYPE_I: cout << 'I'; break;
    case PICTYPE_P: cout << 'P'; break;
    case PICTYPE_B: cout << 'B'; break;
    case PICTYPE_D: cout << 'D'; break;
    default: cout << "UNKNOWN !"; break;
    }

  cout << "\n  vbv_delay:             " << pichdr.m_vbv_delay << endl
       << "  fullpel forward mv:    " << (pichdr.m_fullpel_fw?"true":"false") << endl
       << "  fullpel backward mv:   " << (pichdr.m_fullpel_bw?"true":"false") << endl;
  for (int i=0;i<2;i++)
    for (int j=0;j<2;j++)
      {
	cout << "  fcode[" << i << "][" << j << "] ("
	     << (i?"bw/":"fw/") << (j?'v':'h')
	     << "):    " << ((int)pichdr.m_fcode[i][j]) << endl;
      }

  if (pichdr.m_IsMPEG2)
    {
      cout << "  intra dc precision:    " << ((int)pichdr.m_intra_dc_precision) << endl
	   << "  picture structure:     ";
      switch (pichdr.m_picture_structure)
	{
	case PICSTRUCT_TopField: cout << "top field\n"; break;
	case PICSTRUCT_BottomField: cout << "bottom field\n"; break;
	case PICSTRUCT_FramePicture: cout << "frame picture\n"; break;
	}
 
      cout << "  top field first:       " << (pichdr.m_top_field_first?"true":"false") << endl
	   << "  frame pred frame dct:  " << (pichdr.m_frame_pred_frame_dct?"true":"false") << endl
	   << "  concealment mvs:       " << (pichdr.m_concealment_motion_vectors?"true":"false") << endl
	   << "  q-scale type:          " << ((int)pichdr.m_q_scale_type) << endl
	   << "  intra vlc format:      " << ((int)pichdr.m_intra_vlc_format) << endl
	   << "  alternate scan:        " << (pichdr.m_alternate_scan?"true":"false") << endl
	   << "  repeat first field:    " << (pichdr.m_repeat_first_field?"true":"false") << endl
	   << "  chroma420type(obsolet):" << ((int)pichdr.m_chroma420type) << endl
	   << "  progressive frame:     " << (pichdr.m_progressive_frame?"true":"false") << endl;
          
      if (pichdr.m_composite_display_flag)
	{
	  cout << "  v-axis:                " << ((int)pichdr.m_v_axis) << endl
	       << "  field sequence:        " << ((int)pichdr.m_field_sequence) << endl
	       << "  sub carrier:           " << ((int)pichdr.m_sub_carrier) << endl
	       << "  burst amplitude:       " << ((int)pichdr.m_burst_amplitude) << endl
	       << "  sub carrier phase:     " << ((int)pichdr.m_sub_carrier_phase) << endl;
	}
    }
}


#include "libvideogfx/containers/array2.cc"

template class Array2<Macroblock>;

--- NEW FILE: vlc.hh ---
/********************************************************************************
  video12/vlc.hh

  purpose:
   Utility functions to decode Variable Length Codes

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   28/Dec/1998 - Dirk Farin
     - Added support for table B15 (intra_vlc_format==1)
   26/Dec/1998 - Dirk Farin
     - Added GetMotionCode()
   15/Nov/1998 - Dirk Farin
     - first implementation
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_VIDEO12_VLC_HH
#define DVDVIEW_VIDEO12_VLC_HH

#include "types.hh"

int GetMBAddrIncr (class FastBitBuf&);
int GetCBP        (class FastBitBuf&);
int GetDClumSize  (class FastBitBuf&);
int GetDCchromSize(class FastBitBuf&);
int GetMotionCode (class FastBitBuf&);

bool GetRunLen(FastBitBuf& bs,int& run,int& value ,bool B15,bool first,bool MPEG1);

const uint16 MBMODE_QUANT   = 0x10;
const uint16 MBMODE_MVFWD   = 0x08;
const uint16 MBMODE_MVBKW   = 0x04;
const uint16 MBMODE_PATTERN = 0x02;
const uint16 MBMODE_INTRA   = 0x01;

// extern int (* GetMBMode[5])(class FastBitBuf&);  // use picture_coding_type to index into array

#endif

--- NEW FILE: vdecoder.cc ---
/********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
[...2318 lines suppressed...]
  }
#endif

#if 0
  {
  ImageParam_YUV param; d_outbuf[d_outbuf_len-1].m_image.GetParam(param);
  Pixel*const* p = ((Image_YUV<Pixel>*)&d_outbuf[d_outbuf_len-1].m_image)->AskFrameU();
  for (int y=0;y<param.height/2;y++)
    for (int x=0;x<param.width/2;x++)
      p[y][x]=128;
  }
  {
  ImageParam_YUV param; d_outbuf[d_outbuf_len-1].m_image.GetParam(param);
  Pixel*const* p = ((Image_YUV<Pixel>*)&d_outbuf[d_outbuf_len-1].m_image)->AskFrameV();
  for (int y=0;y<param.height/2;y++)
    for (int x=0;x<param.width/2;x++)
      p[y][x]=128;
  }
#endif


--- NEW FILE: vlc.cc ---
/********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
[...1451 lines suppressed...]
            dest[vlc_base+i].value = n;
            dest[vlc_base+i].bits  = src[n].nBits;
          }
      }
}

static class DummyInit_23487635
{
public:
  DummyInit_23487635()
    {
      InitTAB(vlc_mbaddrinc_tab,vlc_mbaddr,-1);
      InitTAB(vlc_mbmode_P_tab,vlc_mbmode_P,0);
      InitTAB(vlc_mbmode_B_tab,vlc_mbmode_B,0);
      InitTAB(vlc_cbp_tab,vlc_cbp,-1);
      InitTAB(vlc_DClum_tab,vlc_DClum,-1);
      InitTAB(vlc_DCchrom_tab,vlc_DCchrom,-1);
      InitTAB(vlc_mcode_tab,vlc_mc,-1);
    }
} dummyinit_23845673;

--- NEW FILE: output.hh ---
/********************************************************************************
  video12/output.hh

  purpose:

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
    16/Apr/2000 - Dirk Farin
     - new method: FreePictureData()
    04/Oct/1999 - Dirk Farin
     - integration into new architecture (code extracted out of
       old vsink.h)
    05/May/1999 - Dirk Farin
     - interface definition
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_VIDEO12_OUTPUT_HH
#define DVDVIEW_VIDEO12_OUTPUT_HH

#include "types.hh"
#include "libvideogfx/graphics/basic/image.hh"
#include "video12/vidsyntax.hh"
#include "system/system1.hh"



struct DecodedImageData
{
  DecodedImageData()
    : // m_IsDirectBuffer(false),
      m_picdata_needed(false),
      m_picdata1(NULL), m_picdata2(NULL)
    { }

  virtual ~DecodedImageData() { }

  Image_YUV<Pixel> m_image;

  int  m_width,m_height;          // Total size of frame picture.

  int  m_src_y_start,m_src_y_end; // Number of lines in m_image, filled with data.
  int  m_dst_y_start;             // Position of decoded lines in destination image.
  bool m_field_lines;             // Skip every second line if in field mode.
  bool m_may_modify;              // If image contents may be modified by postprocessors.

  bool ContainsOutputLine(int y)
  {
    if (y>=m_dst_y_start &&
	y<=m_dst_y_start+m_src_y_end-m_src_y_start)
      {
	if (!m_field_lines)
	  return true;
	if (m_field_lines && (m_dst_y_start&1)==(y&1))
	  return true;
      }

    return false;
  }

  int GetIndexForOutputLine(int y)
  {
    return y-m_dst_y_start+m_src_y_start;
  }

#if 0
  bool m_IsDirectBuffer; /* Data goes directly to the display.
			    The decoder will have to wait for the PTS before decoding.
			    In the other case, the decoder will decode as soon as
			    possible and wait for the PTS before actually sending
			    the output data.
			 */
#endif

  bool m_picdata_needed;
  
  PictureHeader m_pichdr1; //  first field or frame
  PictureHeader m_pichdr2; //  second field
  PictureData* m_picdata1; //  first field or frame
  PictureData* m_picdata2; //  second field

  SystemTimingInformation m_timing; /* When two fields are contained, the times for
				       the first one. */


  void FreePictureData()
  {
    if (m_picdata1) PictureData::FreePictureData(m_picdata1);
    if (m_picdata2) PictureData::FreePictureData(m_picdata2);
    m_picdata1 = m_picdata2 = NULL;
  }
};



class DecodedPictureSink
{
public:
  virtual ~DecodedPictureSink() { }

  void ShowAllMBRows(DecodedImageData* data)
  {
    ImageParam_YUV param;
    data->m_image.GetParam(param);

    data->m_src_y_start = 0;
    data->m_src_y_end   = param.height-1;
    data->m_dst_y_start = 0;
    data->m_field_lines = false;

    ShowMBRows(data);
  }

  virtual void BeginPicture(const DecodedImageData*) { }
  virtual void ShowMBRows(DecodedImageData*) = 0;
  virtual void FinishedPicture() { };

  virtual bool  NeedsPictureData(uint3 pictype) const { return false; }
  virtual bool  NeedsMBData     (uint3 pictype) const { return false; }
};


class VideoOutput : public DecodedPictureSink
{
public:
  virtual bool PictureAvailable() = 0;
  virtual PTS  AskPTSOfNextToBeDisplayed() const = 0;
  virtual void ShowPicture() { }
};

#endif

--- NEW FILE: macroblock.hh ---
/*********************************************************************
  video12/macroblock.hh
    Macroblock syntax.

  purpose:

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   30/Sep/1999 - Dirk Farin
     - Integrated code into CVS.
   05/May/99 - Dirk Farin
     - Took structure definitions out of viddec.hh
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_VIDEO12_MACROBLOCK_HH
#define DVDVIEW_VIDEO12_MACROBLOCK_HH

#include "types.hh"


struct DCTBlock
{
  short m_coeff[64]; // in custom order, implementation dependent
  bool  m_hasdata; // true iff m_coeff[][]!=0 exists
  int   m_nCoeffs;
};

struct MotionVector
{
  int   m_habs, m_vabs;

  uint1 m_vertical_field_select;  // 0 ist TopField.
   int2 m_dmvector[2];
};

struct Macroblock
{
  uint7  m_quantiser_scale_code; /* 1 bis 31  */

  bool   m_IsIntra;
  DCTBlock m_blks[12];

  // Fuer Frame-Pictures mit 'frame_pred_frame_dct==0' und vorhandenen DCT-Koeff.
  bool m_FieldDCT;

  enum FrameMotionType { FRMT_FieldBased=1, FRMT_FrameBased=2, FRMT_DualPrime=3 };
  enum FieldMotionType { FIMT_FieldBased=1, FIMT_16x8MC=2,     FIMT_DualPrime=3 };
  union {
    // MotionComp.Type fuer Pictures mit 'picture_structure==frame' und
    // 'frame_pred_frame_dct==0'. Ist 'frame_pred_frame_dct==1', so wird FRMT_FrameBased angenommen,
    // m_frame_motion_type aber nicht in den Bitstream codiert.
    enum FrameMotionType m_frame_motion_type;
    
    // MotionComp.Type fuer Pictures mit 'picture_structure!=frame'.
    enum FieldMotionType m_field_motion_type;
  };
  uint2 m_motion_vector_count;
  enum { MVFormat_Field, MVFormat_Frame } m_mv_format;
  bool  m_dmv;

  inline void SetFrameMotionType(FrameMotionType,int temporal_weight_class=0);
  inline void SetFieldMotionType(FieldMotionType);

  MotionVector m_vector[4 /*r*/][2 /*s*/]; // t in der Struktur
  bool m_HasMotionForward;  // <- wird auch als Consealment-Vektor-Flag ( vector[0][0] ) benutzt
  bool m_HasMotionBackward;

#define m_forward1  m_vector[0][0]
#define m_forward2  m_vector[1][0]
#define m_backward1 m_vector[0][1]
#define m_backward2 m_vector[1][1]
};

#include "error.hh"

inline void Macroblock::SetFrameMotionType(FrameMotionType t,int temporal_weight_class)
{
#if 0
  m_motion_vector_count = 1;
  m_mv_format = MVFormat_Frame;

#else

  m_frame_motion_type = t;
  m_mv_format = MVFormat_Frame;

  if (t==FRMT_FrameBased)
    {
      m_motion_vector_count = 1;
      m_dmv = 0;
    }
  else if (t==FRMT_FieldBased)
    {
      if (temporal_weight_class <= 1)
        m_motion_vector_count = 2;
      else
        m_motion_vector_count = 1;
      m_dmv = 0;
    }
  else if (t==FRMT_DualPrime)
    {
      m_motion_vector_count = 1;
      m_dmv = 1;
    }
  else
    {
      // TODO Error(ErrSev_Warning,"Invalid stream: undefined \"frame motion type\". Using \"frame-based\"\n");
      m_motion_vector_count = 1;
      m_dmv = 0;
    }
#endif
}

#include <iostream.h>

inline void Macroblock::SetFieldMotionType(FieldMotionType t)
{
#if 0
  m_motion_vector_count = 1;
#else
  m_field_motion_type = t;
  m_mv_format = MVFormat_Field;

  switch (t)
    {
    case FIMT_FieldBased:
      m_motion_vector_count = 1;
      m_dmv = 0;
      break;
    case FIMT_16x8MC:
      //cout << "16x8\n";
      m_motion_vector_count = 2;
      m_dmv = 0;
      break;
    case FIMT_DualPrime:
      m_motion_vector_count = 1;
      m_dmv = 1;
      break;
    default:
      Assert(0);
      break;
    }
#endif
}

#endif

--- NEW FILE: vdecoder.hh ---
/********************************************************************************
  video12/vdecoder.hh
    Video syntax decoder

  purpose:

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   07/set/2000 - Dirk Farin
     - Decoder is now tolerant against bitstream errors.
   05/Sep/2000 - Dirk Farin
     - Output reorganized again. B-pictures can now be sent slice-wise
       to the output device.
     - Major cleanup. Syntax decoding parts have been moved to vidsyntax.cc.
   16/Apr/2000 - Dirk Farin
     - Major architectur change. Output is now PUSH-oriented.
     - PictureData additional information data structure is filled
       out, when data is needed by postprocessors.
     - Bugfix: The two very last pictures of the stream are shown now.
     - Some cleanup, removing old obsolete code.
   22/Oct/1999 - Dirk Farin
     - Robust even when streams start in the middle of a sequence.
   30/Sep/1999 - Dirk Farin
     - integrated into CVS, major code cleanup and rewrite, quantization
       is now done already in the syntax decoder for efficiency reasons
       (coefficients that are 0 do not need to be quantized).
   17/May/1999 - Dirk Farin
     - Correct decoding of bitstreams with concealment MVs.
   31/Jan/1999 - Dirk Farin
     - Bugfix: MPEG-1 macroblock stuffing was not recognized.
   13/Jan/1999 - Dirk Farin
     - Bugfix: Skip USER-DATA startcode-packets. Streams with such
               data could not be read in earlier versions.
   11/Jan/1999 - Dirk Farin
     - Allocation of PictureData is now done using a pool of
       preallocated structures. This results in a huge reduction
       of system time.
   10/Jan/1999 - Dirk Farin
     - Bugfix: Motionvektor decoding was erroneous when fcode was
               not equal to 1.
   09/Jan/1999 - Dirk Farin
     - Bugfix: end of slice now detected, when remaining bits < 2 and
               not < 8, as there may be some very small MBs at the end
               of a slice (for example a MVFwd-only MB in P needs only
               4 bits). The condition is not redundant as the second
               condition (remaining bits!=0 to leave loop) does not work
               when remaining bits==0.
   07/Jan/1999 - Dirk Farin
     - Bugfix: motionvector activation flags were not set
     - Bugfix: motionvector predictors were not updated
   19/Dec/1998 -> 26/Dec/1998 - Dirk Farin
     - first implementation
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_VIDEO12_VDECODER_HH
#define DVDVIEW_VIDEO12_VDECODER_HH

#include "video12/modules/mcomp_sgl_simple.hh"
#include "types.hh"
#include "video12/output.hh"
#include "video12/vidsyntax.hh"
#include "video12/constants.hh"
#include "error.hh"


struct VideoSyntaxTrace_Options
{
  VideoSyntaxTrace_Options();

  bool Trace_SeqH;
  bool Trace_GOPH;
  bool Trace_PicH;
  bool Trace_SlcH;
  bool Trace_MB;
  bool Trace_SliceData;
  bool Trace_DCTCoeff;
};

struct VideoFrameSkip_Options
{
  VideoFrameSkip_Options();

  bool DecodeI;
  bool DecodeP;
  bool DecodeB;
};

struct VideoDecoder_Options
  : public VideoSyntaxTrace_Options,
    public VideoFrameSkip_Options
{
};


class VideoDecoder
{
public:
   VideoDecoder(class PacketSource&);
  ~VideoDecoder();

  void SetOptions(const VideoDecoder_Options& opts) { d_options=opts; }
  void SetSink(DecodedPictureSink& s) { d_sink=&s; }

  void Reset() { d_SequenceHeaderRead=false; }
  bool DecodeAFrame(); /* Decode a picture. It is NOT guaranteed that the picture will
			  appear at the output of the video decoder. It may be buffered
			  for some time or get completely lost because of jitter
			  reduction or the like.
			  However, it is guaranteed that no more than one picture will
			  appear at the output.
		       */

private:
  VideoDecoder_Options d_options;

  class PacketSource*       d_source;
  class DecodedPictureSink* d_sink;

  ImageSpec_YUV specs;

  // Values out of last SequenceHeader.
  bool   d_IsMPEG2;            // (redundant)
  uint16 d_MBWidth,d_MBHeight; // (redundant) size of image in macroblock units
  uint2  d_ChromaFormat;       // (redundant)
  int    d_dctblks;         // number of dct blocks in one macroblock
  int    d_intra_cbp;       // CBP for intra blocks
  int    mb_chr_w,mb_chr_h; // Size of chroma components in a macroblock.

  // Values out of last PictureHeader.
  int    d_dc_pred;  // initial DC-prediction value

  enum { None,DataPartitioning,SNR,Spatial,Temporal } d_scalability_mode;


  // Syntax decoder

  PictureHeader  d_pichdr;  // current picture data  (macroblock array not used!)
  PictureData*   d_picdata;

  void PostSequenceHeader();
  void PostPictureHeader(const SystemTimingInformation& timing);

  void DecodeExtensions(int n);
  void DecodeSlice    (class FastBitBuf&);
  void FlushBSlice(int MBRow); /* Send physical MB-row 0 to output at the specified position
				  and reset decoding pointers to the first MB in row 0. */
  void motion_vector  (struct MotionVector&,int s,bool dmv,class FastBitBuf&);


  // pushback buffer

  class SysPacket_Packet* GetNextPacket();
  void PushbackPacket(class SysPacket_Packet*);

  class SysPacket_Packet* d_next_packet;

  QuantMatrices d_quant_zz;  // current quantization matrices in zig-zag-order
  QuantMatrices d_quant_bs;  // current quantization matrices in current bitstream scanning order


  inline void AdvancePtrsMB();
  inline void AdvancePtrsMBRow();


  // -------------- Video Decoder ------------------

  SequenceHeader d_seqdata;
  bool   d_SequenceHeaderRead; // If d_seqdata contains valid data.

  bool d_BFrameAvailable;   /* True iff a complete B-picture (1 frame picture or both fields) has
			       been decoded to d_curr and is ready for display. */
  bool d_FirstFieldInFrame; /* True iff the next picture to be decoded is either the first field
			       or a frame picture. */
  bool d_next_IsEmpty;      /* True iff d_next does not contain an image. */
  bool d_skip_this_frame;

  DecodedImageData* d_last; // The picture that already has been displayed.
  DecodedImageData* d_curr; // The currently decoded B-picture.
  DecodedImageData* d_next; // The I/P-picture to be displayed after the pictures above.
  Pixel*const* ptr_y;   // current bitmaps while picture decoding
  Pixel*const* ptr_cb;  // current bitmaps while picture decoding
  Pixel*const* ptr_cr;  // current bitmaps while picture decoding

  int bytesperline_lum;
  int bytesperline_chr;

  int lineskip_lum;
  int lineskip_chr;

  int d_field_offset; // 0 for topfield, frames / 1 for bottom field

  // --- Pointers to current image data used in the calculations
  // current decoding destination
  Pixel* sp_curr_y;
  Pixel* sp_curr_cr;
  Pixel* sp_curr_cb;
  // forward reference pictures
  Pixel* sp_last_y [2]; // 0 - top field / 1 - bottom field
  Pixel* sp_last_cr[2];
  Pixel* sp_last_cb[2];
  // backward reference pictures
  Pixel* sp_next_y [2];
  Pixel* sp_next_cr[2];
  Pixel* sp_next_cb[2];

  // Pointers to current decoding macroblock position
  Pixel* dp_y;
  Pixel* dp_cr;
  Pixel* dp_cb;

  enum TempRef { LAST,NEXT };
  inline void SetSPOffsets(TempRef sp_tempref,int n,TempRef predref,bool field,bool topfield=true);

  void SetReferencePtrsFrm(struct PixPtrs_const&,const struct MotionVector&);
  void SetReferencePtrsFld(struct PixPtrs_const&,const struct MotionVector&);
  void SetHalfPelFlags1(struct MotionCompensation_SglMB::MCData&,const struct MotionVector&);
  void SetHalfPelFlags2(struct MotionCompensation_SglMB::MCData&,
                        const struct MotionVector& last,
                        const struct MotionVector& next);
  void MC_Frame_FrameBased(const Macroblock& mb,uint16 mb_mode);
  void MC_Frame_FieldBased(const Macroblock& mb,uint16 mb_mode);
  void MC_Field_FieldBased(const Macroblock& mb,uint16 mb_mode);
  void MC_Field_16x8(const Macroblock& mb,uint16 mb_mode);

  // Decoder

  int  d_scan[2][64]; // scan pattern 0 - zigzag / 1 - alternate
  class MotionCompensation_SglMB* d_motcomp;
};

//inline int DequantizeIntra(int value,int qscale,int matrix);
inline int DequantizeInter(int value,int qscale,int matrix);
//inline void Saturate(int& value);

class Excpt_StreamError : public Excpt_Base
{
public:
  Excpt_StreamError(ErrorSeverity sev,const char* text) : Excpt_Base(sev,text) { }
};

class Excpt_Huffman : public Excpt_StreamError
{
public:
  Excpt_Huffman(ErrorSeverity sev,const char* text) : Excpt_StreamError(sev,text) { }
};

#endif

--- NEW FILE: viddec_mods.cc ---
/********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#include "video12/viddec_mods.hh"
//#include "video12/modules/idct_std.hh"
//#include "video12/modules/mcomp_std.hh"
//#include "video12/modules/mcomp_scalar.hh"
//#include "video12/modules/mcomp_scalar_unaligned.hh"
#include "video12/modules/mcomp_sgl_simple.hh"

#if ENABLE_MMX
//#include "video12/modules/mcomp_mmx.hh"
#include "video12/modules/mcomp_sgl_mmx.hh"
#include "libvideogfx/arch/x86/CPUcapabilities.hh"
#endif


#if 0
MotionCompensation* MotionCompensation::Create()
{
#if 0 //ENABLE_MMX
  if (cpucapabilities.HasMMX())
    return new MotionCompensation_MMX;
#endif

#if 0 //UNALIGNED_MEMORYACCESS
  return new MotionCompensation_Scalar_Unaligned;
#endif

  return new MotionCompensation_Scalar;

  return new MotionCompensation_Standard;
}
#endif

#include <iostream.h>

MotionCompensation_SglMB* MotionCompensation_SglMB::Create()
{
#if ENABLE_MMX
  if (cpucapabilities.HasMMX())
    return new MotionCompensation_SglMB_MMX;
#endif

  return new MotionCompensation_SglMB_Simple;
}


--- NEW FILE: constants.hh ---
/********************************************************************************
  video12/constants.hh
    MPEG stream constants.

  purpose:

  notes:

  to do:

  author(s):
   - Dirk Farin, farin at ti.uni-mannheim.de

  modifications:
   04/Oct/1999 - Dirk Farin
     - integrated code to CVS
 ********************************************************************************
    Copyright (C) 1999  Dirk Farin

    This program is distributed under GNU Public License (GPL) as
    outlined in the COPYING file that comes with the source distribution.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef DVDVIEW_VIDEO12_CONSTANTS_HH
#define DVDVIEW_VIDEO12_CONSTANTS_HH

#include "types.hh"

// -------------------------------- Startcodes -------------------------------------

// Video Startcodes

#define STARTCODE_PICTURE_START   0x00000100
#define STARTCODE_USER_DATA       0x000001B2
#define STARTCODE_SEQUENCE_HEADER 0x000001B3
#define STARTCODE_SEQUENCE_ERROR  0x000001B4
#define STARTCODE_EXTENSION_START 0x000001B5
#define STARTCODE_SEQUENCE_END    0x000001B7
#define STARTCODE_GROUP_START     0x000001B8

// System Startcodes

#define STARTCODE_ISO11172_END    0x000001B9
#define STARTCODE_PACK_START      0x000001BA
#define STARTCODE_SYSTEM_HEADER_START 0x000001BB

// Packet Startcodes

#define STARTCODE_VIDEO0     0x000001E0
#define STARTCODE_VIDEO1     0x000001E1
#define STARTCODE_VIDEO2     0x000001E2
#define STARTCODE_AUDIO0     0x000001C0
#define STARTCODE_AUDIO1     0x000001C1
#define STARTCODE_AUDIO2     0x000001C2

inline bool IsMPEG_SLICE_START (uint8 code) { return code>=0x01 && code<=0xAF; }
inline bool IsMPEG_VIDEO_STREAM(uint8 code) { return code>=0xE0 && code<=0xEF; }
inline bool IsMPEG_AUDIO_STREAM(uint8 code) { return code>=0xC0 && code<=0xDF; }
inline bool IsMPEG_PACKETCODE  (uint8 code) { return code>=0xC0 && code<=0xEF; }


// ---------- extension_start_code_identifier -----------

const uint4 EXTID_SequenceExtension         = 0x1;
const uint4 EXTID_SequenceDisplayExtension  = 0x2;
const uint4 EXTID_QuantMatrixExtension      = 0x3;
const uint4 EXTID_CopyrightExtension        = 0x4;
const uint4 EXTID_SequenceScalableExtension = 0x5;
const uint4 EXTID_PictureDisplayExtension   = 0x7;
const uint4 EXTID_PictureCodingExtension    = 0x8;
const uint4 EXTID_PictureSpatialScalableExtension  = 0x9;
const uint4 EXTID_PictureTemporalScalableExtension = 0xA;


// ---------- aspect_ratio_information ------------

const uint4 SAR_Square = 0x01;     // Sample Aspect Ratio = 1.0  (square pixels)
const uint4 DAR_3_4    = 0x02;     // Display Aspect Ratio = 3/4
const uint4 DAR_9_16   = 0x03;     // Display Aspect Ratio = 9/16
const uint4 DAR_2_2_21 = 0x04;     // Display Aspect Ratio = 2/2.21


// ---------- frame_rate_code ------------

const uint4 FRAMERATE_23_976 = 0x01;  // 23.976 fps
const uint4 FRAMERATE_24     = 0x02;  // 24     fps
const uint4 FRAMERATE_25     = 0x03;  // 25     fps
const uint4 FRAMERATE_29_97  = 0x04;  // 29.97  fps
const uint4 FRAMERATE_30     = 0x05;  // 30     fps
const uint4 FRAMERATE_50     = 0x06;  // 50     fps
const uint4 FRAMERATE_59_94  = 0x07;  // 59.94  fps
const uint4 FRAMERATE_60     = 0x08;  // 60     fps


// --------- profile_identification ----------

const uint3 PROFILE_Simple      = 0x5;
const uint3 PROFILE_Main        = 0x4;
const uint3 PROFILE_SNRScalable = 0x3;
const uint3 PROFILE_SpatiallyScalable = 0x2;
const uint3 PROFILE_High        = 0x1;


// --------- level_identification ------------

const uint4 LEVEL_Low      = 0xA;
const uint4 LEVEL_Main     = 0x8;
const uint4 LEVEL_High1440 = 0x6;
const uint4 LEVEL_High     = 0x4;


// --------- chroma_format ----------

const uint2 CHROMA_420 = 1;
const uint2 CHROMA_422 = 2;
const uint2 CHROMA_444 = 3;


// --------- picture_coding_type --------

const uint3 PICTYPE_I = 1;
const uint3 PICTYPE_P = 2;
const uint3 PICTYPE_B = 3;
const uint3 PICTYPE_D = 4;


// -------- picture_structure ---------

const uint2 PICSTRUCT_TopField     = 1;
const uint2 PICSTRUCT_BottomField  = 2;
const uint2 PICSTRUCT_FramePicture = 3;

#endif




More information about the dslinux-commit mailing list