]> git.vomp.tv Git - vompclient-marten.git/commitdiff
HDTV for Windows
authorChris Tallon <chris@vomp.tv>
Mon, 8 Feb 2010 15:12:52 +0000 (15:12 +0000)
committerChris Tallon <chris@vomp.tv>
Mon, 8 Feb 2010 15:12:52 +0000 (15:12 +0000)
71 files changed:
afeed.cc
audio.h
audiomvp.cc
audiomvp.h
audiowin.cc
audiowin.h
boxx.cc
boxx.h
channel.cc
channel.h
command.cc
defines.h
demuxer.cc
demuxer.h
demuxeraudio.cc
demuxeraudio.h
demuxermedia.cc
demuxerts.cc
demuxerts.h
demuxervdr.cc
draintarget.h
dsallocator.cc
dsallocator.h
dssourcefilter.cc
dssourcefilter.h
dssourcepin.cc
dssourcepin.h
eventdispatcher.cc
eventdispatcher.h
main.cc
mediafile.cc
osd.h
osdwin.cc
osdwin.h
player.cc
player.h
playerlivetv.cc
playerlivetv.h
readme.win
recinfo.h
recording.cc
recording.h
stream.cc
stream.h
surface.cc
surfacewin.cc
tcp.cc
teletextdecodervbiebu.cc
teletextdecodervbiebu.h
vaudioselector.cc
vcolourtuner.cc
vdr.cc
vdrresponsepacket.cc
vdrresponsepacket.h
vfeed.cc
video.cc
video.h
videomvp.cc
videomvp.h
videowin.cc
videowin.h
vmediaview.cc
vmediaview.h
vradiorec.h
vrecording.cc
vrecordinglist.cc
vvideorec.cc
vvideorec.h
vwelcome.cc
winmain.cc
wjpeg.cc

index 22b5b45d6908e9f3cd202ed21ec1240b49a51f3d..43e8c865660be0861d74fcb222f812ffb202c887 100644 (file)
--- a/afeed.cc
+++ b/afeed.cc
@@ -76,20 +76,21 @@ void AFeed::threadMethod()
 
       if (alen)
       {
-        cb.call(this);
+          cb.call(this);
 //        Log::getInstance()->log("Afeed", Log::DEBUG, "written");
       }
       else
       {
         //MILLISLEEP(100);
-        MILLISLEEP(20); //Performance Issue Marten
+        MILLISLEEP(5); //Performance Issue Marten
       }
     }
     else
     {
       Demuxer::getInstance()->flushAudio();
+      //Log::getInstance()->log("AFeed", Log::DEBUG, "No data delay");
       //MILLISLEEP(100);
-      MILLISLEEP(20); //Performance Issue
+      MILLISLEEP(5); //Performance Issue
     }
   }
 }
diff --git a/audio.h b/audio.h
index a2a326360efce407f748b6082d7219e0bde92fe7..082bc27bff0592a43011ec49173fb1a125ce9488 100644 (file)
--- a/audio.h
+++ b/audio.h
@@ -58,6 +58,7 @@ class Audio : public DrainTarget, public AbstractOption
     virtual int mute()=0;
     virtual int unMute()=0;
     virtual bool supportsAc3()=0;
+    virtual bool maysupportAc3(){return false;}
 
     int volumeUp();
     int volumeDown();
index 8e6034d17cdce377b9f16aeeab495ba44e15380d..b9ba62e5ececd330251fcb1c93e733067cf79861 100644 (file)
@@ -235,7 +235,7 @@ void AudioMVP::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
   packet = mplist.front();
 }
 
-UINT AudioMVP::DeliverMediaSample(const UCHAR* buffer, UINT* samplepos)
+UINT AudioMVP::DeliverMediaSample(UCHAR* buffer, UINT* samplepos)
 {
   int written = ::write(fdAudio, buffer + packet.pos_buffer + *samplepos,
                                  packet.length - *samplepos);
index 0ac1cccd849a74cb49bbbc1cbce9a31857acc653..b1d9ff6ead3946d6480e1ac6dc679a6e20984fd0 100644 (file)
@@ -89,7 +89,7 @@ class AudioMVP : public Audio
 
     //Writing Data to Audiodevice
     virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);
-    virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos);
+    virtual UINT DeliverMediaSample(UCHAR* buffer, UINT *samplepos);
     virtual long long SetStartOffset(long long curreftime, bool *rsync) { return 0; };
     virtual void ResetTimeOffsets();
 
index f6a51b236877cd331e59288d699aae1888955693..aeb8347c2dbb76964e2fc34559493bf505ed644a 100644 (file)
@@ -353,7 +353,7 @@ bool AudioWin::saveOptionstoServer()
     return true;
 }
 
-UINT AudioWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
+UINT AudioWin::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
 {
   DeliverMediaPacket(mediapacket, buffer, samplepos);
   if (*samplepos == mediapacket.length) {
@@ -363,8 +363,8 @@ UINT AudioWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
   else return 0;
 }
 
-UINT AudioWin::DeliverMediaPacket(MediaPacket packet,
-     const UCHAR* buffer,
+UINT AudioWin::DeliverMediaPacket(const MediaPacket packet,
+     UCHAR* buffer,
      UINT *samplepos)
 {
 
@@ -418,7 +418,7 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet,
   UINT haveToCopy;
   if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample
     //samplepos=0;
-    MILLISLEEP(10);
+    //MILLISLEEP(10);
     return *samplepos;
   }
   ms_pos=ms->GetActualDataLength();
@@ -428,7 +428,7 @@ UINT AudioWin::DeliverMediaPacket(MediaPacket packet,
     vw->DeliverAudioMediaSample(); //we are full!
     if (!vw->getCurrentAudioMediaSample(&ms) || ms==NULL) {// get the current sample
       //samplepos=0;
-      MILLISLEEP(10);
+      //MILLISLEEP(10);
       return *samplepos;
     }
     ms_pos=ms->GetActualDataLength();
index e71c14a7d6f6771e2632c86577aa085cb3e1eed5..69e66d8bd04f3cf87bece43cbfca10ef51a3c926 100644 (file)
@@ -66,8 +66,8 @@ class AudioWin : public Audio
 
     // Writing Data to Audiodevice
     virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);
-    virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos);
-    UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos);
+    virtual UINT DeliverMediaSample(UCHAR* buffer, UINT *samplepos);
+    UINT DeliverMediaPacket(MediaPacket packet, UCHAR* buffer, UINT *samplepos);
     
     int dsInitAudioFilter(IGraphBuilder* dsgraphbuilder);
     const AudioFilterDescList *getAudioFilterList(int &selected);
@@ -77,6 +77,7 @@ class AudioWin : public Audio
      bool selectMp3AudioFilter(int filter);
 
     virtual bool supportsAc3();
+    virtual bool maysupportAc3(){return true;} // We are not sure maybe we support this, allows the player to select ac3, if there is no other option
   private:
     MediaPacket mediapacket;
   public:
diff --git a/boxx.cc b/boxx.cc
index 81b8878e1d307b87102f0a174a6108b11ed9e0b3..0bc3570100444634866cff6f196b40ecd3bc2920 100644 (file)
--- a/boxx.cc
+++ b/boxx.cc
@@ -21,6 +21,7 @@
 #include "boxx.h"
 #include "bitmap.h"
 #include "log.h"
+#include <stdlib.h>
 
 char Boxx::numBoxxes = 0;
 
diff --git a/boxx.h b/boxx.h
index 0e7a4b93fdf57b1f31ac5759849a0c505b603238..b38f0a540f4093dbb18195cbefa6ed578dc3bdd2 100644 (file)
--- a/boxx.h
+++ b/boxx.h
@@ -33,9 +33,15 @@ using namespace std;
 #ifdef WIN32
 #include "surfacewin.h"
 #else
+
+#ifdef _MIPS_ARCH
+#include "surfacedirectfb.h"
+#else
 #include "surfacemvp.h"
 #endif
 
+#endif
+
 class Bitmap;
 
 class Boxx
index 052d0425df8bd20b3e605b92b3e3c41b314f3c13..8f2f5bcf5ec7a613d328f183c9a226aaab1542d1 100644 (file)
@@ -37,6 +37,8 @@ Channel::Channel()
   numDPids = 0;
   numSPids = 0;
 
+  vstreamtype=2; //Mpeg2
+
 }
 
 Channel::~Channel()
index a8134704c2cc88b4196baa8ee7d37e76b5887563..c3688f24545502ff8ea8948f015694df35c1f466 100644 (file)
--- a/channel.h
+++ b/channel.h
@@ -47,6 +47,7 @@ class Channel
 
     ULONG number;
     ULONG type;
+       UCHAR vstreamtype;
     char* name;
 
     int index;
index a4f7ae69e1887583e9224b5c0bf99a28b6d8c152..d2b222e9d340c04bf42820ad3342be37de229ab2 100644 (file)
@@ -113,7 +113,10 @@ int Command::shutdown()
 void Command::stop()
 {
 //  VDR::getInstance()->cancelFindingServer();
+       logger->log("Command", Log::NOTICE, "Command stop1...");
+       
   udp.shutdown();
+  logger->log("Command", Log::NOTICE,  "Command stop2...");
   irun = 0;
 }
 
@@ -138,7 +141,11 @@ void Command::doWallpaper()
   if (video->getFormat() == Video::PAL)
   {
     logger->log("Command", Log::DEBUG, "PAL wallpaper selected");
+#ifndef _MIPS_ARCH    
     wallpaperj->init("/wallpaperPAL.jpg");
+#else
+    wallpaperj->init("wallpaperPAL.jpg");
+#endif
   }
   else
   {
@@ -200,9 +207,10 @@ void Command::run()
 #else
     ReleaseMutex(masterLock);
 #endif
-    button = remote->getButtonPress(2);  // FIXME why is this set to 2 and not 0? so it can quit
+       
+    button = remote->getButtonPress(2);  // FIXME why is this set to 2 and not 0? so it can quit 
     // something happened, lock and process
-
+       
     //  logger->log("Command", Log::DEBUG, "WANT LOCK");
 #ifndef WIN32
     pthread_mutex_lock(&masterLock);
@@ -223,6 +231,7 @@ void Command::run()
 #else
   ReleaseMutex(masterLock);
 #endif
+   
 }
 
 void Command::postMessage(Message* m)
@@ -572,7 +581,11 @@ void Command::doReboot()
   // just kill it...
   logger->log("Command", Log::NOTICE, "Reboot");
 #ifndef WIN32
+#ifndef _MIPS_ARCH
   reboot(LINUX_REBOOT_CMD_RESTART);
+#else
+  stop();
+#endif
 #endif //Would we support this on windows?
 }
 
index 9f5815ef6f2483a7d9ab771501934fd8a96191ff..f082f533d5518bb3305d44a457e051e121276fcd 100644 (file)
--- a/defines.h
+++ b/defines.h
@@ -52,8 +52,12 @@ void MILLISLEEP(ULONG a);
 
   int max(int, int);
   int min(UINT, int);
-  
+#ifdef _MIPS_ARCH  
+  #define Surface_TYPE SurfaceDirectFB
+#else
   #define Surface_TYPE SurfaceMVP
+#endif
+
   #define Thread_TYPE ThreadP
   #include <pthread.h>
   #define ThreadID_TYPE pthread_t
index 054baca7ab953b11dfc88acf2d76294b877cbfd6..0c07d00bdcd8e1255d0f21922f86c0c7935536ea 100644 (file)
 
 #include <cstdlib>
 
+#include <math.h>
+
 #define DEMUXER_SEQ_HEAD 0x000001B3
 #define DEMUXER_PIC_HEAD 0x00000101
+
+#define DEMUXER_H264_ACCESS_UNIT 0x00000109
+#define DEMUXER_H264_SEQ_PARAMETER_SET 0x00000107
+
+
 #define SEEK_THRESHOLD 150000 // About 1.5 seconds
 
 // Statics
 const int Demuxer::FrameRates[9] = { 0, 23, 24, 25, 29, 30, 50, 59, 60 };
 Demuxer* Demuxer::instance = NULL;
 
+class NALUUnit {
+public:
+    NALUUnit(const UCHAR* buf,UINT length_buf);
+    ~NALUUnit();
+
+inline    UINT getBits(UINT num_bits);
+    UINT getUe();
+    int getSe();
+    bool isEonalu() {return eonalu;};
+
+protected:
+    UCHAR* nalu_buf;
+    UINT nalu_length;
+    UINT pos;
+    UCHAR bit_pos;
+    UCHAR working_byte;
+    UINT last_bytes;
+    bool eonalu;
+};
+
+NALUUnit::NALUUnit(const UCHAR *buf, UINT length_buf)
+{
+    nalu_length=0;
+    nalu_buf=NULL;
+    pos=0;
+    bit_pos=0;
+    working_byte=0;
+    last_bytes=0;
+    eonalu=false;
+
+    UINT nalu_start=0;
+    UINT nalu_end=0;
+    UINT pattern =(((UINT)buf[ 0] << 16) |
+                   ((UINT)buf[1] <<  8) |
+                    (UINT)buf[2]  );
+    nalu_start=3;
+    while (pattern != 0x000001)
+    {
+        if (++nalu_start >= length_buf) return;
+        pattern = ((pattern << 8) | buf[nalu_start])&0x00FFFFFF;
+    }
+    nalu_end=nalu_start+1;
+    pattern = ((pattern << 8) | buf[nalu_end])&0x00FFFFFF;
+
+    while (pattern != 0x000001 && pattern != 0x000000)
+    {
+        if (++nalu_end >= length_buf) { nalu_end+=3;break;};
+        pattern = ((pattern << 8) | buf[nalu_end])&0x00FFFFFF;
+    }
+    nalu_end-=3;
+    nalu_end=min(length_buf-1,nalu_end);
+    nalu_length=nalu_end-nalu_start;
+    nalu_buf=(UCHAR*)malloc(nalu_length);
+    memcpy(nalu_buf,buf+nalu_start,nalu_length);
+    pos=1;
+}
+
+NALUUnit::~NALUUnit()
+{
+    if (nalu_buf) free(nalu_buf);
+}
+
+inline UINT NALUUnit::getBits(UINT num_bits)
+{
+    if (num_bits==0) return 0; //???
+    UINT remain_bits=num_bits;
+    UINT work=0;
+    //May be slow, but should work!
+    while (remain_bits>0) {
+        if (bit_pos==0) {
+            if (pos<nalu_length)
+            {
+                last_bytes=(last_bytes<<8) & nalu_buf[pos];
+                if ((last_bytes & 0x00FFFFFF) == 0x000003) pos++; //emulation prevention byte
+                 if (pos<nalu_length)
+                 {
+                     working_byte=nalu_buf[pos];
+                     pos++;
+                 } 
+                 else
+                 {
+                     working_byte=0;
+                     eonalu=true;
+                 }
+            } 
+            else
+            {
+                working_byte=0;
+                eonalu=true;
+            }
+
+        }
+        UINT fetch_bits=min(remain_bits,8-bit_pos);
+        work=work <<fetch_bits;
+        //work|=((working_byte>>bit_pos) & (0xFF>>(8-fetch_bits)));
+        work|=(working_byte &(0xFF>>(bit_pos)))>>(8-fetch_bits-bit_pos);
+        remain_bits-=fetch_bits;
+        bit_pos=(bit_pos+fetch_bits)%8;
+    }
+    return work;
+}
+
+UINT NALUUnit::getUe()
+{
+    int leadbits=-1;
+    bool bit;
+    for( bit = 0; !bit && !eonalu; leadbits++ )
+        bit = getBits(1);
+    if (eonalu) return true;
+    return ((1 << leadbits)-1)+getBits(leadbits);
+}
+
+int NALUUnit::getSe()
+{
+    UINT input=getUe();
+    if (input==0) return 0;
+    int output=((input+1)>>1);
+    if (input & 0x1) output*=-1;
+    return output;
+}
+
+
+
 static const int PESPacket_initial_size = 2000;
 
 // PESPacket methods
@@ -145,7 +275,7 @@ UCHAR PESPacket::operator[] (UINT index) const
     return data[index];
 }
 
-UINT PESPacket::findPictureHeader() const
+UINT PESPacket::findPictureHeader(bool h264) const
 {
   if (size < 12) return 0;
   UINT pattern = ( ((UINT)data[ 8] << 24) |
@@ -153,15 +283,25 @@ UINT PESPacket::findPictureHeader() const
                    ((UINT)data[10] <<  8) |
                     (UINT)data[11]  );
   UINT pos = 11;
-  while (pattern != DEMUXER_PIC_HEAD)
-  {
-    if (++pos >= size) return 0;
-    pattern = (pattern << 8) | data[pos];
+  if (h264) {
+         
+         while (pattern != DEMUXER_H264_ACCESS_UNIT)
+         {
+                 if (++pos >= size) return 0;
+                 pattern = (pattern << 8) | data[pos];
+         }
+         return pos-3;
+  } else {
+         while (pattern != DEMUXER_PIC_HEAD)
+         {
+                 if (++pos >= size) return 0;
+                 pattern = (pattern << 8) | data[pos];
+         }
+         return pos-3;
   }
-  return pos-3;
 }
 
-UINT PESPacket::findSeqHeader() const
+UINT PESPacket::findSeqHeader(bool h264) const
 {
   if (seq_header != 1) return seq_header;
   if (size < 12) return 0;
@@ -170,16 +310,31 @@ UINT PESPacket::findSeqHeader() const
                    ((UINT)data[10] <<  8) |
                     (UINT)data[11]  );
   UINT pos = 11;
-  while (pattern != DEMUXER_SEQ_HEAD)
+  if (h264) {
+      while ((pattern & 0xFFFFFF1F) != DEMUXER_H264_SEQ_PARAMETER_SET)
+         {
+                 if (++pos >= size)
+                 {
+                         seq_header = 0;
+                         return 0;
+                 }
+                 pattern = (pattern << 8) | data[pos];
+         }
+         seq_header = pos - 3;
+  } 
+  else 
   {
-    if (++pos >= size)
-    {
-      seq_header = 0;
-      return 0;
-    }
-    pattern = (pattern << 8) | data[pos];
+         while (pattern != DEMUXER_SEQ_HEAD)
+         {
+                 if (++pos >= size)
+                 {
+                         seq_header = 0;
+                         return 0;
+                 }
+                 pattern = (pattern << 8) | data[pos];
+         }
+         seq_header = pos - 3;
   }
-  seq_header = pos - 3;
   return seq_header;
 }
 
@@ -194,6 +349,9 @@ Demuxer::Demuxer()
   vid_seeking = aud_seeking = false;
   video_pts = audio_pts = 0;
   ispre_1_3_19 = false;
+  packetnum=0;
+  h264 = false;
+  fps = 25.0;
 }
 
 Demuxer::~Demuxer()
@@ -208,7 +366,7 @@ Demuxer* Demuxer::getInstance()
 }
 
 int Demuxer::init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, DrainTarget* teletext,
-                  ULONG demuxMemoryV, ULONG demuxMemoryA, ULONG demuxMemoryT, DVBSubtitles* tsubtitles)
+                  ULONG demuxMemoryV, ULONG demuxMemoryA, ULONG demuxMemoryT,double infps, DVBSubtitles* tsubtitles)
 {
   if (!initted)
   {
@@ -227,7 +385,7 @@ int Demuxer::init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, D
   } else {
       isteletextdecoded = false;
   }
-
+  fps=infps;
   reset();
   initted = true;
   subtitles = tsubtitles;
@@ -244,6 +402,8 @@ void Demuxer::reset()
   aspect_ratio = (enum AspectRatio) 0;
   frame_rate = bit_rate = 0;
   ispre_1_3_19 = false;
+  h264 = false;
+  packetnum=0;
 
   for (int i = 0; i <= (PESTYPE_AUDMAX - PESTYPE_AUD0); i++)
   {
@@ -345,13 +505,15 @@ bool Demuxer::submitPacket(PESPacket& packet)
   UINT sent = 0;
   UCHAR packet_type = packet.getPacketType();
   const UCHAR* packetdata = packet.getData();
-
   if (packet_type >= PESTYPE_VID0 && packet_type <= PESTYPE_VIDMAX)
   {
     if (video_current == -1) video_current = packet_type;
     if (video_current == packet_type && !vid_seeking)
-      sent = videostream.put(&packetdata[0], packet.getSize(), MPTYPE_VIDEO);
-    else
+       {
+        sent = videostream.put(&packetdata[0], packet.getSize(), h264?MPTYPE_VIDEO_H264:MPTYPE_VIDEO_MPEG2,packetnum);
+        if (sent) packetnum++;
+       }
+       else
       sent = packet.getSize();
   }
   else if (packet_type >= PESTYPE_AUD0 && packet_type <= PESTYPE_AUDMAX)
@@ -359,8 +521,11 @@ bool Demuxer::submitPacket(PESPacket& packet)
     if (audio_current == -1) audio_current = packet_type;
     avail_mpaudchan[packet_type - PESTYPE_AUD0] = true;
     if (audio_current == packet_type && !aud_seeking)
-      sent = audiostream.put(&packetdata[0], packet.getSize(), MPTYPE_MPEG_AUDIO);
-    else
+       {
+      sent = audiostream.put(&packetdata[0], packet.getSize(), MPTYPE_MPEG_AUDIO,packetnum);
+         if (sent)  packetnum++;
+       }
+       else
       sent = packet.getSize();
   }
   else if (packet_type == PESTYPE_PRIVATE_1 &&
@@ -370,7 +535,8 @@ bool Demuxer::submitPacket(PESPacket& packet)
     avail_ac3audchan[packet.getSubstream() - PESTYPE_SUBSTREAM_AC30] = true;
     if (packet.getSubstream() == audio_current)
     {
-      sent = audiostream.put(&packetdata[0], packet.getSize(), (ispre_1_3_19)? MPTYPE_AC3_PRE13 : MPTYPE_AC3);
+      sent = audiostream.put(&packetdata[0], packet.getSize(), (ispre_1_3_19)? MPTYPE_AC3_PRE13 : MPTYPE_AC3,packetnum);
+         if (sent) packetnum++;
     }
     else
     {
@@ -397,7 +563,7 @@ bool Demuxer::submitPacket(PESPacket& packet)
     if (teletext_current == -1) teletext_current = packet.getSubstream();
     if (teletext_current == packet.getSubstream() )
     {
-        sent = teletextstream.put(&packetdata[0], packet.getSize(), MPTYPE_TELETEXT);
+        sent = teletextstream.put(&packetdata[0], packet.getSize(), MPTYPE_TELETEXT,packetnum);
     }
     else 
     {
@@ -417,129 +583,250 @@ bool Demuxer::submitPacket(PESPacket& packet)
 
 void Demuxer::parsePacketDetails(PESPacket& packet)
 {
-  if (packet.getPacketType() >= PESTYPE_AUD0 &&
-      packet.getPacketType() <= PESTYPE_AUDMAX)
-  {
-    // Extract audio PTS if it exists
-    if (packet.hasPTS())
+    if (packet.getPacketType() >= PESTYPE_AUD0 &&
+        packet.getPacketType() <= PESTYPE_AUDMAX)
     {
-      audio_pts = packet.getPTS();
-      // We continue to seek on the audio if the video PTS that we
-      // are trying to match is ahead of the audio PTS by at most
-      // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
-      if (aud_seeking && !vid_seeking &&
-          !( (video_pts_seek > audio_pts &&
-              video_pts_seek - audio_pts < SEEK_THRESHOLD)
-              ||
-             (video_pts_seek < audio_pts &&
-              video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
-      {
-        aud_seeking = 0;
-        Log::getInstance()->log("Demuxer", Log::DEBUG,
-            "Leaving  audio sync: Audio PTS = %llu", audio_pts);
-      }
-    }
-  }
-  else if (packet.getPacketType() == PESTYPE_PRIVATE_1) // Private stream
-  {
-    //Inspired by vdr's device.c
-    int payload_begin = packet[8]+9;
-    unsigned char substream_id = packet[payload_begin];
-    unsigned char substream_type = substream_id & 0xF0;
-    unsigned char substream_index = substream_id & 0x1F;
-pre_1_3_19_Recording: //This is for old recordings stuff and live TV
-    if (ispre_1_3_19)
-    {
-      substream_id = PESTYPE_PRIVATE_1;
-      substream_type = 0x80;
-      substream_index = 0;
-    }
-    switch (substream_type)
-    {
-      case 0x20://SPU
-      case 0x30://SPU
-        packet.setSubstream(substream_id);
-        break;
-      case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there?
-        break;
-      case 0x80: //ac3, currently only one ac3 track per recording supported
-        packet.setSubstream(substream_type+substream_index);
-
         // Extract audio PTS if it exists
         if (packet.hasPTS())
         {
-          audio_pts = packet.getPTS();
-          // We continue to seek on the audio if the video PTS that we
-          // are trying to match is ahead of the audio PTS by at most
-          // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
-          if (aud_seeking && !vid_seeking &&
-              !( (video_pts_seek > audio_pts &&
-                  video_pts_seek - audio_pts < SEEK_THRESHOLD)
-              ||
-              (video_pts_seek < audio_pts &&
-                    video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
-          {
-            aud_seeking = 0;
-            Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving  audio sync: Audio PTS = %llu", audio_pts);
-          }
+            audio_pts = packet.getPTS();
+            // We continue to seek on the audio if the video PTS that we
+            // are trying to match is ahead of the audio PTS by at most
+            // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
+            if (aud_seeking && !vid_seeking &&
+                !( (video_pts_seek > audio_pts &&
+                video_pts_seek - audio_pts < SEEK_THRESHOLD)
+                ||
+                (video_pts_seek < audio_pts &&
+                video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
+            {
+                aud_seeking = 0;
+                Log::getInstance()->log("Demuxer", Log::DEBUG,
+                    "Leaving  audio sync: Audio PTS = %llu", audio_pts);
+            }
         }
-        break;
-      case 0x10: //Teletext Is this correct?
-          packet.setSubstream(substream_id);
-          // Extract teletxt PTS if it exists
-        if (packet.hasPTS())
-        {
-          teletext_pts = packet.getPTS();
-        }
-        break;
-      default:
-        if (!ispre_1_3_19)
+    }
+    else if (packet.getPacketType() == PESTYPE_PRIVATE_1) // Private stream
+    {
+        //Inspired by vdr's device.c
+        int payload_begin = packet[8]+9;
+        unsigned char substream_id = packet[payload_begin];
+        unsigned char substream_type = substream_id & 0xF0;
+        unsigned char substream_index = substream_id & 0x1F;
+pre_1_3_19_Recording: //This is for old recordings stuff and live TV
+        if (ispre_1_3_19)
         {
-          ispre_1_3_19=true; //switching to compat mode and live tv mode
-          goto pre_1_3_19_Recording;
+            substream_id = PESTYPE_PRIVATE_1;
+            substream_type = 0x80;
+            substream_index = 0;
         }
-        else
+        switch (substream_type)
         {
-          packet.setSubstream(0);
+        case 0x20://SPU
+        case 0x30://SPU
+            packet.setSubstream(substream_id);
+            break;
+        case 0xA0: //LPCM //not supported yet, is there any LPCM transmissio out there?
+            break;
+        case 0x80: //ac3, currently only one ac3 track per recording supported
+            packet.setSubstream(substream_type+substream_index);
+
+            // Extract audio PTS if it exists
+            if (packet.hasPTS())
+            {
+                audio_pts = packet.getPTS();
+                // We continue to seek on the audio if the video PTS that we
+                // are trying to match is ahead of the audio PTS by at most
+                // SEEK_THRESHOLD. We consider the possibility of PTS wrap.
+                if (aud_seeking && !vid_seeking &&
+                    !( (video_pts_seek > audio_pts &&
+                    video_pts_seek - audio_pts < SEEK_THRESHOLD)
+                    ||
+                    (video_pts_seek < audio_pts &&
+                    video_pts_seek + (1LL<<33) - audio_pts < SEEK_THRESHOLD) ))
+                {
+                    aud_seeking = 0;
+                    Log::getInstance()->log("Demuxer", Log::DEBUG, "Leaving  audio sync: Audio PTS = %llu", audio_pts);
+                }
+            }
+            break;
+        case 0x10: //Teletext Is this correct?
+            packet.setSubstream(substream_id);
+            // Extract teletxt PTS if it exists
+            if (packet.hasPTS())
+            {
+                teletext_pts = packet.getPTS();
+            }
+            break;
+        default:
+            if (!ispre_1_3_19)
+            {
+                ispre_1_3_19=true; //switching to compat mode and live tv mode
+                goto pre_1_3_19_Recording;
+            }
+            else
+            {
+                packet.setSubstream(0);
+            }
+            break;
         }
-        break;
     }
-  }
-  else if (packet.getPacketType() >= PESTYPE_VID0 &&
-           packet.getPacketType() <= PESTYPE_VIDMAX)
-  {
-    // Extract video PTS if it exists
-    if (packet.hasPTS()) video_pts = packet.getPTS();
-
-    // If there is a sequence header, extract information
-    UINT pos = packet.findSeqHeader();
-    if (pos > 1)
+    else if (packet.getPacketType() >= PESTYPE_VID0 &&
+        packet.getPacketType() <= PESTYPE_VIDMAX)
     {
-      pos += 4;
-      if (pos+6 >= packet.getSize()) return;
-      horizontal_size = ((int)packet[pos] << 4) | ((int)packet[pos+1] >> 4);
-      vertical_size = (((int)packet[pos+1] & 0xf) << 8) | (int)packet[pos+2];
-      setAspectRatio((enum AspectRatio)(packet[pos+3] >> 4));
-      frame_rate = packet[pos+3] & 0x0f;
-      if (frame_rate >= 1 && frame_rate <= 8)
-        frame_rate = FrameRates[frame_rate];
-      else
-        frame_rate = 0;
-      bit_rate = ((int)packet[pos+4] << 10) |
-                 ((int)packet[pos+5] << 2) |
-                 ((int)packet[pos+6] >> 6);
-      if (vid_seeking)
-      {
-        vid_seeking = 0;
-        video_pts_seek = video_pts;
-        Log::getInstance()->log("Demuxer", Log::DEBUG,
-            "Entering audio sync: Video PTS = %llu", video_pts);
-        Log::getInstance()->log("Demuxer", Log::DEBUG,
-            "Entering audio sync: Audio PTS = %llu", audio_pts);
-      }
-      return;
+        // Extract video PTS if it exists
+        if (packet.hasPTS()) video_pts = packet.getPTS();
+
+        // If there is a sequence header, extract information
+        UINT pos = packet.findSeqHeader(h264);
+        if (pos > 1)
+        {
+            if (!h264) {
+                pos += 4;
+                if (pos+6 >= packet.getSize()) return;
+                horizontal_size = ((int)packet[pos] << 4) | ((int)packet[pos+1] >> 4);
+                
+                vertical_size = (((int)packet[pos+1] & 0xf) << 8) | (int)packet[pos+2];
+
+                setAspectRatio((enum AspectRatio)(packet[pos+3] >> 4));
+                frame_rate = packet[pos+3] & 0x0f;
+                if (frame_rate >= 1 && frame_rate <= 8)
+                    frame_rate = FrameRates[frame_rate];
+                else
+                    frame_rate = 0;
+                bit_rate = ((int)packet[pos+4] << 10) |
+                    ((int)packet[pos+5] << 2) |
+                    ((int)packet[pos+6] >> 6);
+            } 
+            else
+            {
+                /* Chris and Mark I know this is ugly, should we move this to a method  of PESPacket or to NALUUnit what would be better?
+                This looks so ugly since the header includes variable length parts and I have to parse through the whole header to get the wanted information*/
+                NALUUnit nalu(packet.getData()+pos,packet.getSize()-pos);
+                profile=nalu.getBits(8);
+                nalu.getBits(8); //constraints
+                nalu.getBits(8); //level_idc
+                nalu.getUe(); //seq_parameter_set_id
+                if (profile==100 || profile==110 || profile==122 || profile==144)
+                {
+                    if (nalu.getUe()==3)
+                    {
+                        nalu.getBits(1);
+                    }
+                    nalu.getUe(); //bit depth lume
+                    nalu.getUe(); //bit depth chrome
+                    nalu.getBits(1);
+                    if (nalu.getBits(1))
+                    {
+                        for (int i=0;i<8;i++){
+                            if (nalu.getBits(1))
+                            {
+                                if (i<6)
+                                {
+                                    UINT lastscale=8;
+                                    UINT nextscale=8;
+                                    for (int j=0;j<16;j++) {
+                                        if (nextscale!=0) {
+                                            UINT delta=nalu.getSe();
+                                            nextscale=(lastscale+delta+256)%256;
+                                        }
+                                        lastscale=(nextscale==0)?lastscale:nextscale;
+                                    }
+                                }
+                                else
+                                {
+                                    UINT lastscale=8;
+                                    UINT nextscale=8;
+                                    for (int j=0;j<64;j++) {
+                                        if (nextscale!=0) {
+                                            UINT delta=nalu.getSe();
+                                            nextscale=(lastscale+delta+256)%256;
+                                        }
+                                        lastscale=(nextscale==0)?lastscale:nextscale;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                nalu.getUe(); //log2framenum
+                UINT temp=nalu.getUe();
+                if (temp==0) //pict order
+                    nalu.getUe();
+                else if (temp==1) {
+                    nalu.getBits(1);
+                    nalu.getSe();
+                    nalu.getSe();
+                    UINT temp2=nalu.getUe();
+                    for (int i=0;i<temp2;i++)
+                        nalu.getSe();
+                }
+                nalu.getUe(); //Num refframes
+                nalu.getBits(1);
+                horizontal_size=(nalu.getUe()+1)*16;
+                
+                vertical_size=(nalu.getUe()+1)*16;
+                int interlaced=nalu.getBits(1);
+                vertical_size*=(2-interlaced);
+                
+                if (!interlaced) nalu.getBits(1);
+                nalu.getBits(1);
+                if (nalu.getBits(1))
+                {
+                    nalu.getUe();
+                    nalu.getUe();
+                    nalu.getUe();
+                    nalu.getUe();
+                }
+                if (nalu.getBits(1))
+                {
+                    if (nalu.getBits(1))
+                    {
+                        UINT aspectratioidc=nalu.getBits(8);
+                        bool hasaspect=false;
+                        const float aspects[]={1., 1./1.,12./11.,10./11.,16./11.,40./33.,
+                            24./11.,20./11.,32./11.,80./33.,18./11.,15./11.,64./33.,160./99.,4./3.,3./2.,2./1.};
+                      
+                        float aspectratio=((float) horizontal_size)/((float) vertical_size);
+                        if (aspectratioidc<=16) 
+                        {
+                            hasaspect=true;
+                            aspectratio*=aspects[aspectratioidc];
+                           
+                        }
+                        else if (aspectratioidc==255)
+                        {
+                            int t_sar_width=nalu.getBits(16);
+                            int t_sar_height=nalu.getBits(16);
+                            if (t_sar_width!=0 && t_sar_height!=0)
+                            {
+                                hasaspect=true;
+                                aspectratio*=((float)t_sar_width)/((float)t_sar_height);
+                            }
+                        }
+                        if (hasaspect)
+                        {
+                            if (fabs(aspectratio-16./9.)<0.1) setAspectRatio(ASPECT_16_9);
+                            else if (fabs(aspectratio-4./3.)<0.1) setAspectRatio(ASPECT_4_3);
+                        }
+                    }
+
+                }
+
+            }
+           
+            if (vid_seeking)
+            {
+                vid_seeking = 0;
+                video_pts_seek = video_pts;
+                Log::getInstance()->log("Demuxer", Log::DEBUG,
+                    "Entering audio sync: Video PTS = %llu", video_pts);
+                Log::getInstance()->log("Demuxer", Log::DEBUG,
+                    "Entering audio sync: Audio PTS = %llu", audio_pts);
+            }
+            return;
+        } 
     }
-  }
 }
 
 UINT Demuxer::stripAudio(UCHAR* buf, UINT len)
@@ -572,10 +859,11 @@ UINT Demuxer::stripAudio(UCHAR* buf, UINT len)
   return write_pos;
 }
 
-bool Demuxer::scanForVideo(UCHAR* buf, UINT len)
+bool Demuxer::scanForVideo(UCHAR* buf, UINT len, bool &ish264)
 {
   UINT pos = 3;
   UINT pattern;
+  ish264=false;
   if (len < 4) return false;
   pattern = (buf[0] << 16) | (buf[1] << 8) | (buf[2]);
   while (pos < len)
index 54cd1b36b5ecdc30acd023ccf1168363798096d9..c0acf8559b7f351bd2158059d2d9393bcad6542b 100644 (file)
--- a/demuxer.h
+++ b/demuxer.h
@@ -60,8 +60,8 @@ class PESPacket
     ULLONG getPTS() const;
     bool hasPTS() const { return (getPTS() != PTS_INVALID); }
 
-    UINT findPictureHeader() const;
-    UINT findSeqHeader() const;
+    UINT findPictureHeader(bool h264) const;
+    UINT findSeqHeader(bool h264) const;
     static const ULLONG PTS_INVALID = (1LL << 33);
   protected:
     void copyFrom(const PESPacket& packet);
@@ -81,7 +81,7 @@ class Demuxer
     static Demuxer* getInstance();
      int init(Callback* tcallback, DrainTarget* audio, DrainTarget* video,
          DrainTarget* teletext,
-         ULONG demuxMemoryV, ULONG demuxMemoryA, ULONG demuxMemoryT,
+         ULONG demuxMemoryV, ULONG demuxMemoryA, ULONG demuxMemoryT, double fps=25.,
          DVBSubtitles* tsubtitles=NULL);
     virtual void reset();
     virtual void flush();
@@ -110,6 +110,8 @@ class Demuxer
     bool* getSubtitleChannels();
     int getselAudioChannel();
     int getselSubtitleChannel();
+       bool ish264() {return h264;}
+    void seth264(bool newh264){h264=newh264;}
 
     int getHorizontalSize() { return horizontal_size; }
     int getVerticalSize() { return vertical_size; }
@@ -132,8 +134,8 @@ class Demuxer
 
     // Scan a buffer to see if video packets are present.
     // Returns true if video exists; false if not.
-    // *static function*
-    static bool scanForVideo(UCHAR* buf, UINT len);
+    // removed *static function* for h264 detection
+    static bool scanForVideo(UCHAR* buf, UINT len, bool &ish264);
 
     enum PESTYPE
     {
@@ -193,6 +195,7 @@ class Demuxer
     bool initted;
     bool vid_seeking;
     bool aud_seeking;
+       bool h264;
     int video_current, audio_current, teletext_current, subtitle_current;
 
     // Video stream information
@@ -201,6 +204,7 @@ class Demuxer
 
     int horizontal_size;
     int vertical_size;
+    int profile;
     enum AspectRatio aspect_ratio;
     int arcnt;
     int frame_rate;
@@ -211,9 +215,14 @@ class Demuxer
     ULLONG teletext_pts;
     bool isteletextdecoded;
 
+
+       unsigned int packetnum;
+
     // Constants
     static const int FrameRates[9];
 
+       double fps;
+
     bool ispre_1_3_19;
     bool avail_mpaudchan[PESTYPE_AUDMAX-PESTYPE_AUD0+1];
     bool avail_ac3audchan[PESTYPE_SUBSTREAM_AC3MAX-PESTYPE_SUBSTREAM_AC30+1];
index f3d8bae4de27e79bd33f7869338b4bc3814aece7..2c53b59c30be7fe9fab73008a34b2d5720f201c0 100644 (file)
@@ -39,7 +39,7 @@ class PacketBuffer {
       newStream();
     }
     //just handle the data (do not deal with headers)
-    int putInternal(UCHAR* buf,int len);
+    int putInternal(UCHAR* buf,int len,unsigned int &packetnum);
     void reset(){
       partPacket=0;
       bytesWritten=0;
@@ -111,6 +111,7 @@ DemuxerAudio::DemuxerAudio(int p_vID, int p_aID)
   buffer=new PacketBuffer(&audiostream,streamtype);
 //  buffer=new PacketBuffer(&teststream,streamtype);
   globalBytesWritten=0;
+  packetnum=0;
   id3=NULL;
   info=NULL;
        vbr=NULL;
@@ -135,6 +136,7 @@ void DemuxerAudio::reset() {
   buffer->newStream();
   tmpFill=0;
   readHeaders=0;
+  packetnum=0;
   outOfSync=0;
   globalBytesWritten=0;
   if (id3) delete id3;
@@ -840,7 +842,7 @@ bool PacketBuffer::doSkip() {
 }
        
 // just handle the real stream without dealing with the header
-int PacketBuffer::putInternal(UCHAR * wbuf, int len)
+int PacketBuffer::putInternal(UCHAR * wbuf, int len,unsigned int &packetnum)
 {
    /* Important, the type passed to stream must be a mediapacket type as defined in 
        Draintarget.h and not the device setting of the mvp, so we have to translate it here,
@@ -860,7 +862,7 @@ int PacketBuffer::putInternal(UCHAR * wbuf, int len)
                if (doSkip()) return 0;//NoSkip on Windows
 #endif
     //we are still full - so try to write
-    int sent=audio->put(store+bytesWritten,framelen-bytesWritten,/*streamtype*/mptype);
+    int sent=audio->put(store+bytesWritten,framelen-bytesWritten,/*streamtype*/mptype,packetnum);packetnum++;
     //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written %d bytes to stream (still full) pp=%d, framelen=%d, written=%d",sent,partPacket,framelen, bytesWritten );
     if (sent < (framelen - bytesWritten)) {
       //packet still not written
@@ -880,7 +882,7 @@ int PacketBuffer::putInternal(UCHAR * wbuf, int len)
 #ifndef WIN32 //No Skip on Windows
                if (doSkip()) return bytesConsumed;
 #endif
-    int sent=audio->put(store,framelen,mptype);
+    int sent=audio->put(store,framelen,mptype,packetnum);packetnum++;
     bytesWritten+=sent;
     //log->log("DemuxerAudio::PacketBuffer",Log::DEBUG,"written %d bytes to stream",sent );
     if (bytesWritten < framelen) {
@@ -935,7 +937,7 @@ int DemuxerAudio::put(UCHAR* wbuf, int len)
   while (bytesConsumed < len ) {
     if (buffer->bufferFull()) {
       //if this is the first part of the loop, try to write to the stream
-      if (bytesConsumed == 0) buffer->putInternal(wbuf,0);
+      if (bytesConsumed == 0) buffer->putInternal(wbuf,0,packetnum);
       //if the buffer is full, no need to continue
       if (buffer->bufferFull()) break;
     }
@@ -990,7 +992,7 @@ int DemuxerAudio::put(UCHAR* wbuf, int len)
 #ifndef WIN32        
         //hmm - we assume that he low level driver is more intelligent
         //and give him the data "as is"
-        int written=buffer->putInternal(wbuf,garbageBytes);
+        int written=buffer->putInternal(wbuf,garbageBytes,packetnum);
         globalBytesWritten+=written;
         bytesConsumed+=written;
         if (written != garbageBytes || hdr == NULL ) {
@@ -1017,7 +1019,7 @@ int DemuxerAudio::put(UCHAR* wbuf, int len)
       inSync=true;
     }
     //now we are surely within a packet
-    int written=buffer->putInternal(wbuf,len-bytesConsumed);
+    int written=buffer->putInternal(wbuf,len-bytesConsumed,packetnum);
     //update the status
     globalBytesWritten+=written;
     wbuf+=written;
index 6a3f985301552e38873f67b9db932257feb078bd..4bbb86828ee3e23159cee1ad7fe374880f9f8c5f 100644 (file)
@@ -168,6 +168,8 @@ class DemuxerAudio : public Demuxer
                mpegInfo *info;
                vbrInfo *vbr;
 
+               unsigned int packetnum;
+
 
 };
 
index 777a96c4e599ce921eb230e5489a6637752bc53f..813d49b0c38a50eb2bf4c66bd9590bdf2845b75a 100644 (file)
@@ -252,12 +252,12 @@ void DemuxerMedia::parseVDRPacketDetails()
     packetNumber++;
   }
 
-  if (frameCounting && packet.findPictureHeader() &&
+  if (frameCounting && packet.findPictureHeader(h264) &&
       packet.getPacketType() >= PESTYPE_VID0 &&
       packet.getPacketType() <= PESTYPE_VIDMAX)
   {
     ULLONG pts=packet.getPTS();
-    if (packet.findSeqHeader() > 1 && pts != PESPacket::PTS_INVALID)
+    if (packet.findSeqHeader(h264) > 1 && pts != PESPacket::PTS_INVALID)
     {
       if (firstPTS == 0) firstPTS=pts;
       currentPTS=pts;
@@ -266,7 +266,7 @@ void DemuxerMedia::parseVDRPacketDetails()
   }
   if (packet.getPacketType() >= PESTYPE_VID0 &&
       packet.getPacketType() <= PESTYPE_VIDMAX &&
-      packet.findSeqHeader()) {
+      packet.findSeqHeader(h264)) {
     //check video size
     if (horizontal_size != last_horizontal_size ||
         vertical_size != last_vertical_size) {
index e2f8b57adc78a0bd7f82d5b71c15c9136cfedd52..330e7ad687126900c2b968d2b5cf17994d77ba88 100644 (file)
@@ -385,15 +385,18 @@ int DemuxerTS::processTS(UCHAR* buf)
        //     Log::getInstance()->log("ProcessTS", Log::DEBUG, "FOUNDPID is %x", foundpid);
                 switch (streamtype)
                 {
-                 //   case 0x1B: //MPEG 4 for future use
+                case 0x1B: //MPEG 4 for future use
                 case 1:
                 case 2: { //video
                     if (foundpid != getVID())  
                         setVID(foundpid);
                     new_channelinfo.type=VDR::VIDEO;
+                                       new_channelinfo.vstreamtype=streamtype;
                     new_channelinfo.vpid=foundpid;
+                                       if (streamtype==0x1b) h264=true;
+                                       else h264=false;
 
-       //           Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set video PID to %x", foundpid);
+                //  Log::getInstance()->log("ProcessTS", Log::DEBUG, "Set video PID to %x", foundpid);
                         }break;
                 case 3:
                 case 4: { //audio
@@ -643,11 +646,11 @@ ULONG DemuxerTS::getFrameNumFromPTS(ULLONG pts)
   if (difference == (1LL<<33))
     return 0; // We cannot make sense of the pts
   else
-    return ref_frame + difference * Video::getInstance()->getFPS() / 90000;
+    return ref_frame + difference * fps / 90000;
 }
 
 
-void DemuxerTS::parseTSPacketDetails(PESPacket packet) // Only important stuff for paket counting reminas
+void DemuxerTS::parseTSPacketDetails(PESPacket &packet) // Only important stuff for paket counting reminas
 {
     parsePacketDetails(packet);
     if (packetCounting && packet.getPacketType() >= PESTYPE_AUD0 &&
@@ -656,12 +659,12 @@ void DemuxerTS::parseTSPacketDetails(PESPacket packet) // Only important stuff f
         packetNumber++;
     }
 
-  if (frameCounting && packet.findPictureHeader() &&
+  if (frameCounting && packet.findPictureHeader(h264) &&
       packet.getPacketType() >= PESTYPE_VID0 &&
       packet.getPacketType() <= PESTYPE_VIDMAX)
   {
     ULONG frame_num = (frameNumber)++;
-    if (packet.findSeqHeader() > 1 && packet.hasPTS())
+    if ((h264 || packet.findSeqHeader(h264) > 1) && packet.hasPTS())
     {
       PTSMapEntry me;
       pts_map_mutex.Lock();
@@ -676,8 +679,8 @@ void DemuxerTS::parseTSPacketDetails(PESPacket packet) // Only important stuff f
       me = pts_map.front();
       pts_map_mutex.Unlock();
 
-      UINT fps = Video::getInstance()->getFPS();
-      ULLONG pts_expected = me.pts + 90000*(frame_num - me.frame) / fps;
+      //UINT fps = Video::getInstance()->getFPS();
+      ULLONG pts_expected = me.pts + 90000*((int)(((double)(frame_num - me.frame)) / fps));
       while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33);
 
       if (PTSDistance(pts_expected, packet.getPTS()) > PTS_JUMP_MARGIN) // PTS jump!
@@ -693,7 +696,7 @@ void DemuxerTS::parseTSPacketDetails(PESPacket packet) // Only important stuff f
 }
 
 
-bool DemuxerTS::scanForVideo(UCHAR* buf, UINT len)
+bool DemuxerTS::scanForVideo(UCHAR* buf, UINT len, bool &ish264)
 {
     int pmtpidy=0;
 
@@ -718,12 +721,13 @@ bool DemuxerTS::scanForVideo(UCHAR* buf, UINT len)
               int pmtpid = (*(curbuf+11)<< 8) | *(curbuf+12);
               if ((pmtpid >> 13) != 0x07) 
               {
-                  Log::getInstance()->log("findPTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
+                  Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMTPID=%02x %02x TRAILING 111 not set but %x", *(curbuf+11),*(curbuf+12), (pmtpid >> 13));
               } 
               else 
               {
                   pmtpid = pmtpid & 0x1FFF; //clear upper 3 bits
                   pmtpidy = pmtpid;
+                                 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "PMT pid%02x",pmtpid );
               }
           
           } else if (pid == pmtpidy) { //PMT
@@ -739,24 +743,34 @@ bool DemuxerTS::scanForVideo(UCHAR* buf, UINT len)
                   p += 2; //skip ES length
                   if ((foundpid >> 13) != 0x07)
                   {
-                      Log::getInstance()->log("findPTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
+                      Log::getInstance()->log("DemuxerTS", Log::DEBUG, "FOUNDPID=%02x %02x TRAILING 111 not set but %x", *(buf+p),*(buf+p+1), (foundpid >> 13));
                   }
                   else 
                   {
                       foundpid = foundpid & 0x1FFF; //clear upper 3 bits
                    //   int pos=0; UNUSED?
+                                         Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Pid found %02x type %02x",foundpid ,streamtype);
                       if (streamtype==1 || streamtype ==2) {
+                                                 ish264=false;
+                                                 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found Mpeg2 Video");
                           return true;
                       }
+                                         if (streamtype==0x1b) {
+                                                 ish264=true;
+                                                 Log::getInstance()->log("DemuxerTS", Log::DEBUG, "Found h264 Video");
+                                                 return true;
+                                         }
                   }
                   p += eslength; //skip es descriptor
               }
+                         ish264=false;
               return false;
           } 
       }
       len-=TS_SIZE;
       buf+=TS_SIZE;
   }
+  ish264=false;
   return false;
 }
 
@@ -804,7 +818,7 @@ UINT DemuxerTS::stripAudio(UCHAR* buf, UINT len) //it has to be adapted
                     memcpy(buf+writepos,destpaket.getData(),destpaket.getSize());
                     writepos+=destpaket.getSize();
                     destpaket.truncate();
-                    destpaket.write((UCHAR*)"\200\000\000", 3);
+                                       destpaket.write((UCHAR*)"\200\000\000", 3);
                     destpaket.write(buf+readpos,towrite);
 
                 }
index b65c29ed0e096d66b0f2674bd56d00be3e8f819d..4d58840369a00859aaa05e928373d12eaf3f1e29 100644 (file)
@@ -53,7 +53,7 @@ class DemuxerTS : public Demuxer
     ULONG getFrameNumFromPTS(ULLONG pts);
     ULONG getPacketNum();
     UINT stripAudio(UCHAR* buf, UINT len);
-    static bool scanForVideo(UCHAR* buf, UINT len);
+    static bool scanForVideo(UCHAR* buf, UINT len, bool &ish264);
     Channel getChannelInfo() {return channelinfo;};
 
 
@@ -85,7 +85,7 @@ class DemuxerTS : public Demuxer
     typedef std::deque<PTSMapEntry> PTSMap;
     PTSMap pts_map;
     Mutex pts_map_mutex;
-    void parseTSPacketDetails(PESPacket packet);
+    void parseTSPacketDetails(PESPacket &packet);
    
 
 };
index 3ac8818b699e816355df735b419514b2dbf66f2c..abcb921928de4e859cf67dc346bd311ffeb5601a 100644 (file)
@@ -294,7 +294,7 @@ ULONG DemuxerVDR::getFrameNumFromPTS(ULLONG pts)
   if (difference == (1LL<<33))
     return 0; // We cannot make sense of the pts
   else
-    return ref_frame + difference * Video::getInstance()->getFPS() / 90000;
+    return ref_frame + (ULONG)((double) (difference / 90000) *fps);
 }
 
 void DemuxerVDR::dealWithSubtitlePacket()
@@ -366,12 +366,12 @@ void DemuxerVDR::parseVDRPacketDetails()
     packetNumber++;
   }
 
-  if (frameCounting && packet.findPictureHeader() &&
+  if (frameCounting && packet.findPictureHeader(h264) &&
       packet.getPacketType() >= PESTYPE_VID0 &&
       packet.getPacketType() <= PESTYPE_VIDMAX)
   {
     ULONG frame_num = (frameNumber)++;
-    if (packet.findSeqHeader() > 1 && packet.hasPTS())
+    if (packet.findSeqHeader(h264) > 1 && packet.hasPTS())
     {
       PTSMapEntry me;
       pts_map_mutex.Lock();
@@ -387,8 +387,8 @@ Log::getInstance()->log("Demuxer", Log::DEBUG, "+* PTS INIT *+ %llu %u", me.pts,
       me = pts_map.front();
       pts_map_mutex.Unlock();
 
-      UINT fps = Video::getInstance()->getFPS();
-      ULLONG pts_expected = me.pts + 90000*(frame_num - me.frame) / fps;
+//      UINT fps = Video::getInstance()->getFPS();
+      ULLONG pts_expected = me.pts + 90000*((ULONG)((double)(frame_num - me.frame)) / fps);
       while (pts_expected > (1LL<<33)) pts_expected -= (1LL<<33);
 
       if (PTSDistance(pts_expected, packet.getPTS()) > PTS_JUMP_MARGIN) // PTS jump!
index 4c73612eefc292458e1df6a4acc464856c291165..e40bcd0d6ea915c005b617850ac2194c8d9bb34d 100644 (file)
 #include "defines.h"
 #include <list>
 
-#define MPTYPE_VIDEO 0x00
+#define MPTYPE_VIDEO_MPEG2 0x00
 #define MPTYPE_MPEG_AUDIO 0x01
 #define MPTYPE_AC3 0x02
 #define MPTYPE_AC3_PRE13 0x03 //old vdr recording compatmode
 #define MPTYPE_MPEG_AUDIO_LAYER3 0x04 //for media mp3 playback
 #define MPTYPE_TELETEXT 0x05 //for EBU VBI teletext
+#define MPTYPE_VIDEO_H264 0x06
+
+
 
 struct MediaPacket
 {
@@ -38,9 +41,10 @@ struct MediaPacket
   // The fields below are not needed by the MVP
   UCHAR type;
   ULLONG pts;
+  ULLONG dts;
   bool synched;
+  int index;
 #ifdef WIN32
-  ULLONG recording_byte_pos; //position in recording
   long long presentation_time;/* in 100 ns units*/
   bool disconti;
 #endif
@@ -91,7 +95,9 @@ class DrainTarget
     // (inclusive) from the list before the next call.
     // DeliverMediaSample must also set *samplepos equal to the number of bytes
     // processed from packet X (usually zero).
-    virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)=0;
+       // It is allowed, that the draintarget modifies the part of the buffer, which belongs 
+       // to the mediapackets it is processing.
+    virtual UINT DeliverMediaSample(UCHAR* buffer, UINT *samplepos)=0;
 };
 
 #endif
index ae2760daec2945dcc2a0011db6e611620bab41e6..f40573059bae868edfbd34db39ab275d15b08323 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2004-2005 Chris Tallon
+    Copyright 2004-2005 Chris Tallon, Marten Richter
 
     This file is part of VOMP.
 
     along with VOMP; if not, write to the Free Software
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
+
+#define INITGUID
+
 #include "osdwin.h"
 #include "dsallocator.h"
 
+#include <math.h>
+
+#include <mfidl.h>
+#include <Mfapi.h>
+#include <mferror.h>
+
+typedef HRESULT (__stdcall *FCT_MFCreateVideoSampleFromSurface)(IUnknown* pUnkSurface, IMFSample** ppSample);
+
+extern FCT_MFCreateVideoSampleFromSurface ptrMFCreateVideoSampleFromSurface;
+
 
 DsAllocator::DsAllocator() {
-       surfallocnotify=NULL;
-       refcount=1;
-       
+    surfallocnotify=NULL;
+    refcount=1;
+    inevrmode=false;
+    mftransform=NULL;
+    mediasink=NULL;
+    mfclock=NULL;
+    mfmediatype=NULL;
+    endofstream=false;
+    ResetSyncOffsets();
+
 
 
 }
 
 DsAllocator::~DsAllocator() {
-       CleanupSurfaces();
+    ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
+    ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_off);
+    CleanupSurfaces();
 
 }
 
 void DsAllocator::CleanupSurfaces() {
-       for (int i=0;i<surfaces.size();i++) {
-               if (surfaces[i]!=NULL) surfaces[i]->Release();
-               surfaces[i]=NULL;
-       }
+    Lock();
+    while(fullevrsamples.size()>0)
+    {
+        IMFSample *sample=fullevrsamples.front();
+        fullevrsamples.pop();
+        sample->Release();
+    }
+    while(emptyevrsamples.size()>0)
+    {
+        IMFSample *sample=emptyevrsamples.front();
+        emptyevrsamples.pop();
+        sample->Release();
+    }
+
+    for (int i=0;i<surfaces.size();i++) {
+        if (surfaces[i]!=NULL) surfaces[i]->Release();
+        surfaces[i]=NULL;
+    }
+    Unlock();
 }
 
 HRESULT STDMETHODCALLTYPE DsAllocator::InitializeDevice(DWORD_PTR userid,VMR9AllocationInfo* allocinf,DWORD*numbuf){
-       if (!surfallocnotify) return S_FALSE;
-       Lock();
-       CleanupSurfaces();
+    if (!surfallocnotify) return S_FALSE;
 
-       surfaces.resize(*numbuf);
-       HRESULT hres= surfallocnotify->AllocateSurfaceHelper(allocinf,numbuf,&surfaces.at(0));
-       Unlock();
-       return hres;
+    CleanupSurfaces();
+    Lock();
+    surfaces.resize(*numbuf);
+    HRESULT hres= surfallocnotify->AllocateSurfaceHelper(allocinf,numbuf,&surfaces.at(0));
+    vheight=allocinf->dwHeight;
+    vwidth=allocinf->dwWidth;
+    Unlock();
+    /* char buffer[1024];
+    sprintf(buffer,"%d * %d",allocinf->dwWidth,allocinf->dwHeight);
+    MessageBox(0,"hi",buffer,0);*/
+    return hres;
 }
 
 void DsAllocator::LostDevice(IDirect3DDevice9 *d3ddev, IDirect3D9* d3d) {
-       if (!surfallocnotify) return ;
-       Lock();
-       CleanupSurfaces();
-//     d3ddev=((OsdWin*)Osd::getInstance())->getD3dDev();
-       HMONITOR hmon=d3d->GetAdapterMonitor(D3DADAPTER_DEFAULT);
-       surfallocnotify->ChangeD3DDevice(d3ddev,hmon);
-       Unlock();
+    if (!surfallocnotify) return ;
+    CleanupSurfaces();
+    Lock();
+    // d3ddev=((OsdWin*)Osd::getInstance())->getD3dDev();
+    HMONITOR hmon=d3d->GetAdapterMonitor(D3DADAPTER_DEFAULT);
+    surfallocnotify->ChangeD3DDevice(d3ddev,hmon);
+    Unlock();
 
 }
 
 HRESULT STDMETHODCALLTYPE DsAllocator::TerminateDevice(DWORD_PTR userid){
-       Lock();
-       CleanupSurfaces();
-       Unlock();
-       return S_OK; //Do nothing
+    CleanupSurfaces();
+
+    return S_OK; //Do nothing
 }
 HRESULT STDMETHODCALLTYPE DsAllocator::GetSurface(DWORD_PTR userid,DWORD surfindex,DWORD surfflags, IDirect3DSurface9** surf)
 {
-       if (surfindex>=surfaces.size()) return E_FAIL;
-       if (surf==NULL) return E_POINTER;
+    if (surfindex>=surfaces.size()) return E_FAIL;
+    if (surf==NULL) return E_POINTER;
 
-       Lock();
-       surfaces[surfindex]->AddRef();
-       *surf=surfaces[surfindex];
-       Unlock();
-       return S_OK;
+    Lock();
+    surfaces[surfindex]->AddRef();
+    *surf=surfaces[surfindex];
+    Unlock();
+    return S_OK;
 }
 HRESULT STDMETHODCALLTYPE DsAllocator::AdviseNotify(IVMRSurfaceAllocatorNotify9* allnoty){
-       Lock();
-       surfallocnotify=allnoty;
-       IDirect3DDevice9 *d3ddev;
-       //OK lets set the direct3d object from the osd
-       d3ddev=((OsdWin*)Osd::getInstance())->getD3dDev();
-       HMONITOR hmon=((OsdWin*)Osd::getInstance())->getD3d()->GetAdapterMonitor(D3DADAPTER_DEFAULT);
-       HRESULT hres=surfallocnotify->SetD3DDevice(d3ddev,hmon);
-       Unlock();
-       return hres;
+    Lock();
+    surfallocnotify=allnoty;
+    IDirect3DDevice9 *d3ddev;
+    //OK lets set the direct3d object from the osd
+    d3ddev=((OsdWin*)Osd::getInstance())->getD3dDev();
+    HMONITOR hmon=((OsdWin*)Osd::getInstance())->getD3d()->GetAdapterMonitor(D3DADAPTER_DEFAULT);
+    HRESULT hres=surfallocnotify->SetD3DDevice(d3ddev,hmon);
+    Unlock();
+    return hres;
 }
 
 
 HRESULT STDMETHODCALLTYPE DsAllocator::StartPresenting(DWORD_PTR userid){
-       ((OsdWin*)Osd::getInstance())->setExternalDriving(this);
-       return S_OK;
+    //MessageBox(0,"drive me","drive me",0);
+    ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
+    return S_OK;
 }
+
 HRESULT STDMETHODCALLTYPE DsAllocator::StopPresenting(DWORD_PTR userid){
-       ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL);
-       return S_OK;
+    ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,0,0);
+    return S_OK;
 }
 
 HRESULT STDMETHODCALLTYPE DsAllocator::PresentImage(DWORD_PTR userid,VMR9PresentationInfo* presinf){
-       ((OsdWin*)Osd::getInstance())->RenderDS(presinf->lpSurf); //render and return
-       return S_OK;
+    ((OsdWin*)Osd::getInstance())->RenderDS(presinf->lpSurf); //render and return
+    return S_OK;
 
 }
 
 HRESULT STDMETHODCALLTYPE DsAllocator::QueryInterface(REFIID refiid,void ** obj){
-       if (obj==NULL) return E_POINTER;
+    if (obj==NULL) return E_POINTER;
 
-       if (refiid==IID_IVMRSurfaceAllocator9) {
-                *obj=static_cast<IVMRSurfaceAllocator9*>(this);
-                AddRef();
-                return S_OK;
-       } else if (refiid==IID_IVMRImagePresenter9) {
-               *obj=static_cast<IVMRImagePresenter9*>(this);
-               AddRef();
-               return S_OK;
-       }
-       return E_NOINTERFACE;
+    if (refiid==IID_IVMRSurfaceAllocator9) {
+        *obj=static_cast<IVMRSurfaceAllocator9*>(this);
+        AddRef();
+        return S_OK;
+    } else if (refiid==IID_IVMRImagePresenter9) {
+        *obj=static_cast<IVMRImagePresenter9*>(this);
+        AddRef();
+        return S_OK;
+    } else if (refiid==IID_IMFVideoDeviceID) {
+        *obj=static_cast<IMFVideoDeviceID*> (this);
+        AddRef();
+        return S_OK;
+    } else if (refiid==IID_IMFTopologyServiceLookupClient ) {
+        *obj=static_cast<IMFTopologyServiceLookupClient*> (this);
+        AddRef();
+        return S_OK;
+    } else if (refiid==IID_IQualProp ) {
+        *obj=static_cast<IQualProp*> (this);
+        AddRef();
+        return S_OK;
+    }  else if (refiid==IID_IMFGetService) {
+        *obj=static_cast<IMFGetService*> (this);
+        AddRef();
+        return S_OK;
+    } else if (refiid==IID_IDirect3DDeviceManager9) {
+        IDirect3DDeviceManager9 *d3dman=((OsdWin*)Osd::getInstance())->getD3dMan();
+        if (d3dman){
+            return d3dman->QueryInterface(refiid,obj);
+        }
+        else
+        {
+            return E_NOINTERFACE;
+        }
+    }
+    return E_NOINTERFACE;
 }
 
+
+
 ULONG STDMETHODCALLTYPE  DsAllocator::AddRef(){
-       return InterlockedIncrement(&refcount);
+    return InterlockedIncrement(&refcount);
 }
 
 ULONG STDMETHODCALLTYPE DsAllocator::Release(){
-       ULONG ref=0;
-       ref=InterlockedDecrement(&refcount);
-       if (ref==NULL) {
-               delete this; //Commit suicide
-       }
-       return ref;
+    ULONG ref=0;
+    ref=InterlockedDecrement(&refcount);
+    if (ref==NULL) {
+        delete this; //Commit suicide
+    }
+    return ref;
+}
+
+HRESULT STDMETHODCALLTYPE  DsAllocator::GetDeviceID(IID *pDid)
+{
+    if (pDid==NULL)
+        return E_POINTER;
+
+    *pDid=__uuidof(IDirect3DDevice9);
+    return S_OK;
 }
 
+HRESULT STDMETHODCALLTYPE DsAllocator::InitServicePointers(IMFTopologyServiceLookup *plooky)
+{
+    if (!plooky) return E_POINTER;
+    Lock();
+    inevrmode=true;
+    /* get all interfaces we need*/
+
+    DWORD dwobjcts=1;
+    plooky->LookupService(MF_SERVICE_LOOKUP_GLOBAL,0,MR_VIDEO_MIXER_SERVICE,
+        __uuidof(IMFTransform),(void**)&mftransform, &dwobjcts);
+    plooky->LookupService(MF_SERVICE_LOOKUP_GLOBAL,0,MR_VIDEO_RENDER_SERVICE,
+        __uuidof(IMediaEventSink),(void**)&mediasink, &dwobjcts);
+    plooky->LookupService(MF_SERVICE_LOOKUP_GLOBAL, 0, MR_VIDEO_RENDER_SERVICE,
+        __uuidof(IMFClock),(void**)&mfclock,&dwobjcts);
+
+
+    Unlock();
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::ReleaseServicePointers()
+{
+    Lock();
+    inevrmode=false;
+    /* TODO Set RenderState , sample type etc.*/
+
+    ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,0,0);
+
+    if (mftransform) mftransform->Release();
+    mftransform=NULL;
+
+    if (mediasink) mediasink->Release();
+    mediasink=NULL;
+
+    if (mfclock) mfclock->Release();
+    mfclock=NULL;
+    if (mfmediatype) mfmediatype->Release();
+    mfmediatype=NULL;
+
+    Unlock();
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::GetService(const GUID &guid,const IID &iid,LPVOID *obj)
+{
+    if (guid==MR_VIDEO_ACCELERATION_SERVICE)
+    {
+        IDirect3DDeviceManager9 *d3dman=((OsdWin*)Osd::getInstance())->getD3dMan();
+        if (d3dman)
+        {
+            return d3dman->QueryInterface (__uuidof(IDirect3DDeviceManager9), (void**) obj);
+        }
+        else
+        {
+            return E_NOINTERFACE;
+        }
+
+    } 
+    else if (guid==MR_VIDEO_RENDER_SERVICE)
+    {
+        return QueryInterface(iid,obj);
+    } 
+    else
+    {
+        return E_NOINTERFACE;
+    }
+}
+
+
+void DsAllocator::GetEVRSamples()
+{
+    MFCLOCK_STATE clockstate;
+    if (mfclock) mfclock->GetState(0,&clockstate);
+    //MessageBox(0,"get samples","samples",0);
+    Lock();
+    if (mfclock && clockstate==MFCLOCK_STATE_STOPPED && fullevrsamples.size()>0)
+    {
+        Unlock();
+        return;
+    }
+
+    while (emptyevrsamples.size()>0)
+    {
+
+        MFT_OUTPUT_DATA_BUFFER outdatabuffer;
+        ZeroMemory(&outdatabuffer,sizeof(outdatabuffer));
+        outdatabuffer.pSample=emptyevrsamples.front();
+        DWORD status=0;
+        LONGLONG starttime,endtime;
+        MFTIME dummy;
+        starttime=0;
+        endtime=0;
+
+        if (mfclock) 
+        {
+            mfclock->GetCorrelatedTime(0,&starttime,&dummy);
+            if (lastdelframe) CalcJitter( (starttime-lastdelframe)/10000);
+            lastdelframe=starttime;
+        }
+
+        HRESULT hres=mftransform->ProcessOutput(0,1,&outdatabuffer,&status);
+        
+
+        if (hres==MF_E_TRANSFORM_NEED_MORE_INPUT)
+        {
+            if (endofstream)
+            {
+
+                endofstream=false;
+                mediasink->Notify(EC_COMPLETE,(LONG_PTR) S_OK,0);
+
+            }
+            break;
+        }
+        else if (hres==MF_E_TRANSFORM_STREAM_CHANGE)
+        {
+            if (mfmediatype) mfmediatype->Release();
+            mfmediatype=NULL;
+            break;
+        } 
+        else if (hres==MF_E_TRANSFORM_TYPE_NOT_SET)
+        {
+            if (mfmediatype) mfmediatype->Release();
+            mfmediatype=NULL;
+            RenegotiateEVRMediaType();
+            break;
+        } 
+        else if (hres==S_OK)
+        {
+            LONGLONG prestime=0;
+            hres=outdatabuffer.pSample->GetSampleTime(&prestime);
+            //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Got EVR Sample %lld",prestime);
+            IMFSample *temp=emptyevrsamples.front();
+            emptyevrsamples.pop();
+
+
+
+            fullevrsamples.push(temp);
+            //Log::getInstance()->log("DsAllocator", Log::DEBUG , "got evr sample %d, %d",
+            // emptyevrsamples.size(),fullevrsamples.size());
+            if (mfclock){
+                mfclock->GetCorrelatedTime(0,&endtime,&dummy);
+                LONGLONG delay=endtime-starttime;
+                mediasink->Notify( EC_PROCESSING_LATENCY,(LONG_PTR)&delay,0);
+            }
+        } else break;
+
+    }
+    Unlock();
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::ProcessMessage(MFVP_MESSAGE_TYPE mess,ULONG_PTR mess_para)
+{
+    switch (mess) {
+        case MFVP_MESSAGE_FLUSH:{
+            //Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_FLUSH received");
+            FlushEVRSamples(); }break;
+        case MFVP_MESSAGE_INVALIDATEMEDIATYPE: {
+            Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_INVALIDATEMEDIATYPE received");
+            if (mfmediatype) mfmediatype->Release();
+            mfmediatype=NULL;
+            RenegotiateEVRMediaType();}break;
+        case MFVP_MESSAGE_PROCESSINPUTNOTIFY: {
+            //Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_PROCESSINPUTNOTIFY received");
+            GetEVRSamples(); } break;
+        case MFVP_MESSAGE_BEGINSTREAMING:{
+            //Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_BEGINSTREAMING received");
+            ResetSyncOffsets();
+            ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
+            ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);
+            endofstream=false;
+                                         }break;
+        case MFVP_MESSAGE_ENDSTREAMING: {
+            //Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_ENDSTREAMING received");
+            ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_off);
+            ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
+            //FlushEVRSamples();
+            //if (mfmediatype) mfmediatype->Release();
+            //mfmediatype=NULL;
+                                        } break;
+        case MFVP_MESSAGE_ENDOFSTREAM: {
+            Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_ENDOFSTREAM received");
+            MessageBox(0,"endofstream","endofstream",0);
+            endofstream=true;
+                                       } break;
+        case MFVP_MESSAGE_STEP: {
+            Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_STEP received");
+            ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
+            ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_pause);
+            MessageBox(0,"steppy","steppy",0);
+            FlushEVRSamples(/*LOWORD(mess_para)*/); //Message sending, has to be done after compeletion
+                                }; break;
+        case MFVP_MESSAGE_CANCELSTEP: {
+            Log::getInstance()->log("DsAllocator", Log::DEBUG , "EVR Message MFVP_MESSAGE_CANCELSTEP received");
+            //???
+                                      }; break;
+        default:
+            MessageBox(0,"unhandled","unhandled",0);
+    };
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::OnClockStart(MFTIME systime,LONGLONG startoffset)
+{
+    //((OsdWin*)Osd::getInstance())->SetEVRTimes(systime,startoffset);
+    timeBeginPeriod(1);
+
+    if (PRESENTATION_CURRENT_POSITION!=startoffset) FlushEVRSamples();
+    ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
+    ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);
+    GetEVRSamples();
+
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::OnClockStop(MFTIME systime)
+{
+    timeEndPeriod(1);
+
+    ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_off);
+    ((OsdWin*)Osd::getInstance())->setExternalDriving(NULL,vwidth,vheight);
+    FlushEVRSamples();
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::OnClockPause(MFTIME systime)
+{
+    timeEndPeriod(1);
+    ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
+    ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_pause);
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::OnClockRestart(MFTIME systime)
+{
+    ((OsdWin*)Osd::getInstance())->setExternalDriving(this,vwidth,vheight);
+    ((OsdWin*)Osd::getInstance())->SetEVRStatus(OsdWin::EVR_pres_started);
+
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::OnClockSetRate(MFTIME systime,float rate)
+{
+    timeBeginPeriod(1);
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::GetCurrentMediaType(IMFVideoMediaType **mtype)
+{ MessageBox(0,"mediatype","mediatype",0);
+if (mtype==NULL) return E_POINTER;
+Lock();
+if (mfmediatype==NULL)
+{
+    Unlock();
+    *mtype=NULL;
+    return MF_E_NOT_INITIALIZED;
+}
+HRESULT hres=mfmediatype->QueryInterface(IID_IMFVideoMediaType,(void**)mtype);
+Unlock();
+return hres;
+}
+
+void DsAllocator::RenegotiateEVRMediaType()
+{
+    if (!mftransform) {
+        Log::getInstance()->log("DsAllocator", Log::DEBUG , "Cannot renegotiate without transform!");
+        return ;
+    }
+    bool gotcha=false;
+    DWORD index=0;
+
 
+    while (!gotcha) {
+        IMFMediaType *mixtype=NULL;
+        HRESULT hres;
+        if (hres=mftransform->GetOutputAvailableType(0,index++,&mixtype)!=S_OK)
+        {
+            Log::getInstance()->log("DsAllocator", Log::DEBUG , "No more types availiable from EVR %d !",hres);
+            break;
+        }
+
+        //Type check
+        BOOL compressed;
+        mixtype->IsCompressedFormat(&compressed); 
+        if (compressed)
+        {
+            mixtype->Release();
+            continue;
+        }
+        UINT32 helper;
+        mixtype->GetUINT32(MF_MT_INTERLACE_MODE,&helper);
+        if (helper!=MFVideoInterlace_Progressive) {
+            Log::getInstance()->log("DsAllocator", Log::DEBUG , "Skip media type interlaced!");
+            mixtype->Release();
+            continue;
+        }
+        GUID temp;
+        mixtype->GetMajorType(&temp);
+        if (temp!=MEDIATYPE_Video) {
+            Log::getInstance()->log("DsAllocator", Log::DEBUG , "Skip media type no video!");
+            mixtype->Release();
+            continue;
+        }
+        if(mftransform->SetOutputType(0,mixtype,MFT_SET_TYPE_TEST_ONLY)!=S_OK) 
+        {
+            Log::getInstance()->log("DsAllocator", Log::DEBUG , "Skip media type test failed!");
+            mixtype->Release();
+            continue;
+        }
+        //Type is ok!
+
+        gotcha=true;
+
+        Lock();
+        if (mfmediatype) mfmediatype->Release();
+        mfmediatype=NULL;
+
+        mfmediatype=mixtype;
+        AllocateEVRSurfaces();
+        Unlock();
+
+        hres=mftransform->SetOutputType(0,mixtype,0);
+
+
+
+        if (hres!=S_OK) 
+        {
+            Lock();
+            if (mfmediatype) mfmediatype->Release();
+            mfmediatype=NULL;
+            gotcha=false;
+
+            Unlock();
+        }
+
+
+        Log::getInstance()->log("DsAllocator", Log::DEBUG , "Output type set! %d",hres);
+    }
+    if (!gotcha) Log::getInstance()->log("DsAllocator", Log::DEBUG , "No suitable output type!");
+
+
+
+}
+
+void DsAllocator::AllocateEVRSurfaces()
+{
+
+    LARGE_INTEGER temp64;
+    mfmediatype->GetUINT64(MF_MT_FRAME_SIZE, (UINT64*)&temp64);
+    vwidth=temp64.HighPart;
+    vheight=temp64.LowPart;
+    GUID subtype;
+    subtype.Data1=D3DFMT_X8R8G8B8;
+    mfmediatype->GetGUID(MF_MT_SUBTYPE,&subtype);
+    D3DFORMAT format=(D3DFORMAT)subtype.Data1;
+    Log::getInstance()->log("DsAllocator", Log::DEBUG , "Surfaceformat is %d, width %d, height %d",format,vwidth,vheight);
+    format=D3DFMT_X8R8G8B8;
+
+    CleanupSurfaces();
+    Lock();
+    OsdWin* osdwin=(OsdWin*)Osd::getInstance();
+    LPDIRECT3DDEVICE9 d3ddev=osdwin->getD3dDev();
+    osdwin->BeginPainting();
+    surfaces.resize(10);
+    for (int i=0;i<10;i++)
+    {
+        HRESULT hres;
+        LPDIRECT3DSURFACE9 surfy;
+
+        hres=d3ddev->CreateRenderTarget(vwidth,vheight,format,
+            D3DMULTISAMPLE_NONE,0,FALSE,&surfy,NULL);
+        if (hres==S_OK)
+        {
+            surfaces[i]=surfy;
+        }
+        else
+        {
+            surfaces[i]=NULL;
+        }
+    }
+    osdwin->EndPainting();
+
+
+
+    for (int i=0;i<surfaces.size();i++) {
+        if (surfaces[i]!=NULL) 
+        {
+            IMFSample *sample=NULL;
+            ptrMFCreateVideoSampleFromSurface(surfaces[i],&sample);
+            if (sample) emptyevrsamples.push(sample);
+        }
+    }
+    Unlock();
+
+}
+
+void DsAllocator::FlushEVRSamples()
+{
+    Lock();
+    while(fullevrsamples.size()>0)
+    {
+        IMFSample *sample=fullevrsamples.front();
+        fullevrsamples.pop();
+        emptyevrsamples.push(sample);
+    }
+    Unlock();
+}
+#define FAC 1
+
+void DsAllocator::GetNextSurface(LPDIRECT3DSURFACE9* surf,DWORD *waittime)
+{
+    
+    *surf=NULL;
+    *waittime=10;
+    if (fullevrsamples.size()==0) GetEVRSamples();
+    Lock();
+    //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Enter Get Next Surface");
+    
+    while (fullevrsamples.size()>0) 
+    {
+        //MessageBox(0,"Got a sample","got a sample",0);
+        IMFSample *sample=fullevrsamples.front();
+        LONGLONG prestime=0;
+        MFTIME   systime=0;
+        LONGLONG currenttime=0;
+
+        HRESULT hres=sample->GetSampleTime(&prestime);
+        if (hres==S_OK) 
+        {
+            if (mfclock) mfclock->GetCorrelatedTime(0,&currenttime,&systime);
+        }
+        LONGLONG delta=prestime-currenttime; 
+
+       
+
+        if (delta<-10000*20 && false) { //SkipIT
+            LONGLONG latency=-delta;
+            //mediasink->Notify(EC_SAMPLE_LATENCY,(LONG_PTR) &latency,0);
+            LARGE_INTEGER helper;
+            helper.QuadPart=-delta;
+            Log::getInstance()->log("DsAllocator", Log::DEBUG , "skip 1 frame %d %d prestime %lld",helper.LowPart,helper.HighPart,prestime);
+            CalcSyncOffsets(delta/10000LL);
+            // emptyevrsamples.size(),fullevrsamples.size());
+            fullevrsamples.pop();
+            emptyevrsamples.push(sample);
+            framesdropped++;
+            continue;
+        }
+
+        if (delta<10000*20 || !mfclock )
+        {
+            *waittime=0;
+            IMFMediaBuffer* buffy=NULL;
+            //MessageBox(0,"its showtime","showtimw",0);
+            CalcSyncOffsets(delta/10000LL);
+            framesdrawn++;
+            hres=sample->GetBufferByIndex(0,&buffy);
+            //LARGE_INTEGER helper;
+            //helper.QuadPart=-delta;
+            //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Paint 1 frame %d %d, frames  %d prestime %lld",
+             //   helper.LowPart,helper.HighPart,fullevrsamples.size(),prestime);
+            if (hres!=S_OK) { //SkipIT
+                fullevrsamples.pop();
+                emptyevrsamples.push(sample);
+                continue;
+            }
+            IMFGetService* service;
+            hres=buffy->QueryInterface(IID_IMFGetService,(void**)&service);
+            buffy->Release();
+            if (hres!=S_OK) { //SkipIT
+                fullevrsamples.pop();
+                emptyevrsamples.push(sample);
+                continue;
+            }
+            LPDIRECT3DSURFACE9 tempsurf;
+            hres=service->GetService(MR_BUFFER_SERVICE,IID_IDirect3DSurface9 ,(void**) &tempsurf);
+            service->Release();
+            if (hres!=S_OK) { //SkipIT
+                fullevrsamples.pop();
+                emptyevrsamples.push(sample);
+                continue;
+            }
+            *surf=tempsurf;
+            break;
+        } else {
+            *waittime=delta/10000-10;
+            *surf=NULL;
+            break;
+        }       
+    }
+
+    Unlock();
+
+}
+
+void DsAllocator::DiscardSurfaceandgetWait(DWORD *waittime)
+{
+    //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Discard surface and get Wait");
+    GetEVRSamples();
+    //Log::getInstance()->log("DsAllocator", Log::DEBUG , "Discard surface and get Wait2");
+    Lock();
+    if (fullevrsamples.size()==0) {
+        *waittime=0;
+        Unlock();
+        return;
+    }
+    IMFSample *sample=fullevrsamples.front();
+    fullevrsamples.pop();
+    emptyevrsamples.push(sample);
+    *waittime=0;
+
+    while (fullevrsamples.size()>0) 
+    {
+
+        IMFSample *sample=fullevrsamples.front();
+        LONGLONG prestime=0;
+        MFTIME   systime=0;
+        LONGLONG currenttime=0;
+
+        HRESULT hres=sample->GetSampleTime(&prestime);
+        if (hres==S_OK) 
+        {
+            mfclock->GetCorrelatedTime(0,&currenttime,&systime);
+        }
+        LONGLONG delta=prestime-currenttime;
+
+
+        if (delta<-10000*20 ) { //SkipIT
+             LONGLONG latency=-delta;
+           // mediasink->Notify(EC_SAMPLE_LATENCY,(LONG_PTR) &latency,0);
+            //LARGE_INTEGER helper;
+            //helper.QuadPart=-delta;
+            //Log::getInstance()->log("DsAllocator", Log::DEBUG , "skip 1 frame %d %d time %lld",helper.LowPart,helper.HighPart,prestime);
+            CalcSyncOffsets(delta/10000LL);
+            // emptyevrsamples.size(),fullevrsamples.size());
+            fullevrsamples.pop();
+            emptyevrsamples.push(sample);
+            framesdropped++;
+            continue;
+        }
+
+        *waittime=min(delta/10000/2-10,1); 
+
+        break;
+    }
+    Unlock();
+
+}
+void DsAllocator::ResetSyncOffsets()
+{
+    for (int i=0;i<n_stats;i++)
+    {
+        sync_offset[i]=0;
+        jitter_offset[i]=0;
+    }
+    framesdrawn=0;
+    lastdelframe=0;
+    framesdropped=0;
+    avg_sync_offset=0;
+    dev_sync_offset=0;
+    jitter=0;
+    sync_pos=0;
+    jitter_pos=0;
+    avgfps=0;
+}
+
+void DsAllocator::CalcSyncOffsets(int sync)
+{
+    sync_offset[sync_pos]=sync;
+    sync_pos=(sync_pos +1)%n_stats;
+
+    double mean_value=0;
+    for (int i=0;i<n_stats;i++)
+    {
+        mean_value+=sync_offset[i];
+    }
+    mean_value/=(double) n_stats;
+    double std_dev=0;
+    for (int i=0;i<n_stats;i++)
+    {
+        double temp_dev=(mean_value-(double)sync_offset[i]);
+        std_dev+=temp_dev*temp_dev;
+    }
+    std_dev/=(double)n_stats;
+    avg_sync_offset=mean_value;
+    dev_sync_offset=sqrt(std_dev);
+}
+
+void DsAllocator::CalcJitter(int jitter)
+{
+    jitter_offset[jitter_pos]=jitter;
+    jitter_pos=(jitter_pos +1)%n_stats;
+    
+
+    double mean_value=0;
+    for (int i=0;i<n_stats;i++)
+    {
+        mean_value+=jitter_offset[i];
+    }
+    mean_value/=(double) n_stats;
+    avgfps=1000./mean_value*100.;
+    double std_dev=0;
+    for (int i=0;i<n_stats;i++)
+    {
+        double temp_dev=(mean_value-(double)jitter_offset[i]);
+        std_dev+=temp_dev*temp_dev;
+    }
+    std_dev/=(double)n_stats;
+    jitter=sqrt(std_dev);
+}
+
+
+HRESULT STDMETHODCALLTYPE DsAllocator::get_FramesDrawn(int *val)
+{
+    *val=framesdrawn;
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::get_AvgFrameRate(int *val)
+{
+    *val=avgfps;
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::get_Jitter(int *val)
+{
+    *val=jitter;
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::get_AvgSyncOffset(int *val)
+{
+    *val=avg_sync_offset;
+    return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DsAllocator::get_DevSyncOffset(int *val)
+{
+    *val=dev_sync_offset;
+    return S_OK;
+}
+HRESULT STDMETHODCALLTYPE DsAllocator::get_FramesDroppedInRenderer(int *val)
+{
+    *val=framesdropped;
+    return S_OK;
+}
index d7077c8857d7ba7718866c7e037bcadfcf2c6328..5134c2cdf7764aa20f9663a441224125d6e807c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright 2004-2005 Chris Tallon
+    Copyright 2004-2005 Chris Tallon, Marten Richter
 
     This file is part of VOMP.
 
 #ifndef DSALLOCATOR_H
 #define DSALLOCATOR_H
 
+#include <queue>
 #include <vector>
+
+
 using namespace std;
+
 #include <winsock2.h>
 
 #include <d3d9.h>
 #include <dshow.h> 
 #include <vmr9.h>
+#include <evr.h>
 #include "mutex.h"
 
 
+//The Allocator and Presenter for VMR9 is also a Presnter for EVR
 
-
-class DsAllocator: public IVMRSurfaceAllocator9, IVMRImagePresenter9,Mutex {
+class DsAllocator: public IVMRSurfaceAllocator9, IVMRImagePresenter9, Mutex,IMFVideoDeviceID, 
+       IMFTopologyServiceLookupClient,public IMFVideoPresenter,IMFGetService, IQualProp {
 public:
        DsAllocator();
        virtual ~DsAllocator();
@@ -54,14 +60,74 @@ public:
 
     void LostDevice(IDirect3DDevice9 *d3ddev, IDirect3D9* d3d);
 
+       /* EVR members */
+       virtual HRESULT STDMETHODCALLTYPE GetDeviceID(IID *pDid);
+
+       virtual HRESULT STDMETHODCALLTYPE InitServicePointers(IMFTopologyServiceLookup *plooky);
+       virtual HRESULT STDMETHODCALLTYPE ReleaseServicePointers();
+
+       virtual HRESULT STDMETHODCALLTYPE ProcessMessage(MFVP_MESSAGE_TYPE mess,ULONG_PTR mess_para);
+
+       virtual HRESULT STDMETHODCALLTYPE OnClockStart(MFTIME systime,LONGLONG startoffset);
+       virtual HRESULT STDMETHODCALLTYPE OnClockStop(MFTIME systime);
+       virtual HRESULT STDMETHODCALLTYPE OnClockPause(MFTIME systime);
+       virtual HRESULT STDMETHODCALLTYPE OnClockRestart(MFTIME systime);
+       virtual HRESULT STDMETHODCALLTYPE OnClockSetRate(MFTIME systime,float rate);
+       virtual HRESULT STDMETHODCALLTYPE GetCurrentMediaType(IMFVideoMediaType **mtype);
+
+       virtual HRESULT STDMETHODCALLTYPE GetService(const GUID &guid,const IID &iid,LPVOID *obj);
+
+    virtual HRESULT STDMETHODCALLTYPE get_FramesDrawn(int *val);
+    virtual HRESULT STDMETHODCALLTYPE get_AvgFrameRate(int *val);
+    virtual HRESULT STDMETHODCALLTYPE get_Jitter(int *val);
+    virtual HRESULT STDMETHODCALLTYPE get_AvgSyncOffset(int *val);
+    virtual HRESULT STDMETHODCALLTYPE get_DevSyncOffset(int *val);
+    virtual HRESULT STDMETHODCALLTYPE get_FramesDroppedInRenderer(int *val);
+
+       void GetNextSurface(LPDIRECT3DSURFACE9 *surf,DWORD *waittime);
+       void DiscardSurfaceandgetWait(DWORD *waittime);
+
+
 protected:
+
+       void RenegotiateEVRMediaType();
+       void AllocateEVRSurfaces();
+       void FlushEVRSamples();
+       void GetEVRSamples();
+
+       void ResetSyncOffsets();
+       void CalcSyncOffsets(int sync);
+       void CalcJitter(int jitter);
        
-       vector<IDirect3DSurface9* > surfaces;
+       vector<IDirect3DSurface9*> surfaces;
+       queue<IMFSample*> emptyevrsamples;
+       queue<IMFSample*> fullevrsamples;
        //CCritSec objCritSec;
        IVMRSurfaceAllocatorNotify9* surfallocnotify;
        void CleanupSurfaces();
        LONG refcount;
-
+       DWORD vheight;
+       DWORD vwidth;
+       bool inevrmode;
+       bool endofstream;
+
+       IMFTransform* mftransform;
+       IMediaEventSink* mediasink;
+       IMFClock* mfclock;
+       IMFMediaType *mfmediatype;
+
+       static const int n_stats=126;
+       int sync_offset[n_stats];
+       int jitter_offset[n_stats];
+       unsigned int sync_pos;
+       unsigned int jitter_pos;
+       int framesdrawn;
+       int framesdropped;
+       int avg_sync_offset;
+       int dev_sync_offset;
+       int jitter;
+    int avgfps;
+    LONGLONG lastdelframe;
 
 };
 
@@ -71,4 +137,5 @@ protected:
 
 
 
+
 #endif
index 543e59cd188a7e39c8717ac6fb89402ae0be3b3e..6e94b698630029bb37ab862c7c5dce884a2f0041 100644 (file)
@@ -454,4 +454,16 @@ bool DsSourceFilter::changeAType(int type,IMediaSample* ms)
     return true;
 }
 
+bool DsSourceFilter::changeVType(int type,IMediaSample* ms,void * details)
+{
+    if (!videopin ) {
+        return false;
+    }
+    videopin->SetPinMode(type,details);
+    videopin->SetMsToMt(ms);
+    
+
+    return true;
+}
+
 
index ad1ef0e0e8b7a0e3ec4c5c54d3c3d0e09847df7c..ab34c9d238efcda906478b7cd3b18ecdf81ef112 100644 (file)
 #include "mutex.h"
 #include "dssourcepin.h"
 
+struct mptype_video_detail{ //here should be all information added the Video Draintarget needs for rendering, to be extended in the future
+    UINT width;
+    UINT height;
+};
 
 [uuid("EB87AB22-7A95-49c3-8CCE-2F6D61A87009")]
 class DsSourceFilter: public IBaseFilter {
@@ -68,6 +72,7 @@ public:
 
     bool supportsAc3();
     bool changeAType(int type,IMediaSample* ms);
+    bool changeVType(int type,IMediaSample* ms, void *details);
 
 
 protected:
index d5aa13ac3404b555be5c662261d2ab3ce4f2b9b2..d9f665d5545b21b487d60c3eb46678992f314913 100644 (file)
@@ -135,6 +135,8 @@ void CopyMType(AM_MEDIA_TYPE* dest,const AM_MEDIA_TYPE*source) {
   if (source->pbFormat!=NULL) {
     dest->pbFormat=(BYTE*)CoTaskMemAlloc(dest->cbFormat);
     memcpy(dest->pbFormat,source->pbFormat,dest->cbFormat);
+  } else {
+         dest->pbFormat=NULL;
   }
 }
 void ReleaseMType(AM_MEDIA_TYPE* free) {
@@ -151,6 +153,10 @@ DsSourcePin::DsSourcePin(DsSourceFilter *pFilter,
   connected=NULL;
   connectedinput=NULL;
   allocator=NULL;
+
+  v_width=640;
+  v_height=480;
+  
   if (isaudiopin)
   {
       pinmode=MPTYPE_MPEG_AUDIO;
@@ -158,7 +164,8 @@ DsSourcePin::DsSourcePin(DsSourceFilter *pFilter,
   }
   else
   {
-      pinmode=MPTYPE_VIDEO;
+       
+       pinmode=MPTYPE_VIDEO_MPEG2;
   }
 
 }
@@ -428,7 +435,9 @@ HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE
 }
 
 HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){
-  if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0);
+       if (allocator!=NULL) {
+               return allocator->GetBuffer(ms,NULL,NULL,0);
+       }
   else return E_NOINTERFACE;
 }
 
@@ -749,11 +758,47 @@ HRESULT DsSourcePin::GetMediaTypeMpegVideo(int iPosition, AM_MEDIA_TYPE *pmt)
       hdr.dwProfile = AM_MPEG2Profile_Main;
       hdr.dwLevel = AM_MPEG2Level_Main;
       hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader);
-      hdr.hdr.bmiHeader.biWidth = 720;
-      hdr.hdr.bmiHeader.biHeight = 568;
+      hdr.hdr.bmiHeader.biWidth = v_width;
+      hdr.hdr.bmiHeader.biHeight = v_height;
          /* Vista compat*/
-         hdr.hdr.dwPictAspectRatioX=1; 
-         hdr.hdr.dwPictAspectRatioY=1;
+      hdr.hdr.dwPictAspectRatioX=1;//v_sar_width; 
+         hdr.hdr.dwPictAspectRatioY=1;//v_sar_height;
+         /* Vista compat*/
+      pmt->cbFormat = sizeof(hdr);
+      pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(hdr));
+      memcpy(pmt->pbFormat,&hdr,sizeof(hdr));
+  } else {
+      hr=VFW_S_NO_MORE_ITEMS;
+  }
+
+  return hr;
+}
+
+HRESULT DsSourcePin::GetMediaTypeH264Video(int iPosition, AM_MEDIA_TYPE *pmt)
+{
+  HRESULT hr;
+  if (iPosition == 0)
+  {
+      ZeroMemory(pmt,sizeof(*pmt));
+      pmt->lSampleSize = 1;
+      pmt->bFixedSizeSamples = TRUE;
+      pmt->majortype = MEDIATYPE_Video;
+      hr = S_OK;
+      pmt->subtype =MEDIASUBTYPE_H264;// MAKEFOURCC('H','2','6','4');
+      pmt->formattype = FORMAT_VideoInfo2 ;
+               
+
+      VIDEOINFOHEADER2 hdr;
+      ZeroMemory(&hdr,sizeof(hdr));
+      //hdr.dwProfile = AM_MPEG2Profile_Main;
+      //hdr.dwLevel = AM_MPEG2Level_Main;
+      hdr.bmiHeader.biSize = sizeof(hdr.bmiHeader);
+      hdr.bmiHeader.biWidth = v_width;//720;
+      hdr.bmiHeader.biHeight = v_height;//568;
+         hdr.bmiHeader.biCompression = MAKEFOURCC('H','2','6','4');
+         /* Vista compat*/
+         hdr.dwPictAspectRatioX=1;//v_sar_width; 
+         hdr.dwPictAspectRatioY=1;//v_sar_height;
          /* Vista compat*/
       pmt->cbFormat = sizeof(hdr);
       pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(hdr));
@@ -776,19 +821,30 @@ HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt)
   case MPTYPE_MPEG_AUDIO:
          return GetMediaTypeMpegAudio(iPosition,pmt);
   break;
-  case MPTYPE_VIDEO:
+  case MPTYPE_VIDEO_MPEG2:
       return GetMediaTypeMpegVideo(iPosition,pmt);
   break;
+  case MPTYPE_VIDEO_H264:
+      return GetMediaTypeH264Video(iPosition,pmt);
+  break;
   case MPTYPE_AC3_PRE13:
   case MPTYPE_AC3:
       return GetMediaTypeAc3(iPosition,pmt);
   };
 }
 
-void DsSourcePin::SetPinMode(int mode) {
+void DsSourcePin::SetPinMode(int mode, void* details) {
     pinmode=mode;
     AM_MEDIA_TYPE amtype;
     ReleaseMType(&medtype);
+    if (details)
+    {
+        if (!isaudiopin)
+        {
+            v_width=((mptype_video_detail*) details)->width;
+            v_height=((mptype_video_detail*) details)->height;
+        }
+    }
     GetMediaType(0,&medtype);
 }
 
@@ -841,7 +897,7 @@ HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt)
           res = S_FALSE ;
       }
       break;
-  case MPTYPE_VIDEO:
+  case MPTYPE_VIDEO_MPEG2:
        if (pmt->majortype==MEDIATYPE_Video &&
            pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) 
        {
@@ -852,6 +908,17 @@ HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt)
             res = S_FALSE ;
         }
         break;
+  case MPTYPE_VIDEO_H264:
+       if (pmt->majortype==MEDIATYPE_Video &&
+           pmt-> subtype==MEDIASUBTYPE_H264) 
+       {
+               res = S_OK ;
+        } 
+       else 
+       {
+            res = S_FALSE ;
+        }
+        break;
   case MPTYPE_AC3_PRE13:
   case MPTYPE_AC3:
       subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3);
@@ -875,18 +942,18 @@ HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *al
     if (pa==NULL)return E_POINTER;
     if (all_pp==NULL) return E_POINTER;
   if (isaudiopin) {
-    if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
+    if (all_pp->cBuffers*all_pp->cbBuffer < 100*16*1024)
     {
       //all_pp->cBuffers = 300;//old
-      all_pp->cBuffers = 50;
-      all_pp->cbBuffer = 64*1024;
+      all_pp->cBuffers = 100;
+      all_pp->cbBuffer = 16*1024;
     }
   } else {
-    if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)
+    if (all_pp->cBuffers*all_pp->cbBuffer < 50*64*1024*5)
     {
       //all_pp->cBuffers = 300;//old
-      all_pp->cBuffers = 300;
-      all_pp->cbBuffer = 64*1024;
+      all_pp->cBuffers = 50;
+      all_pp->cbBuffer = 64*1024*5;
     }
   }
 
index 670712f3dbe35bfd59816950a6c270a7eff7072f..740aa40ce98885698560c9ba468e630fe60ade17 100644 (file)
@@ -42,7 +42,7 @@ public:
   HRESULT deliver(IMediaSample * ms);
   void SetMsToMt(IMediaSample *ms);
   bool supportsAc3();
-  void SetPinMode(int mode);
+  void SetPinMode(int mode, void* details=NULL);
 
   virtual  HRESULT DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp);
 
@@ -80,6 +80,7 @@ protected:
   HRESULT GetMediaTypeMp3Audio(int iPosition, AM_MEDIA_TYPE *pmt);
   HRESULT GetMediaTypeAc3(int iPosition, AM_MEDIA_TYPE *pmt);
   HRESULT GetMediaTypeMpegVideo(int iPosition, AM_MEDIA_TYPE *pmt);
+  HRESULT GetMediaTypeH264Video(int iPosition, AM_MEDIA_TYPE *pmt);
 
     int pinmode;
   bool isaudiopin;
@@ -89,9 +90,8 @@ protected:
   AM_MEDIA_TYPE medtype;
   IMemAllocator* allocator;
 
-
-
-
+  int v_width;
+  int v_height;
 };
 
 
index 90421641c9e8490f95e3040e19fe1a521b056116..eba132a5831abc9e0e10116c8db7a8a3e756329f 100644 (file)
@@ -19,6 +19,8 @@
 */
 
 #include "eventdispatcher.h"
+#include <stdlib.h>
+
 
 EventDispatcher::EventDispatcher()
 {
index 77212b439f40930b9cae364a21362ca38d9bc031..3b0a5ee805b52b9c148bfef538fc3867cea6dbce 100644 (file)
@@ -58,9 +58,10 @@ class EDReceiver //(implementation in eventdispatcher.cc)
 
 class EventDispatcher
 {
-  typedef list<EDReceiver*> EDRL;
 
   public:
+    typedef list<EDReceiver*> EDRL;
+
     EventDispatcher();
     virtual ~EventDispatcher() {};
 
diff --git a/main.cc b/main.cc
index fee721473632bc5bebd0ff8ec36b25a19ac42ca1..3d4ad20f644417edca80065404f94aacabdf6328 100644 (file)
--- a/main.cc
+++ b/main.cc
 #include "boxstack.h"
 #include "command.h"
 
+#ifndef _MIPS_ARCH
+
 #include "mtdmvp.h"
 #include "remotemvp.h"
 #include "ledmvp.h"
 #include "osdmvp.h"
 #include "audiomvp.h"
 #include "videomvp.h"
+
+#else
+
+#include "mtdnmt.h"
+#include "remotelirc.h"
+#include "lednmt.h"
+#include "osddirectfb.h"
+#include "audionmt.h"
+#include "videonmt.h"
+
+#endif
+
+
 #include "wol.h"
 #include "vsleeptimer.h"
+
+
 #ifndef WIN32
 void sighandler(int signalReceived);
 #endif
 
 void shutdown(int code);
 
+#ifndef _MIPS_ARCH
+
 extern "C"
 {
   int ticonfig_main(int, char**);
 }
 
+#endif
+
 // Global variables --------------------------------------------------------------------------------------------------
 Log* logger;
 Remote* remote;
@@ -72,7 +93,9 @@ Sleeptimer* sleeptimer;
 #ifndef WIN32
 int main(int argc, char** argv)
 {
+#ifndef _MIPS_ARCH
   if (strstr(argv[0], "ticonfig")) return ticonfig_main(argc, argv);
+#endif
 
   bool daemonize = true;
   bool debugEnabled = false;
@@ -105,16 +128,26 @@ int main(int argc, char** argv)
   }
            
   // Init global vars ------------------------------------------------------------------------------------------------
-
   logger     = new Log();
   timers     = new Timers();
   vdr        = new VDR();
+#ifndef _MIPS_ARCH
   mtd        = new MtdMVP();
   remote     = new RemoteMVP();
   led        = new LedMVP();
   osd        = new OsdMVP();
   audio      = new AudioMVP();
   video      = new VideoMVP();
+#else
+  mtd        = new MtdNMT();
+  remote     = new RemoteLirc();
+  led        = new LedNMT();
+  osd        = new OsdDirectFB();
+  audio      = new AudioNMT();
+  video      = new VideoNMT();
+#endif
+
+
   boxstack   = new BoxStack();
   command    = new Command();
   wol        = new Wol();
@@ -205,8 +238,11 @@ int main(int argc, char** argv)
 
   // Init modules ----------------------------------------------------------------------------------------------------
   int success;
-
+#ifndef _MIPS_ARCH
   success = remote->init("/dev/rawir");
+#else
+  success = remote->init("/dev/lircd");
+#endif
   if (success)
   {
     logger->log("Core", Log::INFO, "Remote module initialised");
@@ -216,8 +252,11 @@ int main(int argc, char** argv)
     logger->log("Core", Log::EMERG, "Remote module failed to initialise");
     shutdown(1);
   }
-
+#ifndef _MIPS_ARCH
   success = led->init(((RemoteMVP*)remote)->getDevice());
+#else
+  success = led->init(-1);
+#endif  
   if (success)
   {
     logger->log("Core", Log::INFO, "LED module initialised");
index d01f1aeadb3da35657dd8ca640cebc326e1a6df1..e0c11917551831d8f22b0d33b2d21c347b60eeef 100644 (file)
@@ -29,6 +29,7 @@
 #include "media.h"
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <stdlib.h>
 
 #include <iostream>
 #include "log.h"
diff --git a/osd.h b/osd.h
index 558db622d06a13ed95fd9b9f8e5045f0091ad97b..bd1eba58d10fea44b9f163b2f7fb5a30674cd87a 100644 (file)
--- a/osd.h
+++ b/osd.h
@@ -34,6 +34,7 @@ class Osd
 
     virtual int init(void* device)=0;
     virtual int shutdown()=0;
+    bool isInitted() {return initted;};
 
     virtual int getFD()=0;
 
index aff35f73bced274e154a6ba8f17bdfbe5d02bdb1..e433a8630cd1eb1c5a9d8c58f1d3767d6aa23f41 100644 (file)
--- a/osdwin.cc
+++ b/osdwin.cc
 #include "message.h"
 #include "command.h"
 
+#define  BACKBUFFER_WIDTH 1280
+#define  BACKBUFFER_HEIGHT 720
+
+
+
+typedef HRESULT (__stdcall *FCT_DXVA2CreateDirect3DDeviceManager9)(UINT* pResetToken, IDirect3DDeviceManager9** ppDeviceManager);
+typedef HRESULT (__stdcall *FCT_MFCreateVideoSampleFromSurface)(IUnknown* pUnkSurface, IMFSample** ppSample);
+
+FCT_DXVA2CreateDirect3DDeviceManager9 ptrDXVA2CreateDirect3DDeviceManager9=NULL;
+FCT_MFCreateVideoSampleFromSurface ptrMFCreateVideoSampleFromSurface=NULL;
 
 //This is stuff for rendering the OSD
 
@@ -36,20 +46,55 @@ OsdWin::OsdWin()
 {
   d3d=NULL;
   d3ddevice=NULL;
-  d3dvb=NULL;
   d3drtsurf=NULL;
+  swappy=NULL;
+  swapsurf=NULL;
+  evrstate=EVR_pres_off;
+  window=NULL;
+
   external_driving=false;
   dsallocator=NULL;
   filter_type=D3DTEXF_FORCE_DWORD;
   lastrendertime=timeGetTime();
   event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL);
   d3dmutex = CreateMutex(NULL,FALSE,NULL);
+  /*EVR stuff*/
+  dxvadevicehandle=NULL;
+  evrsupported=true;
+  HMODULE hlib=NULL;
+  hlib=LoadLibrary("dxva2.dll");
+  if (!hlib) {
+         evrsupported=false;
+         return;
+  }
+  ptrDXVA2CreateDirect3DDeviceManager9=(FCT_DXVA2CreateDirect3DDeviceManager9)GetProcAddress(hlib, "DXVA2CreateDirect3DDeviceManager9");
+  if (!ptrDXVA2CreateDirect3DDeviceManager9){
+         evrsupported=false;
+         return;
+  }
+
+  hlib=LoadLibrary("evr.dll");
+  if (!hlib) {
+         evrsupported=false;
+         return;
+  }
+  ptrMFCreateVideoSampleFromSurface = (FCT_MFCreateVideoSampleFromSurface)GetProcAddress(hlib,"MFCreateVideoSampleFromSurface");
+  if (!ptrMFCreateVideoSampleFromSurface){
+         evrsupported=false;
+         return;
+  }
   
 }
 
 OsdWin::~OsdWin()
 {
-  if (initted) shutdown();
+
+  if (initted) 
+  {
+         threadStop();
+               shutdown();
+  }
   CloseHandle(event);
   CloseHandle(d3dmutex);
 }
@@ -64,6 +109,7 @@ int OsdWin::init(void* device)
 {
   if (initted) return 0;
    Video* video = Video::getInstance();
+   window=*((HWND*)device);
   //First Create Direct 3D Object
   d3d=Direct3DCreate9(D3D_SDK_VERSION);
   if (!d3d) 
@@ -74,8 +120,8 @@ int OsdWin::init(void* device)
   // then create the Device
   D3DPRESENT_PARAMETERS d3dparas;
   ZeroMemory(&d3dparas,sizeof(d3dparas));
-  d3dparas.BackBufferWidth=video->getScreenWidth();
-  d3dparas.BackBufferHeight=video->getScreenHeight();
+  d3dparas.BackBufferWidth=BACKBUFFER_WIDTH;
+  d3dparas.BackBufferHeight=BACKBUFFER_HEIGHT;
   d3dparas.Windowed=TRUE;
   d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;
   if (d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,*((HWND*) device),
@@ -85,10 +131,11 @@ int OsdWin::init(void* device)
   }
   d3ddevice->GetRenderTarget(0,&d3drtsurf);
 
+  /*
   if (!InitVertexBuffer()) {
           Log::getInstance()->log("OSD", Log::WARN, "Could not create Direct3D9 vertex buf!");
                  return 0;
-  }
+  }*/
   /* We have to determine which kind of filtering is supported*/
   D3DCAPS9 caps;
   d3ddevice->GetDeviceCaps(&caps);
@@ -119,6 +166,15 @@ int OsdWin::init(void* device)
        filter_type=D3DTEXF_NONE;
    }
 
+   if (evrsupported)
+   {
+          if (ptrDXVA2CreateDirect3DDeviceManager9(&dxvatoken,&d3ddevman)!=S_OK) evrsupported=false;
+          else {
+                  d3ddevman->ResetDevice(d3ddevice,dxvatoken);
+          }
+   }
+
+
 
 
   //Now we will create the Screen
@@ -127,10 +183,36 @@ int OsdWin::init(void* device)
   screen->create(video->getScreenWidth(), video->getScreenHeight());
   screen->display();
   initted = 1; // must set this here or create surface won't work
-  
+  threadStart(); 
+
   return 1;
 }
 
+void OsdWin::LockDevice()
+{
+       if (!evrsupported) return;
+       if (!dxvadevicehandle) 
+       {
+               d3ddevman->OpenDeviceHandle(&dxvadevicehandle);
+       }
+       IDirect3DDevice9 *temp;
+       d3ddevman->LockDevice(dxvadevicehandle,&temp,TRUE);
+
+}
+
+void OsdWin::UnlockDevice()
+{
+       if (!evrsupported) return;
+       if (!initted) return;
+       d3ddevman->UnlockDevice(dxvadevicehandle,TRUE);
+       if (dxvadevicehandle) 
+       {
+               d3ddevman->CloseDeviceHandle(dxvadevicehandle);
+               dxvadevicehandle=NULL;
+       }
+
+}
+
 DWORD OsdWin::getFilterCaps()
 {
     if (!initted) return NULL;
@@ -138,9 +220,11 @@ DWORD OsdWin::getFilterCaps()
     d3ddevice->GetDeviceCaps(&caps);
     return caps.StretchRectFilterCaps;
 }
-
-int OsdWin::InitVertexBuffer() {
-  Video* video = Video::getInstance();
+       
+LPDIRECT3DVERTEXBUFFER9  OsdWin::InitVertexBuffer(DWORD width, DWORD height)
+{
+  LPDIRECT3DVERTEXBUFFER9 ret =NULL;
+  Video* video=Video::getInstance();
   FLOAT texx=((float)video->getScreenWidth())/1024.f;
   FLOAT texy=((float)video->getScreenHeight())/1024.f;
   D3DCOLOR osdcolor=D3DCOLOR_RGBA(255,255,255,255);
@@ -152,50 +236,51 @@ int OsdWin::InitVertexBuffer() {
   osdvertices[0].u=0.f;
   osdvertices[0].v=0.f;
   osdvertices[1].c=osdcolor;
-  osdvertices[1].x=((float)video->getScreenWidth())-0.5f;-0.5f;
+  osdvertices[1].x=((float)width)-0.5f;-0.5f;
   osdvertices[1].y=0.f-0.5f;
   osdvertices[1].z=0.5f;
   osdvertices[1].u=texx;
   osdvertices[1].v=0.f;
   osdvertices[1].rhw=1.f;
   osdvertices[2].c=osdcolor;
-  osdvertices[2].x=((float)video->getScreenWidth())-0.5f;
-  osdvertices[2].y=((float)video->getScreenHeight())-0.5f;
+  osdvertices[2].x=((float)width)-0.5f;
+  osdvertices[2].y=((float)height)-0.5f;
   osdvertices[2].z=0.5f;
   osdvertices[2].rhw=1.f;
   osdvertices[2].u=texx;
   osdvertices[2].v=texy;
   osdvertices[3].c=osdcolor;
   osdvertices[3].x=0.f-0.5f;
-  osdvertices[3].y=((float)video->getScreenHeight())-0.5f;
+  osdvertices[3].y=((float)height)-0.5f;
   osdvertices[3].z=0.5f;
   osdvertices[3].rhw=1.f;
   osdvertices[3].u=0.f;
   osdvertices[3].v=texy;
-  if (d3dvb) {
-         d3dvb->Release();
-         d3dvb=NULL;
-  }
+  
   if (d3ddevice->CreateVertexBuffer(4*sizeof(OSDVERTEX),0,D3DFVF_OSDVERTEX,D3DPOOL_MANAGED,
-         &d3dvb,NULL)!=D3D_OK) {
-         return 0;
+         &ret,NULL)!=D3D_OK) {
+         return NULL;
   }
   void *pvertex=NULL;
-  if (d3dvb->Lock(0,sizeof(osdvertices),&pvertex,0)!=D3D_OK) {
-         return 0;
+  if (ret->Lock(0,sizeof(osdvertices),&pvertex,0)!=D3D_OK) {
+         return NULL;
   }
   memcpy(pvertex,osdvertices,sizeof(osdvertices));
-  d3dvb->Unlock();
-  return 1;
+  ret->Unlock();
+  return ret;
 }
 
 int OsdWin::shutdown()
 {
   if (!initted) return 0;
   initted = 0;
+  evrsupported=0;
+  if (d3ddevman) d3ddevman->Release();
   d3drtsurf->Release();
   d3ddevice->Release();
   d3d->Release();
+  if (swapsurf) swapsurf->Release();
+  if (swappy) swappy->Release();
 
   return 1;
 }
@@ -205,6 +290,45 @@ void OsdWin::screenShot(char* fileName)
   screen->screenShot(fileName);
 }
 
+void OsdWin::threadMethod()
+{
+       while (true)
+       {
+               DWORD waittime=10;
+               if (initted){
+                       if (evrstate==EVR_pres_off || evrstate==EVR_pres_pause) 
+                       {
+                               Render();
+                       } else if (evrstate==EVR_pres_started)
+                       {
+                               LPDIRECT3DSURFACE9 surf;
+                               dsallocator->GetNextSurface(&surf,&waittime);
+                               if (surf==NULL)
+                               {
+                                       Render();
+                               }
+                               else
+                               {
+                                       RenderDS(surf);
+                                       surf->Release();
+                                       dsallocator->DiscardSurfaceandgetWait(&waittime);
+                               }
+                       }
+               }
+               threadCheckExit();
+               if (waittime!=0) Sleep(min(10,waittime));
+               //Sleep(1);
+       }
+}
+
+
+void OsdWin::threadPostStopCleanup()
+{
+       //Doing nothing
+       //goo;
+}
+
+
 // This function is called from the WinMain function in order to get Screen updates
 void OsdWin::Render()
 {
@@ -215,7 +339,7 @@ void OsdWin::Render()
                        InternalRendering(NULL);
                        lastrendertime=timeGetTime();
         } else {
-               Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads
+                  //Sleep(5); //Sleep for 5 ms, in order to avoid blocking the other threads
         }
        } else {
                DWORD time1=timeGetTime();
@@ -223,7 +347,7 @@ void OsdWin::Render()
                        InternalRendering(NULL);
                        lastrendertime=timeGetTime();
                } else {
-                       Sleep(5);
+                       //Sleep(5);
                
                }
                
@@ -240,27 +364,44 @@ void OsdWin::RenderDS(LPDIRECT3DSURFACE9 present){
 
 
 void OsdWin::InternalRendering(LPDIRECT3DSURFACE9 present){
-    WaitForSingleObject(d3dmutex,INFINITE);
+    BeginPainting();
     HRESULT losty=d3ddevice->TestCooperativeLevel();
     if (losty==D3DERR_DEVICELOST) {
-        Sleep(10);
+        //Sleep(10);
+               EndPainting();
         return; //Device Lost
     }
     if (losty==D3DERR_DEVICENOTRESET){
+          EndPainting();
        DoLost();
        return;
     }
        WaitForSingleObject(event,INFINITE);
        
    
-       BeginPainting();
-    d3ddevice->SetRenderTarget(0,d3drtsurf);//Stupid VMR manipulates the render target
+       
+    
+    LPDIRECT3DSURFACE9 targetsurf;
+       if (swappy)
+       {
+               targetsurf=swapsurf;
+               d3ddevice->SetRenderTarget(0,swapsurf);//Stupid VMR manipulates the render target
+       } 
+       else
+       {
+               targetsurf=d3drtsurf;
+               d3ddevice->SetRenderTarget(0,d3drtsurf);//Stupid VMR manipulates the render target
+       }
+       D3DSURFACE_DESC targetdesc;
+       targetsurf->GetDesc(&targetdesc);
+
        if (external_driving) {
                //Copy video to Backbuffer
                if (present!=NULL ) {
                        VideoWin* video =(VideoWin*) Video::getInstance();
                        /*calculating destination rect */
-                       RECT destrect={0,0,video->getScreenWidth(),video->getScreenHeight()};
+                       RECT destrect={0,0,/*video->getScreenWidth()*/ targetdesc.Width,
+                               /*video->getScreenHeight()*/targetdesc.Height};
                        UCHAR mode=video->getMode();
                        switch (mode) {
                        case Video::EIGHTH:
@@ -284,7 +425,7 @@ void OsdWin::InternalRendering(LPDIRECT3DSURFACE9 present){
                                        sourcerect.left=(surf_desc.Width-correction)/2;
                                        sourcerect.right=sourcerect.left+correction;
                        }
-                       d3ddevice->StretchRect(present,&sourcerect,d3drtsurf  ,&destrect,filter_type);
+                       d3ddevice->StretchRect(present,&sourcerect,targetsurf ,&destrect,filter_type);
 
                }
        } else {
@@ -292,9 +433,12 @@ void OsdWin::InternalRendering(LPDIRECT3DSURFACE9 present){
                //Clear Background
                if (!video->isVideoOn()) d3ddevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
        }
+       LPDIRECT3DVERTEXBUFFER9 vb=NULL;
+       vb=InitVertexBuffer(targetdesc.Width,targetdesc.Height);
+
        //Drawing the OSD
        if (d3ddevice->BeginScene()==D3D_OK) {
-               d3ddevice->SetStreamSource(0,d3dvb,0,sizeof(OSDVERTEX));
+               d3ddevice->SetStreamSource(0,vb,0,sizeof(OSDVERTEX));
                d3ddevice->SetFVF(D3DFVF_OSDVERTEX);
                d3ddevice->SetTexture(0,((SurfaceWin*)screen)->getD3dtexture());
                //d3ddevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
@@ -314,16 +458,30 @@ void OsdWin::InternalRendering(LPDIRECT3DSURFACE9 present){
                d3ddevice->EndScene();
                //Show it to the user!
         HRESULT hres;
-               if (hres=d3ddevice->Present(NULL,NULL,NULL,NULL)==D3DERR_DEVICELOST){
-                       EndPainting();
-                       if (!external_driving) DoLost();
+               if (swappy)
+               {
+                       if (hres=swappy->Present(NULL,NULL,NULL,NULL,0)==D3DERR_DEVICELOST){
+                               //EndPainting();
+                               if (!external_driving) DoLost();
+                       }
+               } 
+               else
+               {
+                       if (hres=d3ddevice->Present(NULL,NULL,NULL,NULL)==D3DERR_DEVICELOST){
+                               //EndPainting();
+                               if (!external_driving) DoLost();
+                       }
                }
-               EndPainting();
-       }
-       ReleaseMutex(d3dmutex);
-       if (!external_driving) {
-               Sleep(4);//The User can wait for 4 milliseconds to see his changes
+               
        }
+       
+       vb->Release();
+       EndPainting();
+
+       
+//     if (!external_driving) {
+//             Sleep(4);//The User can wait for 4 milliseconds to see his changes
+//     }
 }
 
 bool OsdWin::DoLost(){
@@ -337,19 +495,22 @@ bool OsdWin::DoLost(){
        ((SurfaceWin*)screen)->ReleaseSurface();
        if (d3drtsurf) d3drtsurf->Release();
     d3drtsurf=NULL;
-       if (d3dvb) d3dvb->Release();
-       d3dvb=NULL;
        D3DPRESENT_PARAMETERS d3dparas;
        ZeroMemory(&d3dparas,sizeof(d3dparas));
-       d3dparas.BackBufferWidth=video->getScreenWidth();
-       d3dparas.BackBufferHeight=video->getScreenHeight();
+       d3dparas.BackBufferWidth=BACKBUFFER_WIDTH;
+       d3dparas.BackBufferHeight=BACKBUFFER_HEIGHT;
        d3dparas.Windowed=TRUE;
        d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;
+
+       if (swapsurf) {swapsurf->Release();swapsurf=NULL;};
+       if (swappy) {swappy->Release();swappy=NULL;};
+
        if (d3ddevice->Reset(&d3dparas)!=D3D_OK){
                return false;
        }
     d3ddevice->GetRenderTarget(0,&d3drtsurf);
-       InitVertexBuffer();
+       if (d3ddevman) d3ddevman->ResetDevice(d3ddevice,dxvatoken);
+       //InitVertexBuffer();
     //Redraw Views, Chris could you add a member function to BoxStack, so that
        // I can cause it to completely redraw the Views?
        // Otherwise the OSD would be distorted after Device Lost
@@ -376,21 +537,58 @@ LPDIRECT3D9 OsdWin::getD3d() {
 
 void OsdWin::BeginPainting() {//We synchronize calls to d3d between different threads
        WaitForSingleObject(d3dmutex,INFINITE);
+       LockDevice();
 }
 
 void OsdWin::EndPainting() {
+       UnlockDevice();
        ReleaseMutex(d3dmutex);
 }
 
-void OsdWin::setExternalDriving(DsAllocator* dsall) {
+void OsdWin::setExternalDriving(DsAllocator* dsall,DWORD width, DWORD height) {
+       
+       if (swappy)
+       {
+               BeginPainting();
+               d3ddevice->StretchRect(swapsurf,NULL,d3drtsurf,NULL,filter_type);
+               LPDIRECT3DSWAPCHAIN9 temp=swappy;
+               LPDIRECT3DSURFACE9 tempsurf=swapsurf;
+               swappy=NULL;
+               swapsurf=NULL;
+               EndPainting();
+               tempsurf->Release();
+               temp->Release();
+       }
+
        if (dsall==NULL) {
                external_driving=false;
-               dsallocator=NULL;
+               dsallocator=NULL;       
                return;
        }
        WaitForSingleObject(event,INFINITE);//We will only return if we are initted
+       BeginPainting();
+
+       if (width>BACKBUFFER_WIDTH || height>BACKBUFFER_HEIGHT) 
+       {
+               D3DPRESENT_PARAMETERS d3dparas;
+               ZeroMemory(&d3dparas,sizeof(d3dparas));
+               d3dparas.BackBufferWidth=width;
+               d3dparas.BackBufferHeight=height;
+               d3dparas.Windowed=TRUE;
+               d3dparas.SwapEffect=D3DSWAPEFFECT_COPY;
+               if (d3ddevice->CreateAdditionalSwapChain(&d3dparas,&swappy)!=D3D_OK){
+                       Log::getInstance()->log("OSD", Log::WARN, "Could not create Swap Chain!");
+                       //return 0;
+               } else {
+                       swappy->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&swapsurf);
+               }
+        Log::getInstance()->log("OSD", Log::INFO, "Create Additional Swap Chain %d %d!",width,height);
+       }
+
        dsallocator=dsall;
        external_driving=true;
+       
+       EndPainting();
 }
 
 void OsdWin::Blank() {
index 756520d3d2a2ae14ebe4ebffb8532349168a563b..a470fbceffba7a39d7ac35ea912b8a21e924cc6d 100644 (file)
--- a/osdwin.h
+++ b/osdwin.h
 #include "osd.h"
 #include "defines.h"
 #include "log.h"
+#include "threadwin.h"
 #include <winsock2.h>
 #include <d3d9.h>
+#include <Dxva2api.h>
 
 struct OSDVERTEX
 {
@@ -40,7 +42,9 @@ struct OSDVERTEX
 
 class DsAllocator;
 
-class OsdWin : public Osd
+
+
+class OsdWin : public Osd, public ThreadWin
 {
   public:
     OsdWin();
@@ -53,6 +57,9 @@ class OsdWin : public Osd
 
     void screenShot(char* fileName);
 
+       void threadMethod();
+    void threadPostStopCleanup();
+
        LPDIRECT3DDEVICE9 getD3dDev() ;
        LPDIRECT3D9 getD3d() ;
        // This function is called from the WinMain function in order to get Screen updates
@@ -60,16 +67,38 @@ class OsdWin : public Osd
        void RenderDS(LPDIRECT3DSURFACE9 present);
        void BeginPainting();
        void EndPainting();
-       void setExternalDriving(DsAllocator* dsall);
+       void setExternalDriving(DsAllocator* dsall,DWORD width, DWORD height);
        void Blank();
     DWORD getFilterCaps();
     DWORD getFilterType(){return filter_type;};
     void setFilterType(D3DTEXTUREFILTERTYPE type) {filter_type=type;};
+
+
+
+       
+
+       enum EVR_state {
+               EVR_pres_off=0,
+               EVR_pres_started,
+               EVR_pres_pause
+       };
+
+       void SetEVRStatus(EVR_state new_state){evrstate=new_state;};
+       
+       IDirect3DDeviceManager9 * getD3dMan() {return d3ddevman;};
+       bool IsEvrSupported() {return evrsupported;};
+       HWND getWindow() {return window;};
+
 private:
+       void LockDevice();
+       void UnlockDevice();
+
          LPDIRECT3D9 d3d;
          LPDIRECT3DDEVICE9 d3ddevice;
-         LPDIRECT3DVERTEXBUFFER9 d3dvb;
+//       LPDIRECT3DVERTEXBUFFER9 d3dvb;
          LPDIRECT3DSURFACE9 d3drtsurf;
+         LPDIRECT3DSWAPCHAIN9 swappy;
+         LPDIRECT3DSURFACE9 swapsurf;
          DsAllocator* dsallocator;
        // This indicates, that currently a video is played, thus the osd updates are driven by the Directshow Filtersystem
        bool external_driving;
@@ -77,10 +106,17 @@ private:
        DWORD lastrendertime;
        void InternalRendering(LPDIRECT3DSURFACE9 present);
        bool DoLost();
-       int InitVertexBuffer();
+       LPDIRECT3DVERTEXBUFFER9 InitVertexBuffer(DWORD width, DWORD height);
        OSDVERTEX osdvertices[4];
        HANDLE event;
        D3DTEXTUREFILTERTYPE filter_type;
+       EVR_state evrstate;
+       bool evrsupported;
+       HWND window;
+
+       UINT dxvatoken;
+       IDirect3DDeviceManager9 *d3ddevman;
+       HANDLE  dxvadevicehandle;
 };
 
 #endif
index 359cbef2bf53716b4819c4120752926eb7437dcc..f250b355f17228c7aed9e3c32a19141f341d0005 100644 (file)
--- a/player.cc
+++ b/player.cc
@@ -58,7 +58,7 @@ Player::Player(MessageQueue* tmessageQueue, void* tmessageReceiver, OSDReceiver*
 
   videoStartup = false;
   threadBuffer = NULL;
-
   blockSize = 100000;
   startupBlockSize = 250000;
   video->turnVideoOn();
@@ -69,7 +69,7 @@ Player::~Player()
   if (initted) shutdown();
 }
 
-int Player::init(bool p_isPesRecording)
+int Player::init(bool p_isPesRecording,double framespersecond)
 {
   if (initted) return 0;
 #ifndef WIN32
@@ -78,6 +78,7 @@ int Player::init(bool p_isPesRecording)
   mutex=CreateMutex(NULL,FALSE,NULL);
 #endif
   is_pesrecording = p_isPesRecording;
+  fps=framespersecond;
   if (is_pesrecording)
     demuxer = new DemuxerVDR();
   else
@@ -89,8 +90,10 @@ int Player::init(bool p_isPesRecording)
   teletext = new TeletextDecoderVBIEBU();
   if (!teletext) return 0;
   teletext->setRecordigMode(true);
+  unsigned int demux_video_size=2097152;
+   if (video->supportsh264()) demux_video_size*=5;
  
-  if (!demuxer->init(this, audio, video,teletext, 2097152, 524288,65536, subtitles))
+  if (!demuxer->init(this, audio, video,teletext, demux_video_size,524288,65536, framespersecond, subtitles))
   {
     logger->log("Player", Log::ERR, "Demuxer failed to init");
     shutdown();
@@ -387,7 +390,7 @@ void Player::skipForward(int seconds)
   logger->log("Player", Log::DEBUG, "SKIP FORWARD %i SECONDS", seconds);
   ULONG newFrame = getCurrentFrameNum();
   if (newFrame == 0) { unLock(); return; } // Current pos from demuxer is not valid
-  newFrame += seconds * video->getFPS();
+  newFrame +=(ULONG) (((double)seconds) * fps);
   if (newFrame > lengthFrames) { switchState(S_PLAY); unLock(); }
   else switchState(S_JUMP, newFrame);
 //  unLock(); - let thread unlock this
@@ -399,7 +402,7 @@ void Player::skipBackward(int seconds)
   logger->log("Player", Log::DEBUG, "SKIP BACKWARD %i SECONDS", seconds);
   long newFrame = getCurrentFrameNum();
   if (newFrame == 0) { unLock(); return; } // Current pos from demuxer is not valid
-  newFrame -= seconds * video->getFPS();
+  newFrame -= (ULONG) (((double)seconds) * fps);
   if (newFrame < 0) newFrame = 0;
   switchState(S_JUMP, newFrame);
 //  unLock(); - let thread unlock this
@@ -654,7 +657,7 @@ void Player::switchState(UCHAR toState, ULONG jumpFrame)
         case S_PLAY: // to S_PLAY
         {
           state = S_PLAY;
-          ULONG stepback = USER_RESPONSE_TIME * video->getFPS() * ifactor / 1000;
+          ULONG stepback = (ULONG)(((double)USER_RESPONSE_TIME * ifactor) * fps / 1000.);
           if (stepback < currentFrameNumber)
             currentFrameNumber -= stepback;
           else
@@ -1081,8 +1084,11 @@ void Player::threadFeedPlay()
       else // normal
         askFor = blockSize;
     }
+    //logger->log("Player", Log::DEBUG, "Get Block in");
 
     threadBuffer = vdr->getBlock(feedPosition, askFor, &thisRead);
+    //logger->log("Player", Log::DEBUG, "Get Block out");
+
     feedPosition += thisRead;
 
     if (!vdr->isConnected())
@@ -1105,7 +1111,9 @@ void Player::threadFeedPlay()
 
     while(writeLength < thisRead)
     {
+      //logger->log("Player", Log::DEBUG, "Put in");
       thisWrite = demuxer->put(threadBuffer + writeLength, thisRead - writeLength);
+      //logger->log("Player", Log::DEBUG, "Put out");
       writeLength += thisWrite;
 
       if (!thisWrite)
@@ -1191,7 +1199,7 @@ void Player::threadFeedScan()
         // scan has got to the end of what we knew to be there before we started scanning
 
       baseFrameNumber = iframeNumber;
-      frameTimeOffset = abs((int)iframeNumber - (int)currentFrameNumber) * 1000 / (video->getFPS() * ifactor);
+      frameTimeOffset =(int) ((double)(abs((int)iframeNumber - (int)currentFrameNumber) * 1000) / (fps * (double)ifactor));
 #ifndef WIN32
       gettimeofday(&clock0, NULL);
 #else
@@ -1205,7 +1213,7 @@ void Player::threadFeedScan()
 #else
     while (clock2 != 0 && clock0 + total_msec > clock2 + frameTimeOffset);
 #endif
-//    logger->log("Player", Log::DEBUG, "XXX Got frame");
+    logger->log("Player", Log::DEBUG, "XXX Got frame");
 
     threadBuffer = vdr->getBlock(filePos, iframeLength, &amountReceived);
     
@@ -1230,7 +1238,7 @@ void Player::threadFeedScan()
     if (sleepTime < 0) sleepTime = 0;
     threadCheckExit();
     MILLISLEEP(sleepTime);
-//    logger->log("Player", Log::DEBUG, "XXX Slept for %d", sleepTime);
+   logger->log("Player", Log::DEBUG, "XXX Slept for %d", sleepTime);
 
     videoLength = demuxer->stripAudio(threadBuffer, amountReceived);
     video->displayIFrame(threadBuffer, videoLength);
@@ -1251,7 +1259,7 @@ void Player::threadFeedScan()
     total_msec = clock2 - clock0 - sleepTime;
     disp_msec = clock2 - clock1 - sleepTime;
 #endif
-//    logger->log("Player", Log::DEBUG, "XXX disp_msec = %4d total_msec = %4d", disp_msec, total_msec);
+    logger->log("Player", Log::DEBUG, "XXX disp_msec = %4d total_msec = %4d", disp_msec, total_msec);
   }
 }
 
index 135292ff5e2519096cb02c60cc6490e85b2f3d3b..af9bedf3cae4d476a9ab392d71896d988d22d324 100644 (file)
--- a/player.h
+++ b/player.h
@@ -58,7 +58,7 @@ class Player : public Thread_TYPE, public Callback
     Player(MessageQueue* messageQueue, void* messageReceiver, OSDReceiver* osdReceiver);
     virtual ~Player();
 
-    int init(bool p_isPesRecording);
+    int init(bool p_isPesRecording,double framespersec);
     int shutdown();
     void setStartFrame(ULONG frameNum);
     void setLengthBytes(ULLONG length);
@@ -157,6 +157,7 @@ class Player : public Thread_TYPE, public Callback
     bool videoStartup;
 
     bool is_pesrecording;
+       double fps;
 
 #ifndef WIN32
     pthread_mutex_t mutex;
index f08d80071400184596bd7b5627ad9ed38f24a85c..20ff359944222ae9a5d3e3ea2f85c6d261befad5 100644 (file)
@@ -50,6 +50,7 @@ PlayerLiveTV::PlayerLiveTV(MessageQueue* tmessageQueue, void* tmessageReceiver,
 
   subtitlesShowing = false;
   videoStartup = false;
+  pendingAudioPlay = false;
 
   stopNow = false;
   state = S_STOP;
@@ -72,8 +73,11 @@ int PlayerLiveTV::init()
   if (!subtitles) return 0;
 
   teletext = new TeletextDecoderVBIEBU();
+  
+  unsigned int demux_video_size=2097152;
+  if (video->supportsh264()) demux_video_size*=5;
  
-  if (!demuxer->init(this, audio, video, teletext, 2097152, 524288, 65536, subtitles))
+  if (!demuxer->init(this, audio, video, teletext, demux_video_size, 524288, 65536,25./*unimportant*/,subtitles))
   {
     logger->log("PlayerLiveTV", Log::ERR, "Demuxer failed to init");
     shutdown();
@@ -320,6 +324,17 @@ void PlayerLiveTV::chunkToDemuxer()
   /*int a = */demuxer->put((UCHAR*)s.data, s.len);
   //logger->log("PlayerLiveTV", Log::DEBUG, "put %i to demuxer", a);
   free(s.data);  
+  if (pendingAudioPlay && demuxer->getHorizontalSize()) //Horizontal Size is zero, if not parsed
+  {
+      video->sync();
+      video->play();
+      video->pause();
+      //audio->setStreamType(Audio::MPEG2_PES);
+      audio->sync();
+      audio->play();
+      audio->pause();
+      pendingAudioPlay = false;
+  }
 }
 
 void PlayerLiveTV::switchState(UCHAR newState)
@@ -336,17 +351,26 @@ void PlayerLiveTV::switchState(UCHAR newState)
         {
           video->blank();
           video->reset();
-          video->sync();
-          video->play();
-          video->pause();
+          //video->sync();
+          //video->play();
+          //video->pause();
 
           audio->stop();
           audio->unPause();
           audio->reset();
-          audio->setStreamType(Audio::MPEG2_PES);
-          audio->sync();
-          audio->play();
-          audio->pause();
+          //audio->setStreamType(Audio::MPEG2_PES);
+          //audio->sync();
+          // I make this modification, since the video/audio devices needs to know at least
+          // which kind of video is embedded inside the stream
+          // therefore the demuxer needs to feeded at least with enough data
+          // to have one video header
+          // This is crucial, if we have mixed h264/mpeg2 channels
+          // the information from channels is not enough since some directshow decoders need
+          // width and height information before startup
+          pendingAudioPlay = true;
+
+          //audio->play();
+          //audio->pause();
 
           demuxer->reset();
           demuxer->seek();
@@ -374,6 +398,7 @@ void PlayerLiveTV::switchState(UCHAR newState)
       {
         case S_PREBUFFERING:
         {
+          pendingAudioPlay=false;
           vfeed.release();
           state = newState;
           return;
@@ -390,17 +415,18 @@ void PlayerLiveTV::switchState(UCHAR newState)
                            
           video->blank();
           video->reset();
-          video->sync();
-          video->play();
-          video->pause();
+          //video->sync();
+          //video->play();
+          //video->pause();
 
           audio->stop();
           audio->unPause();
           audio->reset();
-          audio->setStreamType(Audio::MPEG2_PES);
-          audio->sync();
-          audio->play();
-          audio->pause();
+          //audio->setStreamType(Audio::MPEG2_PES);
+          //audio->sync();
+          pendingAudioPlay = true;
+          //audio->play();
+          //audio->pause();
 
           demuxer->reset();
           demuxer->seek();
@@ -415,12 +441,14 @@ void PlayerLiveTV::switchState(UCHAR newState)
         case S_STOP:
         { 
           vdr->stopStreaming();
+          pendingAudioPlay=false;
           clearStreamChunks();
           vfeed.stop();
           afeed.stop();
-subtitles->stop();        
- tfeed.stop();         
- video->stop();          video->blank();
+          subtitles->stop();
+          tfeed.stop();
+          video->stop();
+          video->blank();
           audio->stop();
           audio->reset();
           video->reset();
@@ -442,6 +470,7 @@ subtitles->stop();
       {
         case S_PLAY:
         {
+          pendingAudioPlay=false;
           audio->unPause();
           video->unPause();
           state = newState;
@@ -462,14 +491,15 @@ subtitles->stop();
           audio->reset();
 
           video->reset();
-          video->sync();
-          video->play();
-          video->pause();
+          //video->sync();
+          //video->play();
+          //video->pause();
 
-          audio->setStreamType(Audio::MPEG2_PES);
-          audio->sync();
-          audio->play();
-          audio->pause();
+          //audio->setStreamType(Audio::MPEG2_PES);
+          //audio->sync();
+          pendingAudioPlay = true;
+          //audio->play();
+          //audio->pause();
 
           demuxer->reset();
           demuxer->seek();
@@ -484,6 +514,7 @@ subtitles->stop();
         }
         case S_STOP:
         {
+          pendingAudioPlay=false;
           vdr->stopStreaming();
           clearStreamChunks();
           vfeed.stop();
@@ -513,6 +544,7 @@ subtitles->stop();
       {
         case S_STOP:
         { 
+          pendingAudioPlay=false;
           vdr->stopStreaming();
           clearStreamChunks();
           vfeed.stop();
@@ -542,14 +574,16 @@ subtitles->stop();
           audio->reset();
 
           video->reset();
-          video->sync();
-          video->play();
-          video->pause();
+          
+          //video->sync();
+         // video->play();
+          //video->pause();
 
-          audio->setStreamType(Audio::MPEG2_PES);
-          audio->sync();
-          audio->play();
-          audio->pause();
+          //audio->setStreamType(Audio::MPEG2_PES);
+          //audio->sync();
+          //audio->play();
+          //audio->pause();
+          pendingAudioPlay = true;
 
           demuxer->reset();
           demuxer->seek();
@@ -616,7 +650,7 @@ void PlayerLiveTV::threadMethod()
 {
   while(1)
   {
-    if (videoStartup) // we are in S_VIDEOSTARTUP, afeed has signalled that it has written some data
+    if (videoStartup && !pendingAudioPlay) // we are in S_VIDEOSTARTUP, afeed has signalled that it has written some data
     {
       switchState(S_PREBUFFERING);
       videoStartup = false;
@@ -635,22 +669,37 @@ void PlayerLiveTV::threadMethod()
       if (i.instruction == I_SETCHANNEL)
       {
         logger->log("PlayerLiveTV", Log::DEBUG, "start new stream");
-
+       
+        
         switchState(S_VIDEOSTARTUP);
         
         if (!checkError())
         {
-          Channel* chan = (*chanList)[i.channelIndex];
-          chan->loadPids();
-          demuxer->setVID(chan->vpid);
+           Channel* chan = (*chanList)[i.channelIndex];
+           chan->loadPids();
+           h264=chan->vstreamtype==0x1b;
+           demuxer->seth264(h264);
+           video->seth264mode(chan->vstreamtype==0x1b);
+           demuxer->setVID(chan->vpid);
+           video->seth264mode(chan->vstreamtype==0x1b);
+
           if (chan->numAPids > 0) 
           {
             demuxer->setAID(chan->apids[0].pid,0);
+            audio->setStreamType(Audio::MPEG2_PES);
             logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer pids: %u %u", chan->vpid, chan->apids[0].pid);
           }
           else 
           {
-            logger->log("PlayerLiveTV", Log::WARN, "Demuxer video pid only: %u", chan->vpid);
+              if (chan->numDPids > 0  && audio->maysupportAc3()) 
+              {
+                  demuxer->setAID(chan->dpids[0].pid,1);
+                  logger->log("PlayerLiveTV", Log::DEBUG, "Demuxer pids: %u %u (ac3)", chan->vpid, chan->dpids[0].pid);
+              } 
+              else
+              {
+                  logger->log("PlayerLiveTV", Log::WARN, "Demuxer video pid only: %u", chan->vpid);
+              }
           }
           if (chan->numSPids > 0)
             demuxer->setSubID(chan->spids[0].pid);
index ebc3a460cc3e34716ff7d6a01972a2c62a33dea4..1ed46d07a63f40e892200316a163666470d69282 100644 (file)
@@ -134,7 +134,9 @@ class PlayerLiveTV : public PlayerLive, public Thread_TYPE, public Callback, pub
     bool checkError();
 
     bool videoStartup;
+    bool pendingAudioPlay;
     bool stopNow;
+    bool h264;
     int preBufferCount;
     const static int preBufferAmount = 3;
 
index 738b31ac4a887e39d03c3adaad9ba9923900f847..9c45c6f7809904441552b30ceea723fae0845426 100644 (file)
@@ -20,38 +20,14 @@ The vomp client on Windows requires:
 
 * Windows 2000 or later
 * Windows XP for full remote control support
+* Windows Vista for EVR support
 * DirectX 8 graphics card (some older cards might work also)
-* A DirectShow MPEG2 decoder, which supports Video Mixing Renderer 9 (VMR-9),
-  mostly included within DVD software player
+* A DirectShow MPEG2 decoder, which supports Video Mixing Renderer 9 (VMR-9) 
+or the Enhanced Video Renderer (EVR) mostly included within DVD software player
+* For h264 palyback a DirectShow h264 decoder, supporting 
+the Video Mixing Renderer 9 (VMR-9) or the Enhanced Video Renderer (EVR)
 * A network connection to the vompserver computer
 
-Compatibility List for MPEG2 Decoders
-=====================================
-Compatible MPEG2 decoders:
-* Cyberlink PowerDVD 6
-* Ulead MovieFactory 5 (Intervideo Filter shipped within)
-
-Incompatible MPEG2 decoders:
-
-
-Old Compatibility List for MPEG2 Decoders (for Vomp < 0.2.7)
-============================================================
-Compatible MPEG2 decoders:
-* Cyberlink PowerDVD 5 (build 2214 and later, look for the update at cyberlinks webpage)
-* Cyberlink PowerDVD 6
-* Cyberlink PowerDVD 7
-* Nero Showtime 2 (from Nero Suite 6)
-* MPV Decoder Filter
-* Ulead MovieFactory 5 (Intervideo Filter shipped within)
-
-Incompatible MPEG2 decoders:
-* Cyberlink PowerDVD 4
-* MainConcept Video Decoder version 1.0.0.38 (comes with some Hauppauge software)
-
-
-These lists are provided without any warranty.
-These lists will be extended, please report success or failure with your decoder
-at the forum at http://www.loggytronic.com .
 
 Remote Control Buttons Reference
 ================================
index 922d855539240aa45dd64b762a884dbdd2d0f435..260bd5f8e41701a90957123cf2b431967e0474d8 100644 (file)
--- a/recinfo.h
+++ b/recinfo.h
@@ -36,6 +36,8 @@ class RecInfo
     ULONG resumePoint;
     char* summary;
 
+       double fps;
+
     ULONG numComponents;
     UCHAR* streams;
     UCHAR* types;
index c0e2f2a24f3b22697006b18a84dbc1fc997c7ae9..5d932f9a0d41c6468e446ecf2a7afe479adb7b57 100644 (file)
@@ -122,7 +122,7 @@ void Recording::loadMarks()
   if (!VDR::getInstance()->isConnected()) Command::getInstance()->connectionLost();
 }
 
-bool Recording::isRadio()
+bool Recording::isRadio(bool &h264)
 {
   ULONG lengthFrames = 0;
   ULLONG lengthBytes = vdr->streamRecording(getFileName(), &lengthFrames, &IsPesRecording);
@@ -139,10 +139,13 @@ bool Recording::isRadio()
   }
 
   bool hasVideo = false;
+  bool ish264=false;
   if (IsPesRecording)
-    hasVideo = Demuxer::scanForVideo(buffer, thisRead);
+    hasVideo = Demuxer::scanForVideo(buffer, thisRead, ish264);
   else
-    hasVideo = DemuxerTS::scanForVideo(buffer, thisRead);
+    hasVideo = DemuxerTS::scanForVideo(buffer, thisRead,ish264);
+
+  h264=ish264;
 
   free(buffer);
 
index e11428196df6e990dc0d61cd4b33ede9c7caf531..2103bc2ffcfd2bd95083a355cfd3831d7a96a601 100644 (file)
@@ -47,7 +47,7 @@ class Recording
     void loadRecInfo();
     void dropRecInfo();
 
-    bool isRadio();
+    bool isRadio(bool &h264);
     bool IsPesRecording;
 
     void loadMarks();
index f053f0218bcc238cd8084f877b540058487af21e..b0318ae526e4ab32768337be17f6706516915cd6 100644 (file)
--- a/stream.cc
+++ b/stream.cc
@@ -41,6 +41,7 @@ void Stream::shutdown()
 #ifdef WIN32
     CloseHandle(mutex);
 #endif
+      
   }
   initted = 0;
 }
@@ -63,12 +64,13 @@ int Stream::init(DrainTarget* tdt, int bufsize)
 void Stream::flush()
 {
   lock();
+
   mediapackets.clear();
   unLock();
   if (draintarget) draintarget->ResetTimeOffsets();
 }
 
-int Stream::put(const UCHAR* inbuf, int len, UCHAR type)
+int Stream::put(const UCHAR* inbuf, int len, UCHAR type,unsigned int index)
 {
   int ret = 0;
   if (!draintarget) return 0;
@@ -77,13 +79,16 @@ int Stream::put(const UCHAR* inbuf, int len, UCHAR type)
   newPacket.pos_buffer = 0;
   newPacket.type = type;
   newPacket.pts=0;
+  newPacket.dts=0;
   newPacket.synched=false;
+  newPacket.index=index;
 #ifdef WIN32
   newPacket.disconti=false;
   newPacket.presentation_time=0;
 #endif
   if (type!=MPTYPE_MPEG_AUDIO_LAYER3) {//no PES
     //Extract the pts...
+      bool hasdts=false;
     if ((inbuf[7] & 0x80) && len>14 ) {
         newPacket.synched=true;
         newPacket.pts=((ULLONG)(inbuf[9] & 0x0E) << 29 ) |
@@ -91,10 +96,21 @@ int Stream::put(const UCHAR* inbuf, int len, UCHAR type)
                     ( (ULLONG)(inbuf[11] & 0xFE) << 14 ) |
                      ( (ULLONG)(inbuf[12])        <<  7 ) |
                      ( (ULLONG)(inbuf[13] & 0xFE) >>  1 );
+        if ((inbuf[7] & 0x40) && len>19) {
+            newPacket.dts=((ULLONG)(inbuf[14] & 0x0E) << 29 ) |
+                    ( (ULLONG)(inbuf[15])        << 22 ) |
+                    ( (ULLONG)(inbuf[16] & 0xFE) << 14 ) |
+                     ( (ULLONG)(inbuf[17])        <<  7 ) |
+                     ( (ULLONG)(inbuf[18] & 0xFE) >>  1 );
+            hasdts=true;
+        }
 #ifdef WIN32
         //ok we have the pts now convert it to a continously time code in 100ns units
-        newPacket.presentation_time=(ULLONG)(newPacket.pts*10000LL/90LL);
-        newPacket.presentation_time-=draintarget->SetStartOffset(newPacket.presentation_time,&newPacket.disconti);
+        if (hasdts ) newPacket.presentation_time=(ULLONG)(newPacket.dts*10000LL/90LL);
+        else newPacket.presentation_time=(ULLONG)(newPacket.pts*10000LL/90LL);
+
+        //newPacket.presentation_time-=draintarget->SetStartOffset((ULLONG)(newPacket.pts*10000LL/90LL),&newPacket.disconti);
+        newPacket.presentation_time-=draintarget->SetStartOffset((ULLONG)(newPacket.pts*10000LL/90LL),&newPacket.disconti);
 #endif
     }
   }
@@ -137,7 +153,10 @@ int Stream::put(const UCHAR* inbuf, int len, UCHAR type)
     lock();
     mediapackets.push_back(newPacket);
     unLock();
-  }
+  }// else {
+ //     Log::getInstance()->log("Stream", Log::DEBUG, "We are full %d!",bufferSize);
+  //}
+
   return ret;
 }
 
@@ -154,7 +173,10 @@ bool Stream::drain()
     lock();
     if (consumed != 0) ret = true;
     if (consumed > listlength) consumed = listlength;
-    while (consumed--) mediapackets.pop_front();
+    while (consumed--) 
+    {
+        mediapackets.pop_front();
+    }
   }
   unLock();
   return ret;
index aba2fdaab8936ff10c33b5bec1c6365eeca97701..26916ebafc279bcf45a01f2d84cf16127218c770 100644 (file)
--- a/stream.h
+++ b/stream.h
@@ -45,7 +45,7 @@ class Stream
     int init(DrainTarget* tdt, int bufsize);
     void shutdown();
     void flush();
-    int put(const UCHAR* inbuf, int len, UCHAR type);
+    int put(const UCHAR* inbuf, int len, UCHAR type,unsigned int index);
     bool drain();
 
   private:
index 13a1daa70b367056fd3e776e19a67b85431f657e..a6cb01f5897bb44c3414ad55efe078356692a8d7 100644 (file)
@@ -89,7 +89,7 @@ int Surface::drawTextRJ(const char* text, int x, int y, ULONG rgba)
 
   for (i = 0; i < n; i++)
   {
-    w += font->width[text[i]];
+    w += font->width[(unsigned char)text[i]];
   }
 
   x -= w;
@@ -107,7 +107,7 @@ int Surface::drawTextCentre(const char* text, int x, int y, ULONG rgba)
 
   for (i = 0; i < n; i++)
   {
-    w += font->width[text[i]];
+    w += font->width[(unsigned char)text[i]]; //Characters bigger then 128 can appear
   }
 
   x -= w / 2;
index 5153c387b89095c91a46ee074e6a79f1670dfda6..2260ac935aadd09f2678a77be67bfb2568870c4e 100644 (file)
@@ -35,46 +35,57 @@ SurfaceWin::SurfaceWin(int id)
 
 SurfaceWin::~SurfaceWin()
 {
-  if (d3dsurface) d3dsurface->Release();
-  if (d3dtexture) d3dtexture->Release();
-  CloseHandle(event);
+       if (d3dsurface) d3dsurface->Release();
+       if (d3dtexture) d3dtexture->Release();
+       CloseHandle(event);
 }
 
 int SurfaceWin::create(UINT width, UINT height)
 {
-  LPDIRECT3DDEVICE9 d3ddev=((OsdWin*)(Osd::getInstance()))->getD3dDev();
-  while (true) {
-    if (screen==this) {
-      if (d3ddev->CreateTexture(1024,1024,0,0,D3DFMT_A8R8G8B8,
-        // Does every adapter with alpha blending support this?
-        D3DPOOL_DEFAULT,&d3dtexture ,NULL)!=D3D_OK) {
-          MILLISLEEP(50);//wait maybe next time it will work
-          continue;
-      }
-      if (d3dtexture->GetSurfaceLevel(0,&d3dsurface)!=D3D_OK) {
-        d3dtexture->Release();
-        d3dtexture=NULL;
-        MILLISLEEP(50);
-        continue;
-      }
-    } else {
-      HRESULT hres;
-      if (hres=d3ddev->CreateOffscreenPlainSurface(width,height,D3DFMT_A8R8G8B8,
-        D3DPOOL_SYSTEMMEM,&d3dsurface,NULL)!=D3D_OK) {
-          MILLISLEEP(50);//wait maybe next time it will work
-          continue;
-      }
-
-    }
-    sheight=height;
-    swidth=width;
-    /* If someone does high performance Animations on the OSD, we have to change the types
-     of surface in order to address these performance issues, if we have only very few updates
-     per second this would be fast enough !*/
-    break;
-  }
-  SetEvent(event);
-  return 1;
+       OsdWin* osd=((OsdWin*)(Osd::getInstance()));
+
+
+       LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();
+
+       while (true) {
+               if (screen==this) {
+                       osd->BeginPainting();
+                       if (d3ddev->CreateTexture(1024,1024,0,0,D3DFMT_A8R8G8B8,
+                               // Does every adapter with alpha blending support this?
+                               D3DPOOL_DEFAULT,&d3dtexture ,NULL)!=D3D_OK) {
+                                       osd->EndPainting();
+                                       MILLISLEEP(50);//wait maybe next time it will work
+                                       continue;
+                       }
+                       if (d3dtexture->GetSurfaceLevel(0,&d3dsurface)!=D3D_OK) {
+                               d3dtexture->Release();
+                               d3dtexture=NULL;
+                               MILLISLEEP(50);
+                               osd->EndPainting();
+                               continue;
+                       }
+               } else {
+                       HRESULT hres;
+                       if (hres=d3ddev->CreateOffscreenPlainSurface(width,height,D3DFMT_A8R8G8B8,
+                               D3DPOOL_SYSTEMMEM,&d3dsurface,NULL)!=D3D_OK) {
+                                       osd->EndPainting();
+                                       MILLISLEEP(50);//wait maybe next time it will work
+
+                                       continue;
+                       }
+
+               }
+               osd->EndPainting();
+
+               sheight=height;
+               swidth=width;
+               /* If someone does high performance Animations on the OSD, we have to change the types
+               of surface in order to address these performance issues, if we have only very few updates
+               per second this would be fast enough !*/
+               break;
+       }
+       SetEvent(event);
+       return 1;
 }
 
 void SurfaceWin::display()
diff --git a/tcp.cc b/tcp.cc
index 753bed3a162c06900bf9d36c230f46f88006d5b4..05b108ca18ae9feea5ae0b20e29c57da7944cae6 100644 (file)
--- a/tcp.cc
+++ b/tcp.cc
@@ -290,9 +290,9 @@ int TCP::readData(UCHAR* buffer, int totalBytes)
     FD_SET(sock, &readSet);
     timeout.tv_sec = 2;
     timeout.tv_usec = 0;
-    Log::getInstance()->log("TCP", Log::DEBUG, "Going to select");
+  //  Log::getInstance()->log("TCP", Log::DEBUG, "Going to select");
     success = select(sock + 1, &readSet, NULL, NULL, passToSelect);
-    Log::getInstance()->log("TCP", Log::DEBUG, "Back from select with success = %i", success);
+   // Log::getInstance()->log("TCP", Log::DEBUG, "Back from select with success = %i", success);
     if (success < 1)
     {
       return 0;  // error, or timeout
index 44e2c1603f25c72568f5944cb8e72b5eab0b5a9a..f5d10bc3825fe3be5fce7e537bed0d88829f8ac8 100644 (file)
-/*\r
-    Copyright 2008 Marten Richter\r
-\r
-    This file is part of VOMP.\r
-\r
-    VOMP is free software; you can redistribute it and/or modify\r
-    it under the terms of the GNU General Public License as published by\r
-    the Free Software Foundation; either version 2 of the License, or\r
-    (at your option) any later version.\r
-\r
-    VOMP is distributed in the hope that it will be useful,\r
-    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-    GNU General Public License for more details.\r
-\r
-    You should have received a copy of the GNU General Public License\r
-    along with VOMP; if not, write to the Free Software\r
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
-*/\r
-\r
-\r
-/* Portions from vdr osdteletext plugin "txtrender.c": */\r
-/***************************************************************************\r
- *                                                                         *\r
- *   txtrender.c - Teletext display abstraction and teletext code          *\r
- *                 renderer                                                *\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) any later version.                                   *\r
- *                                                                         *\r
- *   Changelog:                                                            *\r
- *     2005-03    initial version (c) Udo Richter                          *\r
- *                                                                         *\r
- ***************************************************************************/\r
-\r
-#include "teletextdecodervbiebu.h"\r
-#include "teletxt/tables.h"\r
-#include "message.h"\r
-#include "command.h"\r
-#include "video.h"\r
-\r
-#ifdef WIN32\r
-#include <windows.h>\r
-#endif\r
-\r
-TeletextDecoderVBIEBU::TeletextDecoderVBIEBU()\r
-{\r
-    selectedpage=0x100;\r
-    ourpage=false;\r
-    flags=lang=0; \r
-  \r
-    CleanPage();\r
-    FirstG0CodePage=0;\r
-    SecondG0CodePage=0;\r
-    dirty=false;\r
-    txtview=NULL;\r
-    firstlineupdate=0;\r
-    gotcha=false;\r
-    char digits[]={'1','0','0'};\r
-    setKeyinDigits(digits,false);\r
-    isrecording=false;\r
-    for (int i=0;i<10;i++) record_pages[i]=-1;\r
-    \r
-\r
-}\r
-\r
-TeletextDecoderVBIEBU::~TeletextDecoderVBIEBU()\r
-{\r
-\r
-\r
-}\r
-\r
-long long TeletextDecoderVBIEBU::SetStartOffset(long long curreftime, bool *rsync)\r
-{\r
-  return 0;  \r
-}\r
-\r
-void TeletextDecoderVBIEBU::ResetTimeOffsets()\r
-{\r
-\r
-}\r
-\r
-\r
-\r
-void TeletextDecoderVBIEBU::ResetDecoder()\r
-{\r
-    gotcha=false;\r
-    ourpage=false;\r
-    firstlineupdate=0;\r
-    selectedpage=0x100;\r
-    CleanPage();\r
-    char digits[]={'1','0','0'};\r
-    setKeyinDigits(digits,false);\r
-    for (int i=0;i<10;i++) record_pages[i]=-1;\r
-  \r
-}\r
-\r
-void TeletextDecoderVBIEBU::setPage(unsigned int newpage)\r
-{\r
-    selectedpage=newpage;\r
-    gotcha=false;\r
-    ourpage=false;\r
-    firstlineupdate=0;\r
-    for (int i=0;i<25;i++) {\r
-        memset(curpage[i],0,40);\r
-    }\r
-}\r
-\r
-void TeletextDecoderVBIEBU::CleanPage()\r
-{\r
-    int x,y;\r
-    for (int i=0;i<25;i++) {\r
-        memset(curpage[i],0,40);\r
-    }\r
-    for (y=0;y<25;y++) {\r
-        for (x=0;x<40;x++) {\r
-            cTeletextChar c;\r
-            c.SetFGColor(ttcWhite);\r
-            c.SetBGColor(ttcBlack);\r
-            c.SetCharset(CHARSET_LATIN_G0);\r
-            c.SetChar(' ');\r
-            if (flags&0x60) {\r
-                c.SetBoxedOut(true);    \r
-            }\r
-            setChar(x,y,c);\r
-        }\r
-    } \r
-\r
-}\r
-void TeletextDecoderVBIEBU::setKeyinDigits(char digits[3],bool inKeying)\r
-{\r
-    int x;\r
-    inkeying=inKeying;\r
-    for (x=0;x<3;x++) {\r
-        cTeletextChar c;\r
-        c.SetFGColor(ttcWhite);\r
-        c.SetBGColor(ttcBlack);\r
-        c.SetCharset(CHARSET_LATIN_G0);\r
-        c.SetChar(digits[x]);\r
-        if (flags&0x60) {\r
-            c.SetBoxedOut(true);    \r
-        }\r
-        setChar(x+3,0,c);\r
-        keyindigits[x]=digits[x];\r
-    }\r
-}\r
-\r
-void TeletextDecoderVBIEBU::PrepareMediaSample(const MediaPacketList& mplist, UINT samplepos)\r
-{\r
-    mediapacket = mplist.front();\r
-}\r
-\r
-static ULLONG PTSDifference(ULLONG pts1, ULLONG pts2)\r
-{\r
-  // Assume pts1, pts2 < 2^33; calculate pts1 - pts2\r
-  if (pts1 > pts2)\r
-    return pts1 - pts2;\r
-  else\r
-    return (1LL<<33) + pts1 - pts2;\r
-}\r
-\r
-UINT TeletextDecoderVBIEBU::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)\r
-{\r
-   if (mediapacket.type != MPTYPE_TELETEXT)\r
-   {\r
-       *samplepos= 0;\r
-       return 1; //Skip it! \r
-   }\r
-   unsigned int headerstrip;\r
-   unsigned char txtdata[43];\r
-   headerstrip=buffer[mediapacket.pos_buffer+8]+9;\r
-   //headerstrip+=4; //substream id\r
-   unsigned int datapos=0;\r
-   unsigned int datatype=buffer[mediapacket.pos_buffer+headerstrip+0];\r
-   //Chris should we use here the pts data from mediapacket ?\r
-   // in this case the data fields should also be added in mediamvp\r
-   if (mediapacket.synched)\r
-    { // An entry exists in the work list\r
-        ULLONG nowPTS = Video::getInstance()->getCurrentTimestamp();\r
-       if (PTSDifference(mediapacket.pts, nowPTS) >= 1200*90000) {\r
-            *samplepos=0;\r
-            return 1;//bad data skip it\r
-        }\r
-        if (nowPTS < (mediapacket.pts-4000)  ) {\r
-            *samplepos=0;\r
-            return 0;\r
-        } \r
-   }\r
-   \r
-   if (( datatype>=0x10 && datatype <=0x1F) ||\r
-       ( datatype>=0x99 && datatype <=0x9B)) {\r
-       //EBU VBI DATA\r
-       datapos++;\r
-       while (datapos< (mediapacket.length-headerstrip)) {\r
-           unsigned int unit_id=buffer[mediapacket.pos_buffer+headerstrip+datapos];\r
-           datapos++;\r
-           unsigned int unit_length=buffer[mediapacket.pos_buffer+headerstrip+datapos];\r
-           datapos++;\r
-           switch (unit_id) {\r
-               case 0x02:\r
-               case 0x03: {//Teletext with and without subtitles\r
-                   //call teletext decoder\r
-                   unsigned int field=buffer[mediapacket.pos_buffer+headerstrip+datapos];\r
-\r
-                   if ((datapos+44)< (mediapacket.length-headerstrip)) {\r
-                       for (int i=0;i<42;i++) {\r
-                           txtdata[i]=invtab[buffer[mediapacket.pos_buffer+headerstrip+datapos+2+i]];\r
-                       }\r
-                       DecodeTeletext(txtdata,field);\r
-                   }\r
-                          }break;\r
-               case  0xC0: //inverted Teletext\r
-                   //call teletext decoder\r
-               break;\r
-               \r
-               case 0xC3: //VPS\r
-                   //what to do with this, in the moment we do not need it\r
-               break;\r
-               case 0xC4: //WSS\r
-                   //what to do with this, in the moment we do not need it\r
-               break;\r
-               case 0xC5: //CC\r
-                   //what to do with this, in the moment we do not need it\r
-               break;\r
-               case 0xC6: //monochrome 4:2:2 samples, what is that? \r
-                   //what to do with this, in the moment we do not need it\r
-               break;\r
-               default:\r
-               // case 0x00,0x01,0x04..0x7f,0x80..0xbf,0xc1,0xc2,0xc7..0xfe,0xff: //discard\r
-                   //discard\r
-               break;\r
-           };\r
-           datapos+=unit_length;\r
-       //    while (buffer[mediapacket.pos_buffer+headerstrip+datapos]==0xFF &&(datapos< (mediapacket.length-headerstrip))) {\r
-        //       datapos++; //stuffing bytes\r
-         //  }\r
-\r
-           \r
-       }\r
-       *samplepos=0;\r
-       return 1;\r
-\r
-\r
-   } else {\r
-           *samplepos= 0;\r
-           return 1; //Skip it! and discard data   \r
-   }\r
-\r
-   return 0;\r
-\r
-}\r
-// This part is inspired by the vdr-plugin-osdteletext of Udo Richter and Marcel Wiesweg\r
-void TeletextDecoderVBIEBU::DecodeTeletext(const UCHAR* buffer, unsigned int field) //needs to be exactly 42 byte long!!\r
-{\r
-   UCHAR hdrbuf[5];\r
-   for (int i=0;i<5;i++) hdrbuf[i]=(unhamtab[buffer[2*i]]&0xF) | ((unhamtab[buffer[2*i+1]]&0xF)<< 4);\r
-   int header=hdrbuf[0];\r
-   int magazin=header & 0x7;\r
-   int line = (header>>3) & 0x1f;\r
-   if (magazin==0) magazin=8;\r
-   if (line==0)\r
-   {\r
-       if (ourpage) {\r
-           gotcha=true;\r
-           inkeying=false;\r
-           RenderTeletextCode(false);\r
-       } else {\r
-           RenderTeletextCode(true);\r
-       }\r
-       int pagenumber=hdrbuf[1];\r
-       int pagemagazin=magazin<<8 | pagenumber;\r
-       int pagesubnumber=(hdrbuf[2]) || ((hdrbuf[3]<<8) & 0x3f7f);\r
-\r
-       if (pagemagazin == selectedpage) ourpage=true;\r
-       else ourpage=false;\r
-       if (isrecording) {\r
-           for (int i=0;i<10;i++) {\r
-               if (pagemagazin==record_pages[i]) break;\r
-               if (record_pages[i]==-1) {\r
-                   record_pages[i]=pagemagazin;\r
-                   break;\r
-               }\r
-           }\r
-       }\r
-       if (hdrbuf[3] &0x80) { //This is a subtitle\r
-            for (int i=0;i<10;i++) {\r
-               if (pagemagazin==record_pages[i]) break;\r
-               if (record_pages[i]==-1) {\r
-                   record_pages[i]=pagemagazin;\r
-                   break;\r
-               }\r
-           }\r
-       }\r
-\r
-\r
-       if (ourpage) {\r
-           lang=((hdrbuf[4]>>5) & 0x07);\r
-           flags=hdrbuf[2] & 0x80;\r
-           flags|=(hdrbuf[3]&0x40)|((hdrbuf[3]>>2)&0x20); //??????\r
-           flags|=((hdrbuf[4]<<4)&0x10)|((hdrbuf[4]<<2)&0x08)|(hdrbuf[4]&0x04)|((hdrbuf[4]>>1)&0x02)|((hdrbuf[4]>>4)&0x01);\r
-           for (int i=0;i<25;i++) {\r
-               memset(curpage[i],0,40);\r
-            }\r
-       }\r
-       \r
-       memcpy(curpage[line],buffer+2,40);\r
-   } else if (ourpage && (line<=25)) {\r
-       memcpy(curpage[line],buffer+2,40);\r
-       \r
-   }\r
-}\r
-\r
-\r
-/* from osdteletext plugin: (slightly adapted for vomp)*/\r
-// Font tables\r
-\r
-// teletext uses 7-bit numbers to identify a font set.\r
-// There are three font sets involved:\r
-// Primary G0, Secondary G0, and G2 font set.\r
-\r
-// Font tables are organized in blocks of 8 fonts:\r
-\r
-enumCharsets FontBlockG0_0000[8] = {\r
-    CHARSET_LATIN_G0_EN,\r
-    CHARSET_LATIN_G0_DE,\r
-    CHARSET_LATIN_G0_SV_FI,\r
-    CHARSET_LATIN_G0_IT,\r
-    CHARSET_LATIN_G0_FR,\r
-    CHARSET_LATIN_G0_PT_ES,\r
-    CHARSET_LATIN_G0_CZ_SK,\r
-    CHARSET_LATIN_G0\r
-};\r
-\r
-enumCharsets FontBlockG2Latin[8]={\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_LATIN_G2\r
-};\r
-\r
-enumCharsets FontBlockG0_0001[8] = {\r
-    CHARSET_LATIN_G0_PL,\r
-    CHARSET_LATIN_G0_DE,\r
-    CHARSET_LATIN_G0_SV_FI,\r
-    CHARSET_LATIN_G0_IT,\r
-    CHARSET_LATIN_G0_FR,\r
-    CHARSET_LATIN_G0,\r
-    CHARSET_LATIN_G0_CZ_SK,\r
-    CHARSET_LATIN_G0\r
-};\r
-\r
-enumCharsets FontBlockG0_0010[8] = {\r
-    CHARSET_LATIN_G0_EN,\r
-    CHARSET_LATIN_G0_DE,\r
-    CHARSET_LATIN_G0_SV_FI,\r
-    CHARSET_LATIN_G0_IT,\r
-    CHARSET_LATIN_G0_FR,\r
-    CHARSET_LATIN_G0_PT_ES,\r
-    CHARSET_LATIN_G0_TR,\r
-    CHARSET_LATIN_G0\r
-};\r
-\r
-\r
-enumCharsets FontBlockG0_0011[8] = {\r
-    CHARSET_LATIN_G0,\r
-    CHARSET_LATIN_G0,\r
-    CHARSET_LATIN_G0,\r
-    CHARSET_LATIN_G0,\r
-    CHARSET_LATIN_G0,\r
-    CHARSET_LATIN_G0_SR_HR_SL,\r
-    CHARSET_LATIN_G0,\r
-    CHARSET_LATIN_G0_RO\r
-};\r
-\r
-enumCharsets FontBlockG0_0100[8] = {\r
-    CHARSET_CYRILLIC_G0_SR_HR,\r
-    CHARSET_LATIN_G0_DE,\r
-    CHARSET_LATIN_G0_EE,\r
-    CHARSET_LATIN_G0_LV_LT,\r
-    CHARSET_CYRILLIC_G0_RU_BG,\r
-    CHARSET_CYRILLIC_G0_UK,\r
-    CHARSET_LATIN_G0_CZ_SK,\r
-    CHARSET_INVALID\r
-};\r
-\r
-enumCharsets FontBlockG2_0100[8] = {\r
-    CHARSET_CYRILLIC_G2,\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_CYRILLIC_G2,\r
-    CHARSET_CYRILLIC_G2,\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_INVALID\r
-};\r
-\r
-enumCharsets FontBlockG0_0110[8] = {\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_LATIN_G0_TR,\r
-    CHARSET_GREEK_G0\r
-};\r
-\r
-enumCharsets FontBlockG2_0110[8] = {\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_LATIN_G2,\r
-    CHARSET_GREEK_G2\r
-};\r
-\r
-enumCharsets FontBlockG0_1000[8] = {\r
-    CHARSET_LATIN_G0_EN,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_LATIN_G0_FR,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_ARABIC_G0\r
-};\r
-\r
-enumCharsets FontBlockG2_1000[8] = {\r
-    CHARSET_ARABIC_G2,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_ARABIC_G2,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_ARABIC_G2\r
-};\r
-\r
-enumCharsets FontBlockG0_1010[8] = {\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_HEBREW_G0,\r
-    CHARSET_INVALID,\r
-    CHARSET_ARABIC_G0,\r
-};\r
-\r
-enumCharsets FontBlockG2_1010[8] = {\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_ARABIC_G2,\r
-    CHARSET_INVALID,\r
-    CHARSET_ARABIC_G2,\r
-};\r
-\r
-enumCharsets FontBlockInvalid[8] = {\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID,\r
-    CHARSET_INVALID\r
-};\r
-\r
-\r
-\r
-// The actual font table definition:\r
-// Split the 7-bit number into upper 4 and lower 3 bits,\r
-// use upper 4 bits for outer array,\r
-// use lower 3 bits for inner array\r
-\r
-struct structFontBlock {\r
-    enumCharsets *G0Block;\r
-    enumCharsets *G2Block;\r
-};\r
-    \r
-structFontBlock FontTable[16] = {\r
-    { FontBlockG0_0000, FontBlockG2Latin }, // 0000 block\r
-    { FontBlockG0_0001, FontBlockG2Latin }, // 0001 block\r
-    { FontBlockG0_0010, FontBlockG2Latin }, // 0010 block\r
-    { FontBlockG0_0011, FontBlockG2Latin }, // 0011 block\r
-    { FontBlockG0_0100, FontBlockG2_0100 }, // 0100 block\r
-    { FontBlockInvalid, FontBlockInvalid }, // 0101 block\r
-    { FontBlockG0_0110, FontBlockG2_0110 }, // 0110 block\r
-    { FontBlockInvalid, FontBlockInvalid }, // 0111 block\r
-    { FontBlockG0_1000, FontBlockG2_1000 }, // 1000 block\r
-    { FontBlockInvalid, FontBlockInvalid }, // 1001 block\r
-    { FontBlockG0_1010, FontBlockG2_1010 }, // 1010 block\r
-    { FontBlockInvalid, FontBlockInvalid }, // 1011 block\r
-    { FontBlockInvalid, FontBlockInvalid }, // 1100 block\r
-    { FontBlockInvalid, FontBlockInvalid }, // 1101 block\r
-    { FontBlockInvalid, FontBlockInvalid }, // 1110 block\r
-    { FontBlockInvalid, FontBlockInvalid }  // 1111 block\r
-};\r
-\r
-inline enumCharsets GetG0Charset(int codepage) {\r
-    return FontTable[codepage>>3].G0Block[codepage&7];\r
-}\r
-inline enumCharsets GetG2Charset(int codepage) {\r
-    return FontTable[codepage>>3].G2Block[codepage&7];\r
-}\r
-\r
-enum enumSizeMode {\r
-    // Possible size modifications of characters\r
-    sizeNormal,\r
-    sizeDoubleWidth,\r
-    sizeDoubleHeight,\r
-    sizeDoubleSize\r
-};\r
-\r
-void TeletextDecoderVBIEBU::RenderTeletextCode(bool renderfirstlineonly) {\r
-    int x,y;\r
-    bool EmptyNextLine=false;\r
-    // Skip one line, in case double height chars were/will be used\r
-\r
-    // Get code pages:\r
-    int LocalG0CodePage=(FirstG0CodePage & 0x78) \r
-            | ((lang & 0x04)>>2) | (lang & 0x02) | ((lang & 0x01)<<2);\r
-    enumCharsets FirstG0=GetG0Charset(LocalG0CodePage);\r
-    enumCharsets SecondG0=GetG0Charset(SecondG0CodePage);\r
-    // Reserved for later use:\r
-    // enumCharsets FirstG2=GetG2Charset(LocalG0CodePage);\r
-    \r
-    for (y=0;y<24;(EmptyNextLine?y+=2:y++)) {\r
-        // Start of line: Set start of line defaults\r
-        \r
-        // Hold Mosaics mode: Remember last mosaic char/charset \r
-        // for next spacing code\r
-        bool HoldMosaics=false;\r
-        unsigned char HoldMosaicChar=' ';\r
-        enumCharsets HoldMosaicCharset=FirstG0;\r
-\r
-        enumSizeMode Size=sizeNormal;\r
-        // Font size modification\r
-        bool SecondCharset=false;\r
-        // Use primary or secondary G0 charset\r
-        bool GraphicCharset=false;\r
-        // Graphics charset used?\r
-        bool SeparateGraphics=false;\r
-        // Use separated vs. contiguous graphics charset\r
-        bool NoNextChar=false;\r
-        // Skip display of next char, for double-width\r
-        EmptyNextLine=false;\r
-        // Skip next line, for double-height\r
-\r
-        cTeletextChar c;\r
-        // auto.initialized to everything off\r
-        c.SetFGColor(ttcWhite);\r
-        c.SetBGColor(ttcBlack);\r
-        c.SetCharset(FirstG0);\r
-        \r
-        if (y==0 && (flags&0x10)) {\r
-            if (!inkeying ) c.SetBoxedOut(true);\r
-            \r
-        }\r
-        if (flags&0x60) {\r
-           if (!(inkeying && y==0) ) c.SetBoxedOut(true);\r
-            \r
-        }\r
-        if (y==0) {\r
-            \r
-            for (x=0;x<8;x++) {\r
-                cTeletextChar c2=c;\r
-               \r
-                if (x>=3 && x<6){\r
-                    c2.SetChar(keyindigits[x-3]);\r
-\r
-                }\r
-                else\r
-                    c2.SetChar(' ');\r
-                setChar(x,0,c2);\r
-            }\r
-        }\r
-\r
-        // Pre-scan for double-height and double-size codes\r
-        for (x=0;x<40;x++) {\r
-            if (y==0 && x<8) x=8;\r
-            if ((curpage[y][x] & 0x7f)==0x0D || (curpage[y][x] & 0x7f)==0x0F)\r
-                EmptyNextLine=true;\r
-        }\r
-\r
-        // Move through line\r
-        for (x=0;x<40;x++) {\r
-            unsigned char ttc=curpage[y][x] & 0x7f;\r
-            // skip parity check\r
-\r
-            if (y==0 && x<8) continue;\r
-            if (y==0 && x<31 && renderfirstlineonly && gotcha && !inkeying) continue;\r
-            // no displayable data here...\r
-            \r
-/*          // Debug only: Output line data and spacing codes\r
-            if (y==6) {\r
-                if (ttc<0x20)\r
-                    printf("%s ",names[ttc]);\r
-                else\r
-                    printf("%02x ",ttc);\r
-                if (x==39) printf("\n");\r
-            }\r
-*/          \r
-            \r
-            // Handle all 'Set-At' spacing codes\r
-            switch (ttc) {\r
-            case 0x09: // Steady\r
-                c.SetBlink(false);\r
-                break;\r
-            case 0x0C: // Normal Size\r
-                if (Size!=sizeNormal) {\r
-                    Size=sizeNormal;\r
-                    HoldMosaicChar=' ';\r
-                    HoldMosaicCharset=FirstG0;\r
-                }                   \r
-                break;\r
-            case 0x18: // Conceal\r
-                c.SetConceal(true);\r
-                break;\r
-            case 0x19: // Contiguous Mosaic Graphics\r
-                SeparateGraphics=false;\r
-                if (GraphicCharset)\r
-                    c.SetCharset(CHARSET_GRAPHICS_G1);\r
-                break;\r
-            case 0x1A: // Separated Mosaic Graphics\r
-                SeparateGraphics=true;\r
-                if (GraphicCharset)\r
-                    c.SetCharset(CHARSET_GRAPHICS_G1_SEP);\r
-                break;\r
-            case 0x1C: // Black Background\r
-                c.SetBGColor(ttcBlack);\r
-                break;\r
-            case 0x1D: // New Background\r
-                c.SetBGColor(c.GetFGColor());\r
-                break;\r
-            case 0x1E: // Hold Mosaic\r
-                HoldMosaics=true;               \r
-                break;\r
-            }\r
-\r
-            // temporary copy of character data:\r
-            cTeletextChar c2=c;\r
-            // c2 will be text character or space character or hold mosaic\r
-            // c2 may also have temporary flags or charsets\r
-            \r
-            if (ttc<0x20) {\r
-                // Spacing code, display space or hold mosaic\r
-                if (HoldMosaics) {\r
-                    c2.SetChar(HoldMosaicChar);\r
-                    c2.SetCharset(HoldMosaicCharset);\r
-                } else {\r
-                    c2.SetChar(' ');\r
-                }\r
-            } else {\r
-                // Character code               \r
-                c2.SetChar(ttc);\r
-                if (GraphicCharset) {\r
-                    if (ttc&0x20) {\r
-                        // real graphics code, remember for HoldMosaics\r
-                        HoldMosaicChar=ttc;\r
-                        HoldMosaicCharset=c.GetCharset();\r
-                    } else {\r
-                        // invalid code, pass-through to G0\r
-                        c2.SetCharset(SecondCharset?SecondG0:FirstG0);\r
-                    }   \r
-                }\r
-            }\r
-            \r
-            // Handle double-height and double-width extremes\r
-            if (y>=23) {\r
-                if (Size==sizeDoubleHeight) Size=sizeNormal;\r
-                if (Size==sizeDoubleSize) Size=sizeDoubleWidth;\r
-            }\r
-            if (x>=38) {\r
-                if (Size==sizeDoubleWidth) Size=sizeNormal;\r
-                if (Size==sizeDoubleSize) Size=sizeDoubleHeight;\r
-            }\r
-            \r
-            // Now set character code\r
-            \r
-            if (NoNextChar) {\r
-                // Suppress this char due to double width last char\r
-                NoNextChar=false;\r
-            } else {\r
-                switch (Size) {\r
-                case sizeNormal:\r
-                    // Normal sized\r
-                    setChar(x,y,c2);\r
-                    if (EmptyNextLine && y<23) {\r
-                        // Clean up next line\r
-                        setChar(x,y+1,c2.ToChar(' ').ToCharset(FirstG0));\r
-                    }\r
-                    break;\r
-                case sizeDoubleWidth:\r
-                    // Double width\r
-                    setChar(x,y,c2.ToDblWidth(dblw_Left));\r
-                    setChar(x+1,y,c2.ToDblWidth(dblw_Right));\r
-                    if (EmptyNextLine && y<23) {\r
-                        // Clean up next line\r
-                        setChar(x  ,y+1,c2.ToChar(' ').ToCharset(FirstG0));\r
-                        setChar(x+1,y+1,c2.ToChar(' ').ToCharset(FirstG0));\r
-                    }\r
-                    NoNextChar=true;\r
-                    break;\r
-                case sizeDoubleHeight:\r
-                    // Double height\r
-                    setChar(x,y,c2.ToDblHeight(dblh_Top));\r
-                    setChar(x,y+1,c2.ToDblHeight(dblh_Bottom));\r
-                    break;\r
-                case sizeDoubleSize:\r
-                    // Double Size\r
-                    setChar(x  ,  y,c2.ToDblHeight(dblh_Top   ).ToDblWidth(dblw_Left ));\r
-                    setChar(x+1,  y,c2.ToDblHeight(dblh_Top   ).ToDblWidth(dblw_Right));\r
-                    setChar(x  ,y+1,c2.ToDblHeight(dblh_Bottom).ToDblWidth(dblw_Left ));\r
-                    setChar(x+1,y+1,c2.ToDblHeight(dblh_Bottom).ToDblWidth(dblw_Right));\r
-                    NoNextChar=true;\r
-                    break;\r
-                }\r
-            }\r
-                \r
-            // Handle all 'Set-After' spacing codes\r
-             if (ttc>=0x00 &&  ttc<=0x07) { // Set FG color\r
-                if (GraphicCharset) {\r
-                    // Actual switch from graphics charset\r
-                    HoldMosaicChar=' ';\r
-                    HoldMosaicCharset=FirstG0;\r
-                }\r
-                c.SetFGColor((enumTeletextColor)ttc);\r
-                c.SetCharset(SecondCharset?SecondG0:FirstG0);\r
-                GraphicCharset=false;\r
-                c.SetConceal(false);\r
-             } else if (ttc==0x08) {\r
-                c.SetBlink(true);\r
-             } else if (ttc==0x0A) {\r
-                c.SetBoxedOut(true);\r
-             } else if (ttc==0x0B) {\r
-             // Start Box\r
-                c.SetBoxedOut(false);\r
-             } else if (ttc==0x0D) {\r
-                if (Size!=sizeDoubleHeight) {\r
-                    Size=sizeDoubleHeight;\r
-                    HoldMosaicChar=' ';\r
-                    HoldMosaicCharset=FirstG0;\r
-                }                   \r
-             } else if (ttc==0x0E) {\r
-                if (Size!=sizeDoubleWidth) {\r
-                    Size=sizeDoubleWidth;\r
-                    HoldMosaicChar=' ';\r
-                    HoldMosaicCharset=FirstG0;\r
-                }                   \r
-             } else if (ttc==0x0E) {\r
-                if (Size!=sizeDoubleSize) {\r
-                    Size=sizeDoubleSize;\r
-                    HoldMosaicChar=' ';\r
-                    HoldMosaicCharset=FirstG0;\r
-                }                   \r
-             } else  if (ttc>=0x10 && ttc<=0x17) { \r
-                if (!GraphicCharset) {\r
-                    // Actual switch to graphics charset\r
-                    HoldMosaicChar=' ';\r
-                    HoldMosaicCharset=FirstG0;\r
-                }\r
-                c.SetFGColor((enumTeletextColor)(ttc-0x10));\r
-                c.SetCharset(SeparateGraphics?CHARSET_GRAPHICS_G1_SEP:CHARSET_GRAPHICS_G1);\r
-                GraphicCharset=true;\r
-                c.SetConceal(false);\r
-             } else if (ttc==0x1B) {\r
-                SecondCharset=!SecondCharset;\r
-                if (!GraphicCharset) c.SetCharset(SecondCharset?SecondG0:FirstG0);\r
-             } else if (ttc==0x1F) {\r
-                HoldMosaics=false;\r
-             }\r
-            \r
-        } // end for x\r
-        if (renderfirstlineonly) break;\r
-    } // end for y\r
-    \r
-    for (x=0;x<40;x++) {\r
-        // Clean out last line\r
-        cTeletextChar c;\r
-        c.SetFGColor(ttcWhite);\r
-        c.SetBGColor(ttcBlack);\r
-        c.SetCharset(FirstG0);\r
-        c.SetChar(' ');\r
-        if (flags&0x60) {\r
-            c.SetBoxedOut(true);    \r
-        }\r
-        setChar(x,24,c);\r
-    } \r
-    for (y=0;y<25;y++) {\r
-        for (x=0;x<40;x++) {\r
-            if (isDirty(x,y)) {\r
-                dirty=true;\r
-                break;\r
-            }\r
-            if (dirty) break;\r
-        }\r
-        if (dirty) break;\r
-    }\r
-     \r
-    if (dirty && txtview!=NULL ) {\r
-        \r
-        if ( !renderfirstlineonly) {\r
-            Message* m= new Message();\r
-            m->message = Message::TELETEXTUPDATE;\r
-            m->to = txtview;\r
-            m->from = this;\r
-            m->parameter = 0;\r
-            Command::getInstance()->postMessageFromOuterSpace(m);\r
-        } else if (firstlineupdate==10) {\r
-            Message* m= new Message();\r
-            m->message = Message::TELETEXTUPDATEFIRSTLINE;\r
-            m->to = txtview;\r
-            m->from = this;\r
-            m->parameter = 0;\r
-            Command::getInstance()->postMessageFromOuterSpace(m);\r
-            firstlineupdate=0;\r
-        } else firstlineupdate++;\r
-        \r
-       \r
-    }\r
-        \r
-}\r
+/*
+    Copyright 2008 Marten Richter
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+
+/* Portions from vdr osdteletext plugin "txtrender.c": */
+/***************************************************************************
+ *                                                                         *
+ *   txtrender.c - Teletext display abstraction and teletext code          *
+ *                 renderer                                                *
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ *   Changelog:                                                            *
+ *     2005-03    initial version (c) Udo Richter                          *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "teletextdecodervbiebu.h"
+#include "teletxt/tables.h"
+#include "message.h"
+#include "command.h"
+#include "video.h"
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+TeletextDecoderVBIEBU::TeletextDecoderVBIEBU()
+{
+    selectedpage=0x100;
+    ourpage=false;
+    flags=lang=0; 
+  
+    CleanPage();
+    FirstG0CodePage=0;
+    SecondG0CodePage=0;
+    dirty=false;
+    txtview=NULL;
+    firstlineupdate=0;
+    gotcha=false;
+    char digits[]={'1','0','0'};
+    setKeyinDigits(digits,false);
+    isrecording=false;
+    for (int i=0;i<10;i++) record_pages[i]=-1;
+    
+
+}
+
+TeletextDecoderVBIEBU::~TeletextDecoderVBIEBU()
+{
+
+
+}
+
+long long TeletextDecoderVBIEBU::SetStartOffset(long long curreftime, bool *rsync)
+{
+  return 0;  
+}
+
+void TeletextDecoderVBIEBU::ResetTimeOffsets()
+{
+
+}
+
+
+
+void TeletextDecoderVBIEBU::ResetDecoder()
+{
+    gotcha=false;
+    ourpage=false;
+    firstlineupdate=0;
+    selectedpage=0x100;
+    CleanPage();
+    char digits[]={'1','0','0'};
+    setKeyinDigits(digits,false);
+    for (int i=0;i<10;i++) record_pages[i]=-1;
+  
+}
+
+void TeletextDecoderVBIEBU::setPage(unsigned int newpage)
+{
+    selectedpage=newpage;
+    gotcha=false;
+    ourpage=false;
+    firstlineupdate=0;
+    for (int i=0;i<25;i++) {
+        memset(curpage[i],0,40);
+    }
+}
+
+void TeletextDecoderVBIEBU::CleanPage()
+{
+    int x,y;
+    for (int i=0;i<25;i++) {
+        memset(curpage[i],0,40);
+    }
+    for (y=0;y<25;y++) {
+        for (x=0;x<40;x++) {
+            cTeletextChar c;
+            c.SetFGColor(ttcWhite);
+            c.SetBGColor(ttcBlack);
+            c.SetCharset(CHARSET_LATIN_G0);
+            c.SetChar(' ');
+            if (flags&0x60) {
+                c.SetBoxedOut(true);    
+            }
+            setChar(x,y,c);
+        }
+    } 
+
+}
+void TeletextDecoderVBIEBU::setKeyinDigits(char digits[3],bool inKeying)
+{
+    int x;
+    inkeying=inKeying;
+    for (x=0;x<3;x++) {
+        cTeletextChar c;
+        c.SetFGColor(ttcWhite);
+        c.SetBGColor(ttcBlack);
+        c.SetCharset(CHARSET_LATIN_G0);
+        c.SetChar(digits[x]);
+        if (flags&0x60) {
+            c.SetBoxedOut(true);    
+        }
+        setChar(x+3,0,c);
+        keyindigits[x]=digits[x];
+    }
+}
+
+void TeletextDecoderVBIEBU::PrepareMediaSample(const MediaPacketList& mplist, UINT samplepos)
+{
+    mediapacket = mplist.front();
+}
+
+static ULLONG PTSDifference(ULLONG pts1, ULLONG pts2)
+{
+  // Assume pts1, pts2 < 2^33; calculate pts1 - pts2
+  if (pts1 > pts2)
+    return pts1 - pts2;
+  else
+    return (1LL<<33) + pts1 - pts2;
+}
+
+UINT TeletextDecoderVBIEBU::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
+{
+   if (mediapacket.type != MPTYPE_TELETEXT)
+   {
+       *samplepos= 0;
+       return 1; //Skip it! 
+   }
+   unsigned int headerstrip;
+   unsigned char txtdata[43];
+   headerstrip=buffer[mediapacket.pos_buffer+8]+9;
+   //headerstrip+=4; //substream id
+   unsigned int datapos=0;
+   unsigned int datatype=buffer[mediapacket.pos_buffer+headerstrip+0];
+   //Chris should we use here the pts data from mediapacket ?
+   // in this case the data fields should also be added in mediamvp
+   if (mediapacket.synched)
+    { // An entry exists in the work list
+        ULLONG nowPTS = Video::getInstance()->getCurrentTimestamp();
+       if (PTSDifference(mediapacket.pts, nowPTS) >= 1200*90000) {
+            *samplepos=0;
+            return 1;//bad data skip it
+        }
+        if (nowPTS < (mediapacket.pts-4000)  ) {
+            *samplepos=0;
+            return 0;
+        } 
+   }
+   
+   if (( datatype>=0x10 && datatype <=0x1F) ||
+       ( datatype>=0x99 && datatype <=0x9B)) {
+       //EBU VBI DATA
+       datapos++;
+       while (datapos< (mediapacket.length-headerstrip)) {
+           unsigned int unit_id=buffer[mediapacket.pos_buffer+headerstrip+datapos];
+           datapos++;
+           unsigned int unit_length=buffer[mediapacket.pos_buffer+headerstrip+datapos];
+           datapos++;
+           switch (unit_id) {
+               case 0x02:
+               case 0x03: {//Teletext with and without subtitles
+                   //call teletext decoder
+                   unsigned int field=buffer[mediapacket.pos_buffer+headerstrip+datapos];
+
+                   if ((datapos+44)< (mediapacket.length-headerstrip)) {
+                       for (int i=0;i<42;i++) {
+                           txtdata[i]=invtab[buffer[mediapacket.pos_buffer+headerstrip+datapos+2+i]];
+                       }
+                       DecodeTeletext(txtdata,field);
+                   }
+                          }break;
+               case  0xC0: //inverted Teletext
+                   //call teletext decoder
+               break;
+               
+               case 0xC3: //VPS
+                   //what to do with this, in the moment we do not need it
+               break;
+               case 0xC4: //WSS
+                   //what to do with this, in the moment we do not need it
+               break;
+               case 0xC5: //CC
+                   //what to do with this, in the moment we do not need it
+               break;
+               case 0xC6: //monochrome 4:2:2 samples, what is that? 
+                   //what to do with this, in the moment we do not need it
+               break;
+               default:
+               // case 0x00,0x01,0x04..0x7f,0x80..0xbf,0xc1,0xc2,0xc7..0xfe,0xff: //discard
+                   //discard
+               break;
+           };
+           datapos+=unit_length;
+       //    while (buffer[mediapacket.pos_buffer+headerstrip+datapos]==0xFF &&(datapos< (mediapacket.length-headerstrip))) {
+        //       datapos++; //stuffing bytes
+         //  }
+
+           
+       }
+       *samplepos=0;
+       return 1;
+
+
+   } else {
+           *samplepos= 0;
+           return 1; //Skip it! and discard data   
+   }
+
+   return 0;
+
+}
+// This part is inspired by the vdr-plugin-osdteletext of Udo Richter and Marcel Wiesweg
+void TeletextDecoderVBIEBU::DecodeTeletext(const UCHAR* buffer, unsigned int field) //needs to be exactly 42 byte long!!
+{
+   UCHAR hdrbuf[5];
+   for (int i=0;i<5;i++) hdrbuf[i]=(unhamtab[buffer[2*i]]&0xF) | ((unhamtab[buffer[2*i+1]]&0xF)<< 4);
+   int header=hdrbuf[0];
+   int magazin=header & 0x7;
+   int line = (header>>3) & 0x1f;
+   if (magazin==0) magazin=8;
+   if (line==0)
+   {
+       if (ourpage) {
+           gotcha=true;
+           inkeying=false;
+           RenderTeletextCode(false);
+       } else {
+           RenderTeletextCode(true);
+       }
+       int pagenumber=hdrbuf[1];
+       int pagemagazin=magazin<<8 | pagenumber;
+       int pagesubnumber=(hdrbuf[2]) || ((hdrbuf[3]<<8) & 0x3f7f);
+
+       if (pagemagazin == selectedpage) ourpage=true;
+       else ourpage=false;
+       if (isrecording) {
+           for (int i=0;i<10;i++) {
+               if (pagemagazin==record_pages[i]) break;
+               if (record_pages[i]==-1) {
+                   record_pages[i]=pagemagazin;
+                   break;
+               }
+           }
+       }
+       if (hdrbuf[3] &0x80) { //This is a subtitle
+            for (int i=0;i<10;i++) {
+               if (pagemagazin==record_pages[i]) break;
+               if (record_pages[i]==-1) {
+                   record_pages[i]=pagemagazin;
+                   break;
+               }
+           }
+       }
+
+
+       if (ourpage) {
+           lang=((hdrbuf[4]>>5) & 0x07);
+           flags=hdrbuf[2] & 0x80;
+           flags|=(hdrbuf[3]&0x40)|((hdrbuf[3]>>2)&0x20); //??????
+           flags|=((hdrbuf[4]<<4)&0x10)|((hdrbuf[4]<<2)&0x08)|(hdrbuf[4]&0x04)|((hdrbuf[4]>>1)&0x02)|((hdrbuf[4]>>4)&0x01);
+           for (int i=0;i<25;i++) {
+               memset(curpage[i],0,40);
+            }
+       }
+       
+       memcpy(curpage[line],buffer+2,40);
+   } else if (ourpage && (line<=25)) {
+       memcpy(curpage[line],buffer+2,40);
+       
+   }
+}
+
+
+/* from osdteletext plugin: (slightly adapted for vomp)*/
+// Font tables
+
+// teletext uses 7-bit numbers to identify a font set.
+// There are three font sets involved:
+// Primary G0, Secondary G0, and G2 font set.
+
+// Font tables are organized in blocks of 8 fonts:
+
+enumCharsets FontBlockG0_0000[8] = {
+    CHARSET_LATIN_G0_EN,
+    CHARSET_LATIN_G0_DE,
+    CHARSET_LATIN_G0_SV_FI,
+    CHARSET_LATIN_G0_IT,
+    CHARSET_LATIN_G0_FR,
+    CHARSET_LATIN_G0_PT_ES,
+    CHARSET_LATIN_G0_CZ_SK,
+    CHARSET_LATIN_G0
+};
+
+enumCharsets FontBlockG2Latin[8]={
+    CHARSET_LATIN_G2,
+    CHARSET_LATIN_G2,
+    CHARSET_LATIN_G2,
+    CHARSET_LATIN_G2,
+    CHARSET_LATIN_G2,
+    CHARSET_LATIN_G2,
+    CHARSET_LATIN_G2,
+    CHARSET_LATIN_G2
+};
+
+enumCharsets FontBlockG0_0001[8] = {
+    CHARSET_LATIN_G0_PL,
+    CHARSET_LATIN_G0_DE,
+    CHARSET_LATIN_G0_SV_FI,
+    CHARSET_LATIN_G0_IT,
+    CHARSET_LATIN_G0_FR,
+    CHARSET_LATIN_G0,
+    CHARSET_LATIN_G0_CZ_SK,
+    CHARSET_LATIN_G0
+};
+
+enumCharsets FontBlockG0_0010[8] = {
+    CHARSET_LATIN_G0_EN,
+    CHARSET_LATIN_G0_DE,
+    CHARSET_LATIN_G0_SV_FI,
+    CHARSET_LATIN_G0_IT,
+    CHARSET_LATIN_G0_FR,
+    CHARSET_LATIN_G0_PT_ES,
+    CHARSET_LATIN_G0_TR,
+    CHARSET_LATIN_G0
+};
+
+
+enumCharsets FontBlockG0_0011[8] = {
+    CHARSET_LATIN_G0,
+    CHARSET_LATIN_G0,
+    CHARSET_LATIN_G0,
+    CHARSET_LATIN_G0,
+    CHARSET_LATIN_G0,
+    CHARSET_LATIN_G0_SR_HR_SL,
+    CHARSET_LATIN_G0,
+    CHARSET_LATIN_G0_RO
+};
+
+enumCharsets FontBlockG0_0100[8] = {
+    CHARSET_CYRILLIC_G0_SR_HR,
+    CHARSET_LATIN_G0_DE,
+    CHARSET_LATIN_G0_EE,
+    CHARSET_LATIN_G0_LV_LT,
+    CHARSET_CYRILLIC_G0_RU_BG,
+    CHARSET_CYRILLIC_G0_UK,
+    CHARSET_LATIN_G0_CZ_SK,
+    CHARSET_INVALID
+};
+
+enumCharsets FontBlockG2_0100[8] = {
+    CHARSET_CYRILLIC_G2,
+    CHARSET_LATIN_G2,
+    CHARSET_LATIN_G2,
+    CHARSET_LATIN_G2,
+    CHARSET_CYRILLIC_G2,
+    CHARSET_CYRILLIC_G2,
+    CHARSET_LATIN_G2,
+    CHARSET_INVALID
+};
+
+enumCharsets FontBlockG0_0110[8] = {
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_LATIN_G0_TR,
+    CHARSET_GREEK_G0
+};
+
+enumCharsets FontBlockG2_0110[8] = {
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_LATIN_G2,
+    CHARSET_GREEK_G2
+};
+
+enumCharsets FontBlockG0_1000[8] = {
+    CHARSET_LATIN_G0_EN,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_LATIN_G0_FR,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_ARABIC_G0
+};
+
+enumCharsets FontBlockG2_1000[8] = {
+    CHARSET_ARABIC_G2,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_ARABIC_G2,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_ARABIC_G2
+};
+
+enumCharsets FontBlockG0_1010[8] = {
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_HEBREW_G0,
+    CHARSET_INVALID,
+    CHARSET_ARABIC_G0,
+};
+
+enumCharsets FontBlockG2_1010[8] = {
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_ARABIC_G2,
+    CHARSET_INVALID,
+    CHARSET_ARABIC_G2,
+};
+
+enumCharsets FontBlockInvalid[8] = {
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID,
+    CHARSET_INVALID
+};
+
+
+
+// The actual font table definition:
+// Split the 7-bit number into upper 4 and lower 3 bits,
+// use upper 4 bits for outer array,
+// use lower 3 bits for inner array
+
+struct structFontBlock {
+    enumCharsets *G0Block;
+    enumCharsets *G2Block;
+};
+    
+structFontBlock FontTable[16] = {
+    { FontBlockG0_0000, FontBlockG2Latin }, // 0000 block
+    { FontBlockG0_0001, FontBlockG2Latin }, // 0001 block
+    { FontBlockG0_0010, FontBlockG2Latin }, // 0010 block
+    { FontBlockG0_0011, FontBlockG2Latin }, // 0011 block
+    { FontBlockG0_0100, FontBlockG2_0100 }, // 0100 block
+    { FontBlockInvalid, FontBlockInvalid }, // 0101 block
+    { FontBlockG0_0110, FontBlockG2_0110 }, // 0110 block
+    { FontBlockInvalid, FontBlockInvalid }, // 0111 block
+    { FontBlockG0_1000, FontBlockG2_1000 }, // 1000 block
+    { FontBlockInvalid, FontBlockInvalid }, // 1001 block
+    { FontBlockG0_1010, FontBlockG2_1010 }, // 1010 block
+    { FontBlockInvalid, FontBlockInvalid }, // 1011 block
+    { FontBlockInvalid, FontBlockInvalid }, // 1100 block
+    { FontBlockInvalid, FontBlockInvalid }, // 1101 block
+    { FontBlockInvalid, FontBlockInvalid }, // 1110 block
+    { FontBlockInvalid, FontBlockInvalid }  // 1111 block
+};
+
+inline enumCharsets GetG0Charset(int codepage) {
+    return FontTable[codepage>>3].G0Block[codepage&7];
+}
+inline enumCharsets GetG2Charset(int codepage) {
+    return FontTable[codepage>>3].G2Block[codepage&7];
+}
+
+enum enumSizeMode {
+    // Possible size modifications of characters
+    sizeNormal,
+    sizeDoubleWidth,
+    sizeDoubleHeight,
+    sizeDoubleSize
+};
+
+void TeletextDecoderVBIEBU::RenderTeletextCode(bool renderfirstlineonly) {
+    int x,y;
+    bool EmptyNextLine=false;
+    // Skip one line, in case double height chars were/will be used
+
+    // Get code pages:
+    int LocalG0CodePage=(FirstG0CodePage & 0x78) 
+            | ((lang & 0x04)>>2) | (lang & 0x02) | ((lang & 0x01)<<2);
+    enumCharsets FirstG0=GetG0Charset(LocalG0CodePage);
+    enumCharsets SecondG0=GetG0Charset(SecondG0CodePage);
+    // Reserved for later use:
+    // enumCharsets FirstG2=GetG2Charset(LocalG0CodePage);
+    
+    for (y=0;y<24;(EmptyNextLine?y+=2:y++)) {
+        // Start of line: Set start of line defaults
+        
+        // Hold Mosaics mode: Remember last mosaic char/charset 
+        // for next spacing code
+        bool HoldMosaics=false;
+        unsigned char HoldMosaicChar=' ';
+        enumCharsets HoldMosaicCharset=FirstG0;
+
+        enumSizeMode Size=sizeNormal;
+        // Font size modification
+        bool SecondCharset=false;
+        // Use primary or secondary G0 charset
+        bool GraphicCharset=false;
+        // Graphics charset used?
+        bool SeparateGraphics=false;
+        // Use separated vs. contiguous graphics charset
+        bool NoNextChar=false;
+        // Skip display of next char, for double-width
+        EmptyNextLine=false;
+        // Skip next line, for double-height
+
+        cTeletextChar c;
+        // auto.initialized to everything off
+        c.SetFGColor(ttcWhite);
+        c.SetBGColor(ttcBlack);
+        c.SetCharset(FirstG0);
+        
+        if (y==0 && (flags&0x10)) {
+            if (!inkeying ) c.SetBoxedOut(true);
+            
+        }
+        if (flags&0x60) {
+           if (!(inkeying && y==0) ) c.SetBoxedOut(true);
+            
+        }
+        if (y==0) {
+            
+            for (x=0;x<8;x++) {
+                cTeletextChar c2=c;
+               
+                if (x>=3 && x<6){
+                    c2.SetChar(keyindigits[x-3]);
+
+                }
+                else
+                    c2.SetChar(' ');
+                setChar(x,0,c2);
+            }
+        }
+
+        // Pre-scan for double-height and double-size codes
+        for (x=0;x<40;x++) {
+            if (y==0 && x<8) x=8;
+            if ((curpage[y][x] & 0x7f)==0x0D || (curpage[y][x] & 0x7f)==0x0F)
+                EmptyNextLine=true;
+        }
+
+        // Move through line
+        for (x=0;x<40;x++) {
+            unsigned char ttc=curpage[y][x] & 0x7f;
+            // skip parity check
+
+            if (y==0 && x<8) continue;
+            if (y==0 && x<31 && renderfirstlineonly && gotcha && !inkeying) continue;
+            // no displayable data here...
+            
+/*          // Debug only: Output line data and spacing codes
+            if (y==6) {
+                if (ttc<0x20)
+                    printf("%s ",names[ttc]);
+                else
+                    printf("%02x ",ttc);
+                if (x==39) printf("\n");
+            }
+*/          
+            
+            // Handle all 'Set-At' spacing codes
+            switch (ttc) {
+            case 0x09: // Steady
+                c.SetBlink(false);
+                break;
+            case 0x0C: // Normal Size
+                if (Size!=sizeNormal) {
+                    Size=sizeNormal;
+                    HoldMosaicChar=' ';
+                    HoldMosaicCharset=FirstG0;
+                }                   
+                break;
+            case 0x18: // Conceal
+                c.SetConceal(true);
+                break;
+            case 0x19: // Contiguous Mosaic Graphics
+                SeparateGraphics=false;
+                if (GraphicCharset)
+                    c.SetCharset(CHARSET_GRAPHICS_G1);
+                break;
+            case 0x1A: // Separated Mosaic Graphics
+                SeparateGraphics=true;
+                if (GraphicCharset)
+                    c.SetCharset(CHARSET_GRAPHICS_G1_SEP);
+                break;
+            case 0x1C: // Black Background
+                c.SetBGColor(ttcBlack);
+                break;
+            case 0x1D: // New Background
+                c.SetBGColor(c.GetFGColor());
+                break;
+            case 0x1E: // Hold Mosaic
+                HoldMosaics=true;               
+                break;
+            }
+
+            // temporary copy of character data:
+            cTeletextChar c2=c;
+            // c2 will be text character or space character or hold mosaic
+            // c2 may also have temporary flags or charsets
+            
+            if (ttc<0x20) {
+                // Spacing code, display space or hold mosaic
+                if (HoldMosaics) {
+                    c2.SetChar(HoldMosaicChar);
+                    c2.SetCharset(HoldMosaicCharset);
+                } else {
+                    c2.SetChar(' ');
+                }
+            } else {
+                // Character code               
+                c2.SetChar(ttc);
+                if (GraphicCharset) {
+                    if (ttc&0x20) {
+                        // real graphics code, remember for HoldMosaics
+                        HoldMosaicChar=ttc;
+                        HoldMosaicCharset=c.GetCharset();
+                    } else {
+                        // invalid code, pass-through to G0
+                        c2.SetCharset(SecondCharset?SecondG0:FirstG0);
+                    }   
+                }
+            }
+            
+            // Handle double-height and double-width extremes
+            if (y>=23) {
+                if (Size==sizeDoubleHeight) Size=sizeNormal;
+                if (Size==sizeDoubleSize) Size=sizeDoubleWidth;
+            }
+            if (x>=38) {
+                if (Size==sizeDoubleWidth) Size=sizeNormal;
+                if (Size==sizeDoubleSize) Size=sizeDoubleHeight;
+            }
+            
+            // Now set character code
+            
+            if (NoNextChar) {
+                // Suppress this char due to double width last char
+                NoNextChar=false;
+            } else {
+                switch (Size) {
+                case sizeNormal:
+                    // Normal sized
+                    setChar(x,y,c2);
+                    if (EmptyNextLine && y<23) {
+                        // Clean up next line
+                        setChar(x,y+1,c2.ToChar(' ').ToCharset(FirstG0));
+                    }
+                    break;
+                case sizeDoubleWidth:
+                    // Double width
+                    setChar(x,y,c2.ToDblWidth(dblw_Left));
+                    setChar(x+1,y,c2.ToDblWidth(dblw_Right));
+                    if (EmptyNextLine && y<23) {
+                        // Clean up next line
+                        setChar(x  ,y+1,c2.ToChar(' ').ToCharset(FirstG0));
+                        setChar(x+1,y+1,c2.ToChar(' ').ToCharset(FirstG0));
+                    }
+                    NoNextChar=true;
+                    break;
+                case sizeDoubleHeight:
+                    // Double height
+                    setChar(x,y,c2.ToDblHeight(dblh_Top));
+                    setChar(x,y+1,c2.ToDblHeight(dblh_Bottom));
+                    break;
+                case sizeDoubleSize:
+                    // Double Size
+                    setChar(x  ,  y,c2.ToDblHeight(dblh_Top   ).ToDblWidth(dblw_Left ));
+                    setChar(x+1,  y,c2.ToDblHeight(dblh_Top   ).ToDblWidth(dblw_Right));
+                    setChar(x  ,y+1,c2.ToDblHeight(dblh_Bottom).ToDblWidth(dblw_Left ));
+                    setChar(x+1,y+1,c2.ToDblHeight(dblh_Bottom).ToDblWidth(dblw_Right));
+                    NoNextChar=true;
+                    break;
+                }
+            }
+                
+            // Handle all 'Set-After' spacing codes
+             if (ttc>=0x00 &&  ttc<=0x07) { // Set FG color
+                if (GraphicCharset) {
+                    // Actual switch from graphics charset
+                    HoldMosaicChar=' ';
+                    HoldMosaicCharset=FirstG0;
+                }
+                c.SetFGColor((enumTeletextColor)ttc);
+                c.SetCharset(SecondCharset?SecondG0:FirstG0);
+                GraphicCharset=false;
+                c.SetConceal(false);
+             } else if (ttc==0x08) {
+                c.SetBlink(true);
+             } else if (ttc==0x0A) {
+                c.SetBoxedOut(true);
+             } else if (ttc==0x0B) {
+             // Start Box
+                c.SetBoxedOut(false);
+             } else if (ttc==0x0D) {
+                if (Size!=sizeDoubleHeight) {
+                    Size=sizeDoubleHeight;
+                    HoldMosaicChar=' ';
+                    HoldMosaicCharset=FirstG0;
+                }                   
+             } else if (ttc==0x0E) {
+                if (Size!=sizeDoubleWidth) {
+                    Size=sizeDoubleWidth;
+                    HoldMosaicChar=' ';
+                    HoldMosaicCharset=FirstG0;
+                }                   
+             } else if (ttc==0x0E) {
+                if (Size!=sizeDoubleSize) {
+                    Size=sizeDoubleSize;
+                    HoldMosaicChar=' ';
+                    HoldMosaicCharset=FirstG0;
+                }                   
+             } else  if (ttc>=0x10 && ttc<=0x17) { 
+                if (!GraphicCharset) {
+                    // Actual switch to graphics charset
+                    HoldMosaicChar=' ';
+                    HoldMosaicCharset=FirstG0;
+                }
+                c.SetFGColor((enumTeletextColor)(ttc-0x10));
+                c.SetCharset(SeparateGraphics?CHARSET_GRAPHICS_G1_SEP:CHARSET_GRAPHICS_G1);
+                GraphicCharset=true;
+                c.SetConceal(false);
+             } else if (ttc==0x1B) {
+                SecondCharset=!SecondCharset;
+                if (!GraphicCharset) c.SetCharset(SecondCharset?SecondG0:FirstG0);
+             } else if (ttc==0x1F) {
+                HoldMosaics=false;
+             }
+            
+        } // end for x
+        if (renderfirstlineonly) break;
+    } // end for y
+    
+    for (x=0;x<40;x++) {
+        // Clean out last line
+        cTeletextChar c;
+        c.SetFGColor(ttcWhite);
+        c.SetBGColor(ttcBlack);
+        c.SetCharset(FirstG0);
+        c.SetChar(' ');
+        if (flags&0x60) {
+            c.SetBoxedOut(true);    
+        }
+        setChar(x,24,c);
+    } 
+    for (y=0;y<25;y++) {
+        for (x=0;x<40;x++) {
+            if (isDirty(x,y)) {
+                dirty=true;
+                break;
+            }
+            if (dirty) break;
+        }
+        if (dirty) break;
+    }
+     
+    if (dirty && txtview!=NULL ) {
+        
+        if ( !renderfirstlineonly) {
+            Message* m= new Message();
+            m->message = Message::TELETEXTUPDATE;
+            m->to = txtview;
+            m->from = this;
+            m->parameter = 0;
+            Command::getInstance()->postMessageFromOuterSpace(m);
+        } else if (firstlineupdate==10) {
+            Message* m= new Message();
+            m->message = Message::TELETEXTUPDATEFIRSTLINE;
+            m->to = txtview;
+            m->from = this;
+            m->parameter = 0;
+            Command::getInstance()->postMessageFromOuterSpace(m);
+            firstlineupdate=0;
+        } else firstlineupdate++;
+        
+       
+    }
+        
+}
index 0566a404bc874225322600152df9172b1bd2c824..123486bc1edfd4fe9ebcfb741913d1767b3eed41 100644 (file)
-/*\r
-    Copyright 2008 Marten Richter\r
-\r
-    This file is part of VOMP.\r
-\r
-    VOMP is free software; you can redistribute it and/or modify\r
-    it under the terms of the GNU General Public License as published by\r
-    the Free Software Foundation; either version 2 of the License, or\r
-    (at your option) any later version.\r
-\r
-    VOMP is distributed in the hope that it will be useful,\r
-    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-    GNU General Public License for more details.\r
-\r
-    You should have received a copy of the GNU General Public License\r
-    along with VOMP; if not, write to the Free Software\r
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
-*/\r
-/* Portions from vdr osdteletext plugin "txtrender.c": */\r
-/***************************************************************************\r
- *                                                                         *\r
- *   txtrender.h - Teletext display abstraction and teletext code          *\r
- *                 renderer                                                *\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) any later version.                                   *\r
- *                                                                         *\r
- *   Changelog:                                                            *\r
- *     2005-03    initial version (c) Udo Richter                          *\r
- *                                                                         *\r
- ***************************************************************************/\r
-\r
-#ifndef TXTDECVBIEBU_H\r
-#define TXTDECVBIEBU_H\r
-\r
-#include "draintarget.h"\r
-#include "log.h"\r
-\r
-/* from osdteletext begin */\r
-\r
-// Teletext character sets\r
-enum enumCharsets {\r
-    CHARSET_LATIN_G0          = 0x0000, // native latin (partially todo)\r
-    CHARSET_LATIN_G0_CZ_SK    = 0x0100, // Czech/Slovak (todo)\r
-    CHARSET_LATIN_G0_EN       = 0x0200, // English\r
-    CHARSET_LATIN_G0_EE       = 0x0300, // Estonian (todo)\r
-    CHARSET_LATIN_G0_FR       = 0x0400, // French\r
-    CHARSET_LATIN_G0_DE       = 0x0500, // German\r
-    CHARSET_LATIN_G0_IT       = 0x0600, // Italian\r
-    CHARSET_LATIN_G0_LV_LT    = 0x0700, // Lettish/Lithuanian (todo)\r
-    CHARSET_LATIN_G0_PL       = 0x0800, // Polish (todo)\r
-    CHARSET_LATIN_G0_PT_ES    = 0x0900, // Portugese/Spanish\r
-    CHARSET_LATIN_G0_RO       = 0x0A00, // Romanian (todo)\r
-    CHARSET_LATIN_G0_SR_HR_SL = 0x0B00, // Serbian/Croatian/Slovenian (todo)\r
-    CHARSET_LATIN_G0_SV_FI    = 0x0C00, // Swedish/Finnish\r
-    CHARSET_LATIN_G0_TR       = 0x0D00, // Turkish (todo)\r
-    CHARSET_LATIN_G2          = 0x0E00, // Latin G2 supplementary set (todo)\r
-    CHARSET_CYRILLIC_G0_SR_HR = 0x0F00, // Serbian/Croatian (todo)\r
-    CHARSET_CYRILLIC_G0_RU_BG = 0x1000, // Russian/Bulgarian (todo)\r
-    CHARSET_CYRILLIC_G0_UK    = 0x1100, // Ukrainian (todo)\r
-    CHARSET_CYRILLIC_G2       = 0x1200, // Cyrillic G2 Supplementary (todo)\r
-    CHARSET_GREEK_G0          = 0x1300, // Greek G0 (todo)\r
-    CHARSET_GREEK_G2          = 0x1400, // Greeek G2 (todo)\r
-    CHARSET_ARABIC_G0         = 0x1500, // Arabic G0 (todo)\r
-    CHARSET_ARABIC_G2         = 0x1600, // Arabic G2 (todo)\r
-    CHARSET_HEBREW_G0         = 0x1700, // Hebrew G0 (todo)\r
-    CHARSET_GRAPHICS_G1       = 0x1800, // G1 graphics set\r
-    CHARSET_GRAPHICS_G1_SEP   = 0x1900, // G1 graphics set, separated\r
-    CHARSET_GRAPHICS_G3       = 0x1A00, // G3 graphics set (todo)\r
-    CHARSET_INVALID           = 0x1F00  // no charset defined\r
-};\r
-\r
-// Macro to get the lowest non-0 bit position from a bit mask\r
-// Should evaluate to const on a const mask\r
-#define LowestSet2Bit(mask) ((mask)&0x0001?0:1)\r
-#define LowestSet4Bit(mask) ((mask)&0x0003?LowestSet2Bit(mask):LowestSet2Bit((mask)>>2)+2)\r
-#define LowestSet8Bit(mask) ((mask)&0x000f?LowestSet4Bit(mask):LowestSet4Bit((mask)>>4)+4)\r
-#define LowestSet16Bit(mask) ((mask)&0x00ff?LowestSet8Bit(mask):LowestSet8Bit((mask)>>8)+8)\r
-#define LowestSet32Bit(mask) ((mask)&0xffff?LowestSet16Bit(mask):LowestSet16Bit((mask)>>16)+16)\r
-\r
-\r
-// Character modifcation double height:\r
-enum enumDblHeight {\r
-    dblh_Normal=0x00000000, // normal height\r
-    dblh_Top   =0x04000000, // upper half character\r
-    dblh_Bottom=0x08000000  // lower half character\r
-};\r
-// Character modifcation double width:\r
-enum enumDblWidth {\r
-    dblw_Normal=0x00000000, // normal width\r
-    dblw_Left  =0x10000000, // left half character\r
-    dblw_Right =0x20000000  // right half character\r
-};\r
-\r
-// Teletext colors\r
-enum enumTeletextColor {\r
-    // level 1:\r
-    ttcBlack=0,\r
-    ttcRed=1,\r
-    ttcGreen=2,\r
-    ttcYellow=3,\r
-    ttcBlue=4,\r
-    ttcMagenta=5,\r
-    ttcCyan=6,\r
-    ttcWhite=7,\r
-    // level 2.5:\r
-    ttcTransparent=8,\r
-    ttcHalfRed=9,\r
-    ttcHalfGreen=10,\r
-    ttcHalfYellow=11,\r
-    ttcHalfBlue=12,\r
-    ttcHalfMagenta=13,\r
-    ttcHalfCyan=14,\r
-    ttcGrey=15,\r
-    // unnamed, level 2.5:\r
-    ttcColor16=16, ttcColor17=17, ttcColor18=18, ttcColor19=19,\r
-    ttcColor20=20, ttcColor21=21, ttcColor22=22, ttcColor23=23,\r
-    ttcColor24=24, ttcColor25=25, ttcColor26=26, ttcColor27=27,\r
-    ttcColor28=28, ttcColor29=29, ttcColor30=30, ttcColor31=31,\r
-    \r
-    ttcFirst=0, ttcLast=31\r
-};\r
-inline enumTeletextColor& operator++(enumTeletextColor& c) { return c=enumTeletextColor(int(c)+1); }\r
-inline enumTeletextColor operator++(enumTeletextColor& c, int) { enumTeletextColor tmp(c); ++c; return tmp; }\r
-    \r
-class cTeletextChar {\r
-    // Wrapper class that represents a teletext character,\r
-    // including colors and effects. Should optimize back\r
-    // to 4 byte unsigned int on compile.\r
-    \r
-protected:\r
-    unsigned int c;\r
-\r
-    static const unsigned int CHAR             = 0x000000FF;\r
-    // character code\r
-    static const unsigned int CHARSET          = 0x00001F00;\r
-    // character set code, see below\r
-    static const unsigned int BOXOUT           = 0x00004000;\r
-    // 'boxed' mode hidden area\r
-    static const unsigned int DIRTY            = 0x00008000;\r
-    // 'dirty' bit - internal marker only\r
-    static const unsigned int FGCOLOR          = 0x001F0000;\r
-    // 5-bit foreground color code, 3 bit used for now\r
-    static const unsigned int BGCOLOR          = 0x03E00000;\r
-    // 5-bit background color code, 3 bit used for now\r
-    static const unsigned int DBLHEIGHT        = 0x0C000000;\r
-    // show double height\r
-    static const unsigned int DBLWIDTH         = 0x30000000;\r
-    // show double width (todo)\r
-    static const unsigned int CONCEAL          = 0x40000000;\r
-    // character concealed\r
-    static const unsigned int BLINK            = 0x80000000;\r
-    // blinking character\r
-\r
-    cTeletextChar(unsigned int cc) { c=cc; }\r
-\r
-public:\r
-    cTeletextChar() { c=0; }\r
-    \r
-    // inline helper functions:\r
-    // For each parameter encoded into the 32-bit int, there is\r
-    // a Get...() to read, a Set...() to write, and a To...() to\r
-    // return a modified copy\r
-    \r
-    inline unsigned char GetChar() \r
-        { return c&CHAR; }\r
-    inline void SetChar(unsigned char chr)\r
-        { c=(c&~CHAR)|chr; }\r
-    inline cTeletextChar ToChar(unsigned char chr)\r
-        { return cTeletextChar((c&~CHAR)|chr); }\r
-        \r
-    inline enumCharsets GetCharset() \r
-        { return (enumCharsets)(c&CHARSET); }\r
-    inline void SetCharset(enumCharsets charset) \r
-        { c=(c&~CHARSET)|charset; }\r
-    inline cTeletextChar ToCharset(enumCharsets charset) \r
-        { return cTeletextChar((c&~CHARSET)|charset); }\r
-    \r
-    inline enumTeletextColor GetFGColor() \r
-        { return (enumTeletextColor)((c&FGCOLOR) >> LowestSet32Bit(FGCOLOR)); }\r
-    inline void SetFGColor(enumTeletextColor fgc) \r
-        { c=(c&~FGCOLOR) | (fgc << LowestSet32Bit(FGCOLOR)); }\r
-    inline cTeletextChar ToFGColor(enumTeletextColor fgc) \r
-        { return cTeletextChar((c&~FGCOLOR) | (fgc << LowestSet32Bit(FGCOLOR))); }\r
-    \r
-    inline enumTeletextColor GetBGColor() \r
-        { return (enumTeletextColor)((c&BGCOLOR) >> LowestSet32Bit(BGCOLOR)); }\r
-    inline void SetBGColor(enumTeletextColor bgc) \r
-        { c=(c&~BGCOLOR) | (bgc << LowestSet32Bit(BGCOLOR)); }\r
-    inline cTeletextChar ToBGColor(enumTeletextColor bgc) \r
-        { return cTeletextChar((c&~BGCOLOR) | (bgc << LowestSet32Bit(BGCOLOR))); }\r
-    \r
-    inline bool GetBoxedOut() \r
-        { return c&BOXOUT; }\r
-    inline void SetBoxedOut(bool BoxedOut) \r
-        { c=(BoxedOut)?(c|BOXOUT):(c&~BOXOUT); }\r
-    inline cTeletextChar ToBoxedOut(bool BoxedOut) \r
-        { return cTeletextChar((BoxedOut)?(c|BOXOUT):(c&~BOXOUT)); }\r
-    \r
-    inline bool GetDirty() \r
-        { return c&DIRTY; }\r
-    inline void SetDirty(bool Dirty) \r
-        { c=(Dirty)?(c|DIRTY):(c&~DIRTY); }\r
-    inline cTeletextChar ToDirty(bool Dirty) \r
-        { return cTeletextChar((Dirty)?(c|DIRTY):(c&~DIRTY)); }\r
-    \r
-    inline enumDblHeight GetDblHeight() \r
-        { return (enumDblHeight)(c&DBLHEIGHT); }\r
-    inline void SetDblHeight(enumDblHeight dh) \r
-        { c=(c&~(DBLHEIGHT)) | dh; }\r
-    inline cTeletextChar ToDblHeight(enumDblHeight dh) \r
-        { return cTeletextChar((c&~(DBLHEIGHT)) | dh); }\r
-    \r
-    inline enumDblWidth GetDblWidth() \r
-        { return (enumDblWidth)(c&DBLWIDTH); }\r
-    inline void SetDblWidth(enumDblWidth dw) \r
-        { c=(c&~(DBLWIDTH)) | dw; }\r
-    inline cTeletextChar ToDblWidth(enumDblWidth dw) \r
-        { return cTeletextChar((c&~(DBLWIDTH)) | dw); }\r
-    \r
-    inline bool GetConceal() \r
-        { return c&CONCEAL; }\r
-    inline void SetConceal(bool Conceal) \r
-        { c=(Conceal)?(c|CONCEAL):(c&~CONCEAL); }\r
-    inline cTeletextChar ToConceal(bool Conceal) \r
-        { return cTeletextChar((Conceal)?(c|CONCEAL):(c&~CONCEAL)); }\r
-    \r
-    inline bool GetBlink() \r
-        { return c&BLINK; }\r
-    inline void SetBlink(bool Blink) \r
-        { c=(Blink)?(c|BLINK):(c&~BLINK); }\r
-    inline cTeletextChar ToBlink(bool Blink) \r
-        { return cTeletextChar((Blink)?(c|BLINK):(c&~BLINK)); }\r
-        \r
-    bool operator==(cTeletextChar &chr) { return c==chr.c; }\r
-    bool operator!=(cTeletextChar &chr) { return c!=chr.c; }\r
-};\r
-/* from osdteletext end*/\r
-\r
-class VTeletextView;\r
-\r
-/* Decoder of teletext matrial present in Data stream for VBI reinsertion more or less according to EBU specs*/ \r
-class TeletextDecoderVBIEBU: public DrainTarget {\r
-public:\r
-    TeletextDecoderVBIEBU();\r
-    virtual ~TeletextDecoderVBIEBU();\r
-\r
-    virtual long long SetStartOffset(long long curreftime, bool *rsync);\r
-    virtual void ResetTimeOffsets();\r
-\r
-    void ResetDecoder();\r
-    void setKeyinDigits(char digits[3],bool inKeying);\r
-    void setPage(unsigned int newpage);\r
-    int getPage() {return selectedpage;};\r
-    void setRecordigMode(bool isrecord) {isrecording=isrecord;};\r
-    int *getSubtitlePages() {return record_pages;};\r
-\r
-\r
-    virtual void PrepareMediaSample(const MediaPacketList& mplist, UINT samplepos);\r
-    virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos);\r
-\r
-    void registerTeletextView(VTeletextView* view) {txtview=view;};\r
-    void unRegisterTeletextView(VTeletextView* view) {if (txtview==view) txtview=NULL;};\r
-    VTeletextView* getTeletxtView() {return txtview;};\r
-\r
-    cTeletextChar getChar(int x, int y) {\r
-        // Read character content from page\r
-        if (x<0 || x>=40 || y<0 || y>=25) {\r
-            Log::getInstance()->log("TeletextDecoderVBIEBU", Log::DEBUG, "Warning: out of bounds read access to teletext page");\r
-            return cTeletextChar();\r
-        }\r
-        return Page[x][y].ToDirty(false);\r
-    }\r
-    bool isDirty(int x, int y) {\r
-        if (x<0 || x>=40 || y<0 || y>=25) {\r
-            Log::getInstance()->log("TeletextDecoderVBIEBU", Log::DEBUG, "Warning: out of bounds dirty access to teletext page");\r
-            return false;\r
-        }\r
-        return Page[x][y].GetDirty();\r
-    }\r
-    void setChar(int x, int y, cTeletextChar c) {\r
-        // Set character at given location\r
-        \r
-        if (x<0 || x>=40 || y<0 || y>=25) {\r
-            Log::getInstance()->log("TeletextDecoderVBIEBU", Log::DEBUG, "Warning: out of bounds write access to teletext page");\r
-            return;\r
-        }\r
-        if (getChar(x,y) != c) {\r
-            Page[x][y]=c.ToDirty(true);\r
-            dirty=true; \r
-        }           \r
-    }\r
-\r
-\r
-protected:\r
-    void DecodeTeletext(const UCHAR* buffer, unsigned int field);\r
-    void RenderTeletextCode(bool renderfirstlineonly);\r
-    void CleanPage();\r
-\r
-    int selectedpage;\r
-    int lang;\r
-    int flags;\r
-    UCHAR curpage[25][40]; //Line DataCache\r
-    cTeletextChar Page[40][25];\r
-    char keyindigits[3];\r
-\r
-\r
-    // Font Code pages\r
-    int FirstG0CodePage;  // 7-bit number, lower 3 bits ignored\r
-    int SecondG0CodePage; // 7-bit number\r
\r
-    bool ourpage;\r
-    bool dirty;\r
-    bool gotcha;\r
-    bool inkeying;\r
-    bool isrecording;\r
-    int record_pages[10];//Only 10 Pages per record;\r
-    unsigned int firstlineupdate;\r
-    VTeletextView *txtview;\r
-private:\r
-    MediaPacket mediapacket;\r
-    \r
-    \r
-\r
-};\r
-\r
-#endif\r
+/*
+    Copyright 2008 Marten Richter
+
+    This file is part of VOMP.
+
+    VOMP 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.
+
+    VOMP 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 VOMP; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+/* Portions from vdr osdteletext plugin "txtrender.c": */
+/***************************************************************************
+ *                                                                         *
+ *   txtrender.h - Teletext display abstraction and teletext code          *
+ *                 renderer                                                *
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ *   Changelog:                                                            *
+ *     2005-03    initial version (c) Udo Richter                          *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef TXTDECVBIEBU_H
+#define TXTDECVBIEBU_H
+
+#include "draintarget.h"
+#include "log.h"
+
+/* from osdteletext begin */
+
+// Teletext character sets
+enum enumCharsets {
+    CHARSET_LATIN_G0          = 0x0000, // native latin (partially todo)
+    CHARSET_LATIN_G0_CZ_SK    = 0x0100, // Czech/Slovak (todo)
+    CHARSET_LATIN_G0_EN       = 0x0200, // English
+    CHARSET_LATIN_G0_EE       = 0x0300, // Estonian (todo)
+    CHARSET_LATIN_G0_FR       = 0x0400, // French
+    CHARSET_LATIN_G0_DE       = 0x0500, // German
+    CHARSET_LATIN_G0_IT       = 0x0600, // Italian
+    CHARSET_LATIN_G0_LV_LT    = 0x0700, // Lettish/Lithuanian (todo)
+    CHARSET_LATIN_G0_PL       = 0x0800, // Polish (todo)
+    CHARSET_LATIN_G0_PT_ES    = 0x0900, // Portugese/Spanish
+    CHARSET_LATIN_G0_RO       = 0x0A00, // Romanian (todo)
+    CHARSET_LATIN_G0_SR_HR_SL = 0x0B00, // Serbian/Croatian/Slovenian (todo)
+    CHARSET_LATIN_G0_SV_FI    = 0x0C00, // Swedish/Finnish
+    CHARSET_LATIN_G0_TR       = 0x0D00, // Turkish (todo)
+    CHARSET_LATIN_G2          = 0x0E00, // Latin G2 supplementary set (todo)
+    CHARSET_CYRILLIC_G0_SR_HR = 0x0F00, // Serbian/Croatian (todo)
+    CHARSET_CYRILLIC_G0_RU_BG = 0x1000, // Russian/Bulgarian (todo)
+    CHARSET_CYRILLIC_G0_UK    = 0x1100, // Ukrainian (todo)
+    CHARSET_CYRILLIC_G2       = 0x1200, // Cyrillic G2 Supplementary (todo)
+    CHARSET_GREEK_G0          = 0x1300, // Greek G0 (todo)
+    CHARSET_GREEK_G2          = 0x1400, // Greeek G2 (todo)
+    CHARSET_ARABIC_G0         = 0x1500, // Arabic G0 (todo)
+    CHARSET_ARABIC_G2         = 0x1600, // Arabic G2 (todo)
+    CHARSET_HEBREW_G0         = 0x1700, // Hebrew G0 (todo)
+    CHARSET_GRAPHICS_G1       = 0x1800, // G1 graphics set
+    CHARSET_GRAPHICS_G1_SEP   = 0x1900, // G1 graphics set, separated
+    CHARSET_GRAPHICS_G3       = 0x1A00, // G3 graphics set (todo)
+    CHARSET_INVALID           = 0x1F00  // no charset defined
+};
+
+// Macro to get the lowest non-0 bit position from a bit mask
+// Should evaluate to const on a const mask
+#define LowestSet2Bit(mask) ((mask)&0x0001?0:1)
+#define LowestSet4Bit(mask) ((mask)&0x0003?LowestSet2Bit(mask):LowestSet2Bit((mask)>>2)+2)
+#define LowestSet8Bit(mask) ((mask)&0x000f?LowestSet4Bit(mask):LowestSet4Bit((mask)>>4)+4)
+#define LowestSet16Bit(mask) ((mask)&0x00ff?LowestSet8Bit(mask):LowestSet8Bit((mask)>>8)+8)
+#define LowestSet32Bit(mask) ((mask)&0xffff?LowestSet16Bit(mask):LowestSet16Bit((mask)>>16)+16)
+
+
+// Character modifcation double height:
+enum enumDblHeight {
+    dblh_Normal=0x00000000, // normal height
+    dblh_Top   =0x04000000, // upper half character
+    dblh_Bottom=0x08000000  // lower half character
+};
+// Character modifcation double width:
+enum enumDblWidth {
+    dblw_Normal=0x00000000, // normal width
+    dblw_Left  =0x10000000, // left half character
+    dblw_Right =0x20000000  // right half character
+};
+
+// Teletext colors
+enum enumTeletextColor {
+    // level 1:
+    ttcBlack=0,
+    ttcRed=1,
+    ttcGreen=2,
+    ttcYellow=3,
+    ttcBlue=4,
+    ttcMagenta=5,
+    ttcCyan=6,
+    ttcWhite=7,
+    // level 2.5:
+    ttcTransparent=8,
+    ttcHalfRed=9,
+    ttcHalfGreen=10,
+    ttcHalfYellow=11,
+    ttcHalfBlue=12,
+    ttcHalfMagenta=13,
+    ttcHalfCyan=14,
+    ttcGrey=15,
+    // unnamed, level 2.5:
+    ttcColor16=16, ttcColor17=17, ttcColor18=18, ttcColor19=19,
+    ttcColor20=20, ttcColor21=21, ttcColor22=22, ttcColor23=23,
+    ttcColor24=24, ttcColor25=25, ttcColor26=26, ttcColor27=27,
+    ttcColor28=28, ttcColor29=29, ttcColor30=30, ttcColor31=31,
+    
+    ttcFirst=0, ttcLast=31
+};
+inline enumTeletextColor& operator++(enumTeletextColor& c) { return c=enumTeletextColor(int(c)+1); }
+inline enumTeletextColor operator++(enumTeletextColor& c, int) { enumTeletextColor tmp(c); ++c; return tmp; }
+    
+class cTeletextChar {
+    // Wrapper class that represents a teletext character,
+    // including colors and effects. Should optimize back
+    // to 4 byte unsigned int on compile.
+    
+protected:
+    unsigned int c;
+
+    static const unsigned int CHAR             = 0x000000FF;
+    // character code
+    static const unsigned int CHARSET          = 0x00001F00;
+    // character set code, see below
+    static const unsigned int BOXOUT           = 0x00004000;
+    // 'boxed' mode hidden area
+    static const unsigned int DIRTY            = 0x00008000;
+    // 'dirty' bit - internal marker only
+    static const unsigned int FGCOLOR          = 0x001F0000;
+    // 5-bit foreground color code, 3 bit used for now
+    static const unsigned int BGCOLOR          = 0x03E00000;
+    // 5-bit background color code, 3 bit used for now
+    static const unsigned int DBLHEIGHT        = 0x0C000000;
+    // show double height
+    static const unsigned int DBLWIDTH         = 0x30000000;
+    // show double width (todo)
+    static const unsigned int CONCEAL          = 0x40000000;
+    // character concealed
+    static const unsigned int BLINK            = 0x80000000;
+    // blinking character
+
+    cTeletextChar(unsigned int cc) { c=cc; }
+
+public:
+    cTeletextChar() { c=0; }
+    
+    // inline helper functions:
+    // For each parameter encoded into the 32-bit int, there is
+    // a Get...() to read, a Set...() to write, and a To...() to
+    // return a modified copy
+    
+    inline unsigned char GetChar() 
+        { return c&CHAR; }
+    inline void SetChar(unsigned char chr)
+        { c=(c&~CHAR)|chr; }
+    inline cTeletextChar ToChar(unsigned char chr)
+        { return cTeletextChar((c&~CHAR)|chr); }
+        
+    inline enumCharsets GetCharset() 
+        { return (enumCharsets)(c&CHARSET); }
+    inline void SetCharset(enumCharsets charset) 
+        { c=(c&~CHARSET)|charset; }
+    inline cTeletextChar ToCharset(enumCharsets charset) 
+        { return cTeletextChar((c&~CHARSET)|charset); }
+    
+    inline enumTeletextColor GetFGColor() 
+        { return (enumTeletextColor)((c&FGCOLOR) >> LowestSet32Bit(FGCOLOR)); }
+    inline void SetFGColor(enumTeletextColor fgc) 
+        { c=(c&~FGCOLOR) | (fgc << LowestSet32Bit(FGCOLOR)); }
+    inline cTeletextChar ToFGColor(enumTeletextColor fgc) 
+        { return cTeletextChar((c&~FGCOLOR) | (fgc << LowestSet32Bit(FGCOLOR))); }
+    
+    inline enumTeletextColor GetBGColor() 
+        { return (enumTeletextColor)((c&BGCOLOR) >> LowestSet32Bit(BGCOLOR)); }
+    inline void SetBGColor(enumTeletextColor bgc) 
+        { c=(c&~BGCOLOR) | (bgc << LowestSet32Bit(BGCOLOR)); }
+    inline cTeletextChar ToBGColor(enumTeletextColor bgc) 
+        { return cTeletextChar((c&~BGCOLOR) | (bgc << LowestSet32Bit(BGCOLOR))); }
+    
+    inline bool GetBoxedOut() 
+        { return c&BOXOUT; }
+    inline void SetBoxedOut(bool BoxedOut) 
+        { c=(BoxedOut)?(c|BOXOUT):(c&~BOXOUT); }
+    inline cTeletextChar ToBoxedOut(bool BoxedOut) 
+        { return cTeletextChar((BoxedOut)?(c|BOXOUT):(c&~BOXOUT)); }
+    
+    inline bool GetDirty() 
+        { return c&DIRTY; }
+    inline void SetDirty(bool Dirty) 
+        { c=(Dirty)?(c|DIRTY):(c&~DIRTY); }
+    inline cTeletextChar ToDirty(bool Dirty) 
+        { return cTeletextChar((Dirty)?(c|DIRTY):(c&~DIRTY)); }
+    
+    inline enumDblHeight GetDblHeight() 
+        { return (enumDblHeight)(c&DBLHEIGHT); }
+    inline void SetDblHeight(enumDblHeight dh) 
+        { c=(c&~(DBLHEIGHT)) | dh; }
+    inline cTeletextChar ToDblHeight(enumDblHeight dh) 
+        { return cTeletextChar((c&~(DBLHEIGHT)) | dh); }
+    
+    inline enumDblWidth GetDblWidth() 
+        { return (enumDblWidth)(c&DBLWIDTH); }
+    inline void SetDblWidth(enumDblWidth dw) 
+        { c=(c&~(DBLWIDTH)) | dw; }
+    inline cTeletextChar ToDblWidth(enumDblWidth dw) 
+        { return cTeletextChar((c&~(DBLWIDTH)) | dw); }
+    
+    inline bool GetConceal() 
+        { return c&CONCEAL; }
+    inline void SetConceal(bool Conceal) 
+        { c=(Conceal)?(c|CONCEAL):(c&~CONCEAL); }
+    inline cTeletextChar ToConceal(bool Conceal) 
+        { return cTeletextChar((Conceal)?(c|CONCEAL):(c&~CONCEAL)); }
+    
+    inline bool GetBlink() 
+        { return c&BLINK; }
+    inline void SetBlink(bool Blink) 
+        { c=(Blink)?(c|BLINK):(c&~BLINK); }
+    inline cTeletextChar ToBlink(bool Blink) 
+        { return cTeletextChar((Blink)?(c|BLINK):(c&~BLINK)); }
+        
+    bool operator==(cTeletextChar &chr) { return c==chr.c; }
+    bool operator!=(cTeletextChar &chr) { return c!=chr.c; }
+};
+/* from osdteletext end*/
+
+class VTeletextView;
+
+/* Decoder of teletext matrial present in Data stream for VBI reinsertion more or less according to EBU specs*/ 
+class TeletextDecoderVBIEBU: public DrainTarget {
+public:
+    TeletextDecoderVBIEBU();
+    virtual ~TeletextDecoderVBIEBU();
+
+    virtual long long SetStartOffset(long long curreftime, bool *rsync);
+    virtual void ResetTimeOffsets();
+
+    void ResetDecoder();
+    void setKeyinDigits(char digits[3],bool inKeying);
+    void setPage(unsigned int newpage);
+    int getPage() {return selectedpage;};
+    void setRecordigMode(bool isrecord) {isrecording=isrecord;};
+    int *getSubtitlePages() {return record_pages;};
+
+
+    virtual void PrepareMediaSample(const MediaPacketList& mplist, UINT samplepos);
+    virtual UINT DeliverMediaSample(UCHAR* buffer, UINT *samplepos);
+
+    void registerTeletextView(VTeletextView* view) {txtview=view;};
+    void unRegisterTeletextView(VTeletextView* view) {if (txtview==view) txtview=NULL;};
+    VTeletextView* getTeletxtView() {return txtview;};
+
+    cTeletextChar getChar(int x, int y) {
+        // Read character content from page
+        if (x<0 || x>=40 || y<0 || y>=25) {
+            Log::getInstance()->log("TeletextDecoderVBIEBU", Log::DEBUG, "Warning: out of bounds read access to teletext page");
+            return cTeletextChar();
+        }
+        return Page[x][y].ToDirty(false);
+    }
+    bool isDirty(int x, int y) {
+        if (x<0 || x>=40 || y<0 || y>=25) {
+            Log::getInstance()->log("TeletextDecoderVBIEBU", Log::DEBUG, "Warning: out of bounds dirty access to teletext page");
+            return false;
+        }
+        return Page[x][y].GetDirty();
+    }
+    void setChar(int x, int y, cTeletextChar c) {
+        // Set character at given location
+        
+        if (x<0 || x>=40 || y<0 || y>=25) {
+            Log::getInstance()->log("TeletextDecoderVBIEBU", Log::DEBUG, "Warning: out of bounds write access to teletext page");
+            return;
+        }
+        if (getChar(x,y) != c) {
+            Page[x][y]=c.ToDirty(true);
+            dirty=true; 
+        }           
+    }
+
+
+protected:
+    void DecodeTeletext(const UCHAR* buffer, unsigned int field);
+    void RenderTeletextCode(bool renderfirstlineonly);
+    void CleanPage();
+
+    int selectedpage;
+    int lang;
+    int flags;
+    UCHAR curpage[25][40]; //Line DataCache
+    cTeletextChar Page[40][25];
+    char keyindigits[3];
+
+
+    // Font Code pages
+    int FirstG0CodePage;  // 7-bit number, lower 3 bits ignored
+    int SecondG0CodePage; // 7-bit number
+    bool ourpage;
+    bool dirty;
+    bool gotcha;
+    bool inkeying;
+    bool isrecording;
+    int record_pages[10];//Only 10 Pages per record;
+    unsigned int firstlineupdate;
+    VTeletextView *txtview;
+private:
+    MediaPacket mediapacket;
+    
+    
+
+};
+
+#endif
index 6347adc2502ecb48e3d53c2c3013ad4315ff9756..4908b4f4aca7c5224a469066ac9b9633b4f601b4 100644 (file)
@@ -527,6 +527,7 @@ int VAudioSelector::handleCommand(int command)
       return 2;
     }
     case Remote::LEFT:
+    case Remote::DF_LEFT:
      {
         if (editsubtitles && subtitles) {
             ssl.setDarkSelOption(true);
@@ -539,6 +540,7 @@ int VAudioSelector::handleCommand(int command)
         return 2;
      }
      case Remote::RIGHT:
+     case Remote::DF_RIGHT:
      {
          if (!editsubtitles && subtitles) {
              ssl.setDarkSelOption(false);
index f173d226350c4f8f59df4ad0243e43f67021c606..bba1e1e75348f784631a48970697585a053e4611 100644 (file)
@@ -169,7 +169,9 @@ int VColourTuner::handleCommand(int command)
       vgfactor=gfactor;
       vbfactor=bfactor;
 #ifndef WIN32
+#ifndef _MIPS_ARCH
     ((Surface_TYPE *)surface)->initConversionTables(vrfactor,vgfactor,vbfactor);
+#endif
 #endif
       rt=4;
       break;
@@ -185,7 +187,9 @@ int VColourTuner::handleCommand(int command)
   }
   if (rt == 2) {
 #ifndef WIN32
+#ifndef _MIPS_ARCH
     ((Surface_TYPE *)surface)->initConversionTables(vrfactor,vgfactor,vbfactor);
+#endif
 #endif
     bool updateAll=drawPicture;
     draw();
@@ -272,6 +276,8 @@ void VColourTuner::initFactors(){
   bfactor=bf;
   Log::getInstance()->log("VColourTuner",Log::DEBUG,"setting initial factors r=%d,g=%d,b=%d",rf,gf,bf);
 #ifndef WIN32
+#ifndef _MIPS_ARCH
   Surface_TYPE::initConversionTables(rfactor,gfactor,bfactor);
 #endif
+#endif
 }
diff --git a/vdr.cc b/vdr.cc
index c28d41ea2164f8408fc96e32088f3cde1af6310d..3073697872d1dba5dc57d51664d040a4352149d2 100644 (file)
--- a/vdr.cc
+++ b/vdr.cc
@@ -35,6 +35,7 @@
 #include "mediaprovider.h"
 #include "mediaproviderids.h"
 #include "vdrcommand.h"
+#include "video.h"
 
 VDR* VDR::instance = NULL;
 //prepare a request
@@ -628,12 +629,16 @@ bool VDR::networkLog(const char* logString)
   if (!connected) return false;
   int stringLength = strlen(logString);
   int packetLength = stringLength + 8;
-  char buffer[packetLength + 1];
+  char *buffer=new char[packetLength + 1];
   *(ULONG*)&buffer[0] = htonl(CHANNEL_NETLOG);
   *(ULONG*)&buffer[4] = htonl(stringLength);
   strcpy(&buffer[8], logString);
-
-  if ((ULONG)tcp->sendData(buffer, packetLength) != packetLength) return false;
+  
+  if ((ULONG)tcp->sendData(buffer, packetLength) != packetLength) {
+         delete [] buffer;
+         return false;
+  }
+  delete [] buffer;
   return true;
 }
 
@@ -718,14 +723,17 @@ ChannelList* VDR::getChannelsList(ULONG type)
   
   ChannelList* chanList = new ChannelList();
 
+  bool h264support=Video::getInstance()->supportsh264();
+
   while (!vresp->end())
   {
     Channel* chan = new Channel();
     chan->number = vresp->extractULONG();
     chan->type = vresp->extractULONG();
     chan->name = vresp->extractString();
+    chan->vstreamtype = vresp->extractULONG();
 
-    if (chan->type == type)
+    if (chan->type == type && (chan->vstreamtype!=0x1b || h264support))
     {
       chanList->push_back(chan);
       logger->log("VDR", Log::DEBUG, "Have added a channel to list. %lu %lu %s", chan->number, chan->type, chan->name);
@@ -1095,6 +1103,8 @@ RecInfo* VDR::getRecInfo(char* fileName)
       recInfo->descriptions[i] = vresp->extractString();
     }
   }
+  recInfo->fps=vresp->extractdouble();
+  
 
   recInfo->print();
 
@@ -1170,6 +1180,7 @@ void VDR::getChannelPids(Channel* channel)
   // }
 
   channel->vpid = vresp->extractULONG();
+  channel->vstreamtype = vresp->extractULONG();
   channel->numAPids = vresp->extractULONG();
 
   for (ULONG i = 0; i < channel->numAPids; i++)
index c7a077e6e33b7046dc4edec417a9a2d1cb8ec7f3..7d156c0f8d186d88a4a873d5b7dc5c855e3c77ab 100644 (file)
@@ -114,6 +114,16 @@ ULLONG VDR_ResponsePacket::extractULLONG()
   return ull;
 }
 
+double VDR_ResponsePacket::extractdouble()
+{
+  if ((packetPos + sizeof(ULLONG)) > userDataLength) return 0;
+  ULLONG ull = ntohll(*(ULLONG*)&userData[packetPos]);
+  double d;
+  memcpy(&d,&ull,sizeof(double));
+  packetPos += sizeof(ULLONG);
+  return d;
+}
+
 long VDR_ResponsePacket::extractLONG()
 {
   if ((packetPos + sizeof(long)) > userDataLength) return 0;
index 3d8d5f35a874205fe5e8746e1afc0c78af12e417..0d60be0e3bc71387b407fe1428dc7f4a1fef6a0f 100644 (file)
@@ -55,6 +55,7 @@ class VDR_ResponsePacket
     ULONG  extractULONG();
     ULLONG extractULLONG();
     long   extractLONG();
+       double extractdouble();
 
     bool end();
 
index b351cf8f7c74d50954c791a6f4a2569dd8c6b095..f15d7139b429c98f94303c4e66606343aac91271 100644 (file)
--- a/vfeed.cc
+++ b/vfeed.cc
@@ -74,8 +74,8 @@ void VFeed::threadMethod()
     }
     else
     {
-//      Log::getInstance()->log("VFeed", Log::DEBUG, "No data delay");
-      MILLISLEEP(20);
+      //Log::getInstance()->log("VFeed", Log::DEBUG, "No data delay");
+      MILLISLEEP(5);
     }
   }
 }
index 0a1388cddceb30b742fb62ff2002f3c7aee24031..1d6254d7ea563707337e77b5c295c82245524803 100644 (file)
--- a/video.cc
+++ b/video.cc
@@ -17,6 +17,7 @@
     along with VOMP; if not, write to the Free Software
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
+//portions from vdr by Klaus Schmiding HSMF code
 
 #include "video.h"
 
@@ -50,11 +51,19 @@ Video* Video::getInstance()
   return instance;
 }
 
-hmsf Video::framesToHMSF(ULONG frames)
+/*
+hmsf Video::framesToHMSF(ULONG frames, double fps)
 {
   hmsf ret;
+  / * from vdr *
+  double Seconds;
+  ret.frames= int(modf((frames + 0.5) / fps, &Seconds) * fps + 1);
+  int s = int(Seconds);
+  ret.seconds=s;
+  ret.minutes = s / 60 % 60;
+  ret.hours = s / 3600;
 
-  if (format == NTSC)
+/ *  if (format == NTSC)
   {
     ret.hours = frames / 108000;
     frames %= 108000;
@@ -71,12 +80,14 @@ hmsf Video::framesToHMSF(ULONG frames)
     frames %= 1500;
     ret.seconds = frames / 25;
     ret.frames = frames % 25;
-  }
+  }* /
   return ret;
-}
+}*/
 
+/*
 UINT Video::getFPS()
 {
   if (format == NTSC) return 30;
   else return 25;
 }
+*/
diff --git a/video.h b/video.h
index 2429583b23d70a06fbcacb3cacfd6e691742d543..502a1bafa7d8fb14160b1602eafdc239e96e77c8 100644 (file)
--- a/video.h
+++ b/video.h
@@ -63,13 +63,16 @@ class Video: public DrainTarget, public AbstractOption
     virtual int signalOn()=0;
     virtual int signalOff()=0;
     virtual int attachFrameBuffer()=0; // What does this do?
-    virtual ULONG timecodeToFrameNumber(ULLONG timecode)=0;
+//    virtual ULONG timecodeToFrameNumber(ULLONG timecode)=0; //Obsolete and not HD compatible
     virtual ULLONG getCurrentTimestamp()=0;
     virtual void displayIFrame(const UCHAR* buffer, UINT length)=0;
 
+       virtual bool supportsh264(){return false;};
+       virtual void seth264mode(bool ish264) {h264=ish264;};
+
     virtual void turnVideoOn(){};
     virtual void turnVideoOff(){};
-    virtual ULLONG frameNumberToTimecode(ULONG timecode) { return 0; };
+//    virtual ULLONG frameNumberToTimecode(ULONG timecode) { return 0; };//Obsolete and not HD compatible
 
 #ifdef DEV
     virtual int test() { return 0; }
@@ -82,8 +85,8 @@ class Video: public DrainTarget, public AbstractOption
     UINT getScreenHeight()  { return screenHeight; }
     UCHAR getTVsize()       { return tvsize; }
 
-    hmsf framesToHMSF(ULONG frames);
-    UINT getFPS();
+    //hmsf framesToHMSF(ULONG frames,double fps);
+   // UINT getFPS(); //removed
 
     // Video formats - AV_SET_VID_DISP_FMT
     const static UCHAR NTSC = 0;
@@ -138,6 +141,7 @@ class Video: public DrainTarget, public AbstractOption
     UCHAR connection;
     UCHAR aspectRatio;
     UCHAR mode;
+       bool h264;
 
     UINT screenWidth;
     UINT screenHeight;
index a66e0f9d9d5a69cc2d83c6ae1bb88c62cafca647..6e627af1a1b3a43d779f1cba499a8b65dadd7578 100644 (file)
@@ -383,7 +383,7 @@ void VideoMVP::PrepareMediaSample(const MediaPacketList& mplist,UINT samplepos)
   }
 }
 
-UINT VideoMVP::DeliverMediaSample(const UCHAR* buffer, UINT* samplepos)
+UINT VideoMVP::DeliverMediaSample(UCHAR* buffer, UINT* samplepos)
 {
   int written = ::write(fdVideo, buffer + deliver_start, deliver_length);
   if (written == (int)deliver_length) { *samplepos = 0; return deliver_count;}
index dd94a45c7c7fc11e34198fc65aa4d2d3702be56c..fc086e6962eeed8a5a5b94a63503263f068bd378 100644 (file)
@@ -134,7 +134,7 @@ class VideoMVP : public Video
 
     // Writing Data to Videodevice
     virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);
-    virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT* samplepos);
+    virtual UINT DeliverMediaSample( UCHAR* buffer, UINT* samplepos);
     virtual long long SetStartOffset(long long curreftime, bool *rsync)
     { return 0; };
     virtual void ResetTimeOffsets();
index 1f1b6358013a079ecdeecdecd0c4b0432472a2d5..8e0a4ddab629a2a86cc0ee2447928630db47aa75 100644 (file)
@@ -18,6 +18,8 @@
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 
+
+
 #include "videowin.h"
 #include "log.h"
 #include "dssourcefilter.h"
 #include "osdwin.h"
 #include "audiowin.h"
 #include "wwinvideofilter.h"
+#include "wwinvideoh264filter.h"
 #include "wtabbar.h"
 #include "woptionpane.h"
 #include "i18n.h"
+#include "demuxer.h"
+
+#include <Mfapi.h>
+#include <mferror.h>
 
 void AdjustWindow();
 
@@ -39,7 +46,7 @@ VideoWin::VideoWin()
   dsinited=false;
   dsgraphbuilder=NULL;
   dsmediacontrol=NULL;
-  dsvmrrenderer=NULL;
+  dsrenderer=NULL;
   dsrefclock=NULL;
   dsmediafilter=NULL;
   dsbasicaudio=NULL;
@@ -71,6 +78,8 @@ VideoWin::VideoWin()
   iframemode=false;//We are not in Iframe mode at begining
   vmrdeinterlacing=2;//Best
   videofilterselected=-1;
+  videoH264filterselected=-1;
+  currentpresenter=EVR;
 
 
 
@@ -81,7 +90,7 @@ VideoWin::~VideoWin()
 {
   CleanupDS();
   CloseHandle(filtermutex);
-  int i;
+  unsigned int i;
   for (i=0;i<videofilterlist.size();i++)
   {
    if (videofilterlist[i].displayname) delete [] videofilterlist[i].displayname;
@@ -89,6 +98,13 @@ VideoWin::~VideoWin()
   }
   videofilterlist.clear();
 
+  for (i=0;i<videoH264filterlist.size();i++)
+  {
+   if (videoH264filterlist[i].displayname) delete [] videoH264filterlist[i].displayname;
+   if (videoH264filterlist[i].friendlyname) delete [] videoH264filterlist[i].friendlyname;
+  }
+  videoH264filterlist.clear();
+
 
 
 
@@ -104,6 +120,7 @@ int VideoWin::init(UCHAR tformat)
   videoposx=0;
   videoposy=0;
   initFilterDatabase();
+  initH264FilterDatabase();
 
   if (!setFormat(tformat)){ shutdown(); return 0; }
   return 1;
@@ -283,6 +300,77 @@ void VideoWin::initFilterDatabase()
 
 
 
+    filtmap->Release();
+}
+
+void VideoWin::initH264FilterDatabase()
+{
+    /* This method should determine all availiable DirectShow Filters */
+    IFilterMapper2* filtmap=NULL;
+    HRESULT result;
+    result = CoCreateInstance(CLSID_FilterMapper2,NULL,CLSCTX_INPROC,
+                IID_IFilterMapper2,(void**)&filtmap);
+    if (result != S_OK)
+    {
+        Log::getInstance()->log("VideoWin", Log::ERR , "Unable to create FilterMapper!");
+        return;
+    }
+    /* Wishlist, what Mediatypes do we want */
+    GUID mtypesin[]={MEDIATYPE_Video,MEDIASUBTYPE_H264};
+    IEnumMoniker *myenum;
+    result = filtmap->EnumMatchingFilters(&myenum,0,TRUE,MERIT_DO_NOT_USE+1,
+                    TRUE,1,mtypesin,NULL,NULL,FALSE,TRUE,0,NULL,NULL,NULL);
+    if (result != S_OK)
+    {
+        filtmap->Release();
+        Log::getInstance()->log("VideoWin", Log::ERR , "Unable to enum Filters!");
+        return;
+    }
+    ULONG gethowmany;
+    IMoniker * moni;
+    while(myenum->Next(1,&moni,&gethowmany)==S_OK)
+    {
+        VideoFilterDesc desc;
+        ZeroMemory(&desc,sizeof(desc));
+   
+        LPOLESTR string;
+        moni->GetDisplayName(0,0,&string);
+        desc.displayname=new char[wcslen(string)+1];
+        wcstombs(desc.displayname,string,wcslen(string)+1);
+        CoTaskMemFree(string);
+        IPropertyBag *bag;
+        if (moni->BindToStorage(0,0,IID_IPropertyBag,(void**)&bag) == S_OK)
+        {
+            VARIANT vari;
+            VariantInit(&vari);
+            result = bag->Read(L"FriendlyName",&vari,NULL);
+            if (result == S_OK)
+            {
+                desc.friendlyname=new char[wcslen(vari.bstrVal)+1];
+                wcstombs(desc.friendlyname,vari.bstrVal,wcslen(vari.bstrVal)+1);
+            }
+            VariantClear(&vari);
+            bag->Release();
+
+        }
+        
+       
+        videoH264filterlist.push_back(desc);
+       
+
+        
+        moni->Release();
+       // bctx->Release();
+    }
+    int i;
+    videoH264filterselected=-1;
+    
+    
+  
+    myenum->Release();
+
+
+
     filtmap->Release();
 }
 
@@ -301,6 +389,19 @@ bool VideoWin::loadOptionsfromServer(VDR* vdr)
             }
         }
    }
+   name=vdr->configLoad("DirectShow","VideoH264Filter");
+    
+    if (name != NULL) 
+    {
+        for (int i = 0;i <videoH264filterlist.size();i++)
+        {
+            if (strcmp(name,videoH264filterlist[i].displayname)==0)
+            {
+                videoH264filterselected = i;
+                break;
+            }
+        }
+   }
    name=vdr->configLoad("DirectShow","VMR9DeinterlacingMode");
    if (name != NULL) 
    {
@@ -317,6 +418,18 @@ bool VideoWin::loadOptionsfromServer(VDR* vdr)
        }
    }
 
+   name=vdr->configLoad("DirectShow", "VideoPresenter");
+   if (name!=NULL) {
+       if (STRCASECMP(name,"VMR9")==0) {
+           currentpresenter=VMR9;
+          } else if (STRCASECMP(name,"EVR")==0) {
+           currentpresenter=EVR;
+       } 
+   }
+   if (!((OsdWin*)Osd::getInstance())->IsEvrSupported()) {
+           currentpresenter=VMR9;
+   }
+
    name=vdr->configLoad("DirectGraphics", "StretchFiltering");
    if (name!=NULL) {
        if (STRCASECMP(name,"None")==0) {
@@ -328,6 +441,8 @@ bool VideoWin::loadOptionsfromServer(VDR* vdr)
        }
    }
 
+   
+
 
    return true;
 
@@ -360,6 +475,13 @@ bool VideoWin::handleOptionChanges(Option* option)
                 vmrdeinterlacing=4;
             } 
                 }break;
+                case 3: {
+            if (STRCASECMP(option->options[option->userSetChoice],"VMR9")==0)  {
+                currentpresenter=VMR9;
+            } else if (STRCASECMP(option->options[option->userSetChoice],"EVR")==0)  {
+                currentpresenter=EVR;
+            } 
+                }break;
     };
     return false;
 
@@ -370,6 +492,8 @@ bool VideoWin::saveOptionstoServer()
     if (videofilterselected!=-1) {
         VDR::getInstance()->configSave("DirectShow",
             "VideoFilter",videofilterlist[videofilterselected].displayname);
+                VDR::getInstance()->configSave("DirectShow",
+            "VideoH264Filter",videoH264filterlist[videoH264filterselected].displayname);
     }
     return true;
 }
@@ -404,14 +528,25 @@ bool VideoWin::addOptionsToPanes(int panenumber,Options *options,WOptionPane* pa
             strcpy(scalingopts[i],"Linear");
             i++;
         }
-        option = new Option(1 , "Video Stretching Filter", "DirectGraphics", "StretchFiltering", Option::TYPE_TEXT, i, (i-1), 0, scalingopts,NULL,true, this);
+        option = new Option(1 ,tr("Video Stretching Filter"), "DirectGraphics", "StretchFiltering", Option::TYPE_TEXT, i, (i-1), 0, scalingopts,NULL,true, this);
         options->push_back(option);
         pane->addOptionLine(option);
         static const char* deintopts[]={"NoMix","None","Best","Bob","Weave"};
-        option = new Option(2,"VMR9 Deinterlacing Mode", "DirectShow","VMR9DeinterlacingMode",Option::TYPE_TEXT,5,2,0,deintopts,NULL,false,this);
+        option = new Option(2,tr("VMR9 Deinterlacing Mode"), "DirectShow","VMR9DeinterlacingMode",Option::TYPE_TEXT,5,2,0,deintopts,NULL,false,this);
         options->push_back(option);
         pane->addOptionLine(option);
 
+               if (((OsdWin*)Osd::getInstance())->IsEvrSupported()) 
+               {
+                       static const char* presenteropts[]={"EVR","VMR9"};
+                       option = new Option(3,tr("Video Presenter Filter"),"DirectShow", "VideoPresenter",Option::TYPE_TEXT,2,0,0,presenteropts,NULL,false,this);
+               } else {
+                       static const char* presenteropts[]={"VMR9"};
+                       option = new Option(3,tr("Video Presenter Filter"),"DirectShow", "VideoPresenter",Option::TYPE_TEXT,1,0,0,presenteropts,NULL,false,this);
+               }
+               options->push_back(option);
+        pane->addOptionLine(option);
+
       
     }
 
@@ -539,6 +674,130 @@ IBaseFilter *VideoWin::getVideoFilter()
     
 }
 
+IBaseFilter *VideoWin::getVideoH264Filter()
+{
+    IBaseFilter *curfilter= NULL;
+    if (videoH264filterselected == -1)
+    {
+        int i;
+        for (i = 0;i <videoH264filterlist.size();i++)
+        {
+            
+            if (videoH264filterlist[i].vmr9tested == true)
+            {
+                if (videoH264filterlist[i].vmr9 == true)
+                {
+                    videoH264filterselected = i;
+                    break;
+                } 
+                else
+                {
+                    continue;
+                }
+            }
+            else
+            {
+                IMoniker * moni=NULL;
+                IBindCtx *bindctx=NULL;
+                if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
+                LPCOLESTR name=(LPCOLESTR)new WCHAR[strlen(videoH264filterlist[i].displayname)+1];
+                mbstowcs((wchar_t*)name,videoH264filterlist[i].displayname,strlen(videoH264filterlist[i].displayname)+1);
+                ULONG eater=0;
+                               Log::getInstance()->log("VideoWin", Log::DEBUG ,"Creating filter: %s",videoH264filterlist[i].friendlyname);
+
+                
+
+                if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
+                {
+                    if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
+                    {
+                        IAMDecoderCaps* desccaps=NULL;
+                        if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
+                        {
+                            DWORD caps;
+                            desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
+                            if (caps == DECODER_CAP_SUPPORTED)
+                            {
+                                videoH264filterlist[i].vmr9tested =  true;
+                                videoH264filterlist[i].vmr9 = true;
+                                videoH264filterselected = i;
+                            } 
+                            else
+                            {
+                                videoH264filterlist[i].vmr9tested =  true;
+                                videoH264filterlist[i].vmr9 = false;
+                                
+                                curfilter->Release();
+                                curfilter=NULL;
+                            }
+                        }
+                        desccaps->Release();
+                    }
+                    moni->Release();
+                } 
+                delete [] name;
+                bindctx->Release();
+            }
+            if (videoH264filterlist[i].vmr9) break;
+            
+        }
+        if (curfilter != NULL)
+        {
+            VDR *vdr=VDR::getInstance();
+            if (vdr != NULL)
+            {
+                vdr->configSave("DirectShow","VideoH264Filter",
+                    videoH264filterlist[videoH264filterselected].displayname);
+            }
+            return curfilter;
+        }
+    } 
+    else
+    {
+        IBindCtx *bindctx=NULL;
+        if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
+        IMoniker * moni=NULL;
+        LPCOLESTR name=new WCHAR[strlen(videoH264filterlist[videoH264filterselected].displayname)+1];
+        mbstowcs((wchar_t*)name,videoH264filterlist[videoH264filterselected].displayname,
+            strlen(videoH264filterlist[videoH264filterselected].displayname)+1);
+        ULONG eater;
+               Log::getInstance()->log("VideoWin", Log::DEBUG ,"Creating filter: %s",videoH264filterlist[videoH264filterselected].friendlyname);
+        if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
+        {
+            if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
+            {
+                    IAMDecoderCaps* desccaps=NULL;
+                    if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
+                    {
+                        DWORD caps;
+                        desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
+                        if (caps == DECODER_CAP_SUPPORTED)
+                        {
+                            videoH264filterlist[videoH264filterselected].vmr9tested =  true;
+                            videoH264filterlist[videoH264filterselected].vmr9 = true;
+                        } 
+                        else
+                        {
+                            videoH264filterlist[videoH264filterselected].vmr9tested =  true;
+                            videoH264filterlist[videoH264filterselected].vmr9 = false;
+                            Log::getInstance()->log("VideoWin", Log::WARN ,"Filter does not support VMR9, but is selected, manual selection!");
+                        }
+                    }
+                    moni->Release();
+                    delete [] name;
+                    bindctx->Release();
+                    return curfilter;
+             } 
+            moni->Release();
+        }
+        bindctx->Release();
+        delete [] name;
+        return NULL;         
+    }
+    return NULL;
+    
+}
+
 
 #ifdef DS_DEBUG // This stuff would not included in vomp due to lincemse restrcitions
 #include "dshelper.h"
@@ -556,6 +815,8 @@ bool VideoWin::addOptionPagesToWTB(WTabBar *wtb)
 {
     Boxx *box=new WWinVideoFilter();
     wtb->addTab(tr("Video Filter"), box);
+       box=new WWinVideoH264Filter();
+    wtb->addTab(tr("H264 Filter"), box);
     return true;
 }
 
@@ -565,6 +826,12 @@ const VideoFilterDescList *VideoWin::getVideoFilterList(int &selected)
     return &videofilterlist;
 }
 
+const VideoFilterDescList *VideoWin::getVideoH264FilterList(int &selected)
+{
+    selected=videoH264filterselected;
+    return &videoH264filterlist;
+}
+
 bool VideoWin::selectVideoFilter(int filter)
 {
     IBindCtx *bindctx=NULL;
@@ -622,6 +889,62 @@ bool VideoWin::selectVideoFilter(int filter)
     }
 }
 
+bool VideoWin::selectVideoH264Filter(int filter)
+{
+    IBindCtx *bindctx=NULL;
+    if (CreateBindCtx(0,&bindctx)!=S_OK) return NULL;
+    IMoniker * moni=NULL;
+    LPCOLESTR name=new WCHAR[strlen(videoH264filterlist[filter].displayname)+1];
+    mbstowcs((wchar_t*)name,videoH264filterlist[filter].displayname,
+    strlen(videoH264filterlist[filter].displayname)+1);
+    ULONG eater;
+    bool success=false;
+    if (MkParseDisplayName(bindctx,name,&eater,&moni)==S_OK)
+    {
+        IBaseFilter* curfilter=NULL;
+        if (moni->BindToObject(0,0,IID_IBaseFilter,(void**)&curfilter) == S_OK)
+        {
+            IAMDecoderCaps* desccaps=NULL;
+            if (curfilter->QueryInterface(IID_IAMDecoderCaps,(void**) &desccaps)==S_OK)
+            {
+                DWORD caps;
+                HRESULT hres=desccaps->GetDecoderCaps(AM_GETDECODERCAP_QUERY_VMR9_SUPPORT,&caps);
+                if (caps == DECODER_CAP_SUPPORTED)
+                {
+                    videoH264filterlist[filter].vmr9tested =  true;
+                    videoH264filterlist[filter].vmr9 = true;
+                    success=true;
+                } 
+                else
+                {
+                    videoH264filterlist[filter].vmr9tested =  true;
+                    videoH264filterlist[filter].vmr9 = false;
+                    success=false;
+                 }
+                desccaps->Release();
+            } else {
+                videoH264filterlist[filter].vmr9tested =  true;
+                videoH264filterlist[filter].vmr9 = false;
+                success=false;
+            }
+
+             curfilter->Release();
+             
+        } 
+        moni->Release();
+    }
+    bindctx->Release();
+    delete [] name;
+    if (success || true) 
+    {
+        videoH264filterselected=filter;
+        return true;
+    } 
+    else
+    {
+        return false;
+    }
+}
 
 int VideoWin::dsInitVideoFilter()
 {
@@ -629,74 +952,167 @@ int VideoWin::dsInitVideoFilter()
     HRESULT hres;
     if (videoon) {
     //We alloc the vmr9 as next step
-        if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,
-            CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsvmrrenderer)!=S_OK) 
-        {
-            Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");
-               ReleaseMutex(filtermutex);
-            CleanupDS();
-        }
-        /*VMR 9 stuff**/
-        if (hres=dsgraphbuilder->AddFilter(dsvmrrenderer,L"VMR9")!=S_OK)
-        {
-            ReleaseMutex(filtermutex);
-            CleanupDS();
-            Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");
-            return 0;
-        }
-        IVMRFilterConfig9* vmrfilconfig;
-        if (dsvmrrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK)
-        {
-            ReleaseMutex(filtermutex);
-            CleanupDS();
-            Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");
-            return 0;
-        }
-        if (vmrdeinterlacing!=0) vmrfilconfig->SetNumberOfStreams(1);//Enter Mixing Mode
-        vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);
-       
-        vmrfilconfig->Release();
-
-        if (dsvmrrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,
-            (void**)& dsvmrsurfnotify) != S_OK)
-        {
-            ReleaseMutex(filtermutex);
-               CleanupDS();
-            Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");
-            return 0;
-        }
-        allocatorvmr=new DsAllocator();
-        dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);
-        allocatorvmr->AdviseNotify(dsvmrsurfnotify);
-
-        IVMRDeinterlaceControl9* deintctrl;
-        if (dsvmrrenderer->QueryInterface(IID_IVMRDeinterlaceControl9,(void**)&deintctrl)!=S_OK)
-        {
-            ReleaseMutex(filtermutex);
-               CleanupDS();
-            Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Deinterlace control!");
-            return 0;
-        }
-        /*turnoff*/
-        switch (vmrdeinterlacing)
-        {
-        case 1: //No Deinterlasing
-          deintctrl->SetDeinterlaceMode(0xFFFFFFFF,(LPGUID)&GUID_NULL);//Turn Off
+               if (currentpresenter==VMR9) 
+               {
+                       Log::getInstance()->log("VideoWin", Log::INFO ,"VMR9 Videopresenter selected!");
+                       if (hres=CoCreateInstance(CLSID_VideoMixingRenderer9,0,
+                               CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsrenderer)!=S_OK) 
+                       {
+                               Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating VMR9 renderer!");
+                               ReleaseMutex(filtermutex);
+                               CleanupDS();
+                       }
+                       /*VMR 9 stuff**/
+                       if (hres=dsgraphbuilder->AddFilter(dsrenderer,L"VMR9")!=S_OK)
+                       {
+                               ReleaseMutex(filtermutex);
+                               CleanupDS();
+                               Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding VMR9 renderer!");
+                               return 0;
+                       }
+                       IVMRFilterConfig9* vmrfilconfig;
+                       if (dsrenderer->QueryInterface(IID_IVMRFilterConfig9,(void**)&vmrfilconfig)!=S_OK)
+                       {
+                               ReleaseMutex(filtermutex);
+                               CleanupDS();
+                               Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Filterconfig interface!");
+                               return 0;
+                       }
+                       if (vmrdeinterlacing!=0) vmrfilconfig->SetNumberOfStreams(1);//Enter Mixing Mode
+                       vmrfilconfig->SetRenderingMode(VMR9Mode_Renderless);
+                       vmrfilconfig->Release();
+                       if (dsrenderer->QueryInterface(IID_IVMRSurfaceAllocatorNotify9,
+                               (void**)& dsvmrsurfnotify) != S_OK)
+                       {
+                               ReleaseMutex(filtermutex);
+                               CleanupDS();
+                               Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Surface Allocator interface!");
+                               return 0;
+                       }
+                       allocatorvmr=new DsAllocator();
+                       dsvmrsurfnotify->AdviseSurfaceAllocator(NULL,allocatorvmr);
+                       allocatorvmr->AdviseNotify(dsvmrsurfnotify);
+                       
+                       IVMRDeinterlaceControl9* deintctrl;
+                       if (dsrenderer->QueryInterface(IID_IVMRDeinterlaceControl9,(void**)&deintctrl)!=S_OK)
+                       {
+                               ReleaseMutex(filtermutex);
+                               CleanupDS();
+                               Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Deinterlace control!");
+                               return 0;
+                       }
+                       /*turnoff*/
+                       switch (vmrdeinterlacing)
+                       {
+                       case 1: //No Deinterlasing
+                        deintctrl->SetDeinterlaceMode(0xFFFFFFFF,(LPGUID)&GUID_NULL);//Turn Off
             break;
-        case 2: //Best
-            deintctrl->SetDeinterlacePrefs(DeinterlacePref_NextBest);//Choose Next Best
-            
+                       case 2: //Best
+             deintctrl->SetDeinterlacePrefs(DeinterlacePref_NextBest);//Choose Next Best
             break;
-        case 3: //Bob
-            deintctrl->SetDeinterlacePrefs(DeinterlacePref_BOB);//Choose NBob
-        break;
-        case 4: //Weave
-            deintctrl->SetDeinterlacePrefs(DeinterlacePref_Weave);//Choose Weave
+                       case 3: //Bob
+             deintctrl->SetDeinterlacePrefs(DeinterlacePref_BOB);//Choose NBob
+                       break;
+                       case 4: //Weave
+             deintctrl->SetDeinterlacePrefs(DeinterlacePref_Weave);//Choose Weave
+             break;
+                       };
+                       deintctrl->Release();
+                       /*VMR 9 stuff end */
+               }
+               else if (currentpresenter==EVR)
+               {
+                       Log::getInstance()->log("VideoWin", Log::INFO ,"EVR Videopresenter selected!");
+                       if (hres=CoCreateInstance(CLSID_EnhancedVideoRenderer,0,
+                               CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void**) &dsrenderer)!=S_OK) 
+                       {
+                               Log::getInstance()->log("VideoWin", Log::WARN ,"Failed creating EVR renderer!");
+                               ReleaseMutex(filtermutex);
+                               CleanupDS();
+                       }
+                       /*EVR stuff**/
+                       if (hres=dsgraphbuilder->AddFilter(dsrenderer,L"EVR")!=S_OK)
+                       {
+                               ReleaseMutex(filtermutex);
+                               CleanupDS();
+                               Log::getInstance()->log("VideoWin", Log::WARN ,"Failed adding EVR renderer!");
+                               return 0;
+                       }
+                       
+                       
+                       IMFGetService *evr_services;
+                       if (dsrenderer->QueryInterface(IID_IMFGetService,(void**)&evr_services)!=S_OK)
+                       {
+                               ReleaseMutex(filtermutex);
+                               CleanupDS();
+                               Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting EVR IMFGetServices interface!");
+                               return 0;
+                       }
+
+                       IMFVideoDisplayControl* mfvideodisplaycontrol;
+                       if (evr_services->GetService(MR_VIDEO_RENDER_SERVICE,IID_IMFVideoDisplayControl,(void**)&mfvideodisplaycontrol)!=S_OK)
+                       {
+                               ReleaseMutex(filtermutex);
+                               CleanupDS();
+                               Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting EVR IMFVideoDisplayControl interface!");
+                               return 0;
+                       }
+
+                       evr_services->Release();
+                       mfvideodisplaycontrol->SetVideoWindow(((OsdWin*) Osd::getInstance())->getWindow());
+                       //RECT client;
+                   //GetClientRect(((OsdWin*) Osd::getInstance())->getWindow(), &client);
+                       //mfvideodisplaycontrol->SetVideoPosition(NULL,&client);
+
+                       mfvideodisplaycontrol->Release();
+
+
+               ///     if (vmrdeinterlacing!=0) vmrfilconfig->SetNumberOfStreams(1);//Enter Mixing Mode //always the case for evr!
+
+                       IMFVideoRenderer *mfvideorenderer;
+                       if (dsrenderer->QueryInterface(IID_IMFVideoRenderer,(void**)&mfvideorenderer)!=S_OK)
+                       {
+                               ReleaseMutex(filtermutex);
+                               CleanupDS();
+                               Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting EVR IMFVideoRenderer interface!");
+                               return 0;
+                       }
+                       
+                       allocatorvmr=new DsAllocator();
+                       HRESULT hres=mfvideorenderer->InitializeRenderer(NULL,allocatorvmr);
+
+                       mfvideorenderer->Release();
+                       //How should I do this in EVR?
+               /*      IVMRDeinterlaceControl9* deintctrl;
+                       if (dsrenderer->QueryInterface(IID_IVMRDeinterlaceControl9,(void**)&deintctrl)!=S_OK)
+                       {
+                               ReleaseMutex(filtermutex);
+                               CleanupDS();
+                               Log::getInstance()->log("VideoWin", Log::WARN ,"Failed getting VMR9 Deinterlace control!");
+                               return 0;
+                       }
+                       /*turnoff*
+                       switch (vmrdeinterlacing)
+                       {
+                       case 1: //No Deinterlasing
+                        deintctrl->SetDeinterlaceMode(0xFFFFFFFF,(LPGUID)&GUID_NULL);//Turn Off
             break;
-        };
-        deintctrl->Release();
-
-       /*VMR 9 stuff end */
+                       case 2: //Best
+             deintctrl->SetDeinterlacePrefs(DeinterlacePref_NextBest);//Choose Next Best
+            break;
+                       case 3: //Bob
+             deintctrl->SetDeinterlacePrefs(DeinterlacePref_BOB);//Choose NBob
+                       break;
+                       case 4: //Weave
+             deintctrl->SetDeinterlacePrefs(DeinterlacePref_Weave);//Choose Weave
+             break;
+                       };
+                       deintctrl->Release();*/
+                       /*EVR stuff end */
+               } else {
+                       Log::getInstance()->log("VideoWin", Log::ERR ,"No videopresenter selected! Please post on the forum!");
+                       return -1;
+               }
         IFilterGraph2*fg2=NULL;
         if (dsgraphbuilder->QueryInterface(IID_IFilterGraph2,(void**)&fg2)!= S_OK)
         {
@@ -718,7 +1134,17 @@ int VideoWin::dsInitVideoFilter()
         }
         
 #else*/
-        IBaseFilter*videofilter=getVideoFilter();
+        IBaseFilter*videofilter;
+               if (h264)  
+               {
+                       Log::getInstance()->log("VideoWin", Log::DEBUG ,"Entering h264 playback...");
+                       videofilter=getVideoH264Filter();
+               } 
+               else
+               {
+                       Log::getInstance()->log("VideoWin", Log::DEBUG ,"Entering MPEG2 playback...");
+                       videofilter=getVideoFilter();
+               }
         if (hres=dsgraphbuilder->AddFilter(videofilter,NULL) != S_OK) 
         {
             Log::getInstance()->log("VideoWin", Log::WARN , "Failed adding Video Filter!");
@@ -728,6 +1154,20 @@ int VideoWin::dsInitVideoFilter()
         }
         IEnumPins *pinenum=NULL;
         bool error=false;
+
+        mptype_video_detail vid_details;
+        Demuxer* demux=Demuxer::getInstance();
+        vid_details.width=demux->getHorizontalSize();
+        vid_details.height=demux->getVerticalSize();
+
+               if (h264)
+               {
+                       sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_H264,&vid_details);
+               }
+               else
+               {
+                       sourcefilter->GetVideoPin()->SetPinMode(MPTYPE_VIDEO_MPEG2,&vid_details);
+               }
         if (videofilter->EnumPins(&pinenum) == S_OK)
         {
             IPin *current=NULL;
@@ -1055,7 +1495,7 @@ ULLONG VideoWin::getCurrentTimestamp()
   return result;
 
 }
-
+/* //to beremoved
 ULONG VideoWin::timecodeToFrameNumber(ULLONG timecode)
 {
   if (format == PAL) return (ULONG)(((double)timecode / (double)90000) * (double)25);
@@ -1067,7 +1507,7 @@ ULLONG VideoWin::frameNumberToTimecode(ULONG framenumber)
   if (format == PAL) return (ULLONG)(((double)framenumber * (double)90000) / (double)25);
   else               return (ULLONG)(((double)framenumber * (double)90000) / (double)30);
 }
-
+*/
 void VideoWin::CleanupDS()
 {
   WaitForSingleObject(filtermutex,INFINITE);
@@ -1089,9 +1529,9 @@ void VideoWin::CleanupDS()
     dsvmrsurfnotify->Release();
     dsvmrsurfnotify=NULL;
   }
-  if (dsvmrrenderer) {
-    dsvmrrenderer->Release();
-    dsvmrrenderer=NULL;
+  if (dsrenderer) {
+    dsrenderer->Release();
+    dsrenderer=NULL;
   }
 
   if (allocatorvmr) {
@@ -1134,7 +1574,7 @@ void VideoWin::PrepareMediaSample(const MediaPacketList& mplist,
   mediapacket = mplist.front();
 }
 
-UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
+UINT VideoWin::DeliverMediaSample(UCHAR* buffer, UINT *samplepos)
 {
   DeliverMediaPacket(mediapacket, buffer, samplepos);
   if (*samplepos == mediapacket.length) {
@@ -1145,123 +1585,141 @@ UINT VideoWin::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos)
 }
 
 UINT VideoWin::DeliverMediaPacket(MediaPacket packet,
-     const UCHAR* buffer,
-     UINT *samplepos)
+                                  const UCHAR* buffer,
+                                  UINT *samplepos)
 {
-    
-  /*First Check, if we have an audio sample*/
-       if (!isdsinited()) return 0;
+
+    /*First Check, if we have an audio sample*/
+    if (!isdsinited()) return 0;
+    if (packet.type == MPTYPE_VIDEO_H264)
+    {
+        h264=true;
+    }
+    else
+    {
+        h264=false;
+    }
+
 #ifdef DO_VIDEO
-       if (!videoon) {
-         *samplepos+=packet.length;
-       MILLISLEEP(0); //yet not implemented//bad idea
-       return packet.length;
-       }
-  /*First Check, if we have an audio sample*/
-  if (iframemode) {
-               samplepos=0;
-               MILLISLEEP(10);
-               return 0; //Not in iframe mode!
-  }
-  IMediaSample* ms=NULL;
-  REFERENCE_TIME reftime1=0;
-  REFERENCE_TIME reftime2=0;
+    if (!videoon) {
+        *samplepos+=packet.length;
+        MILLISLEEP(0); //yet not implemented//bad idea
+        return packet.length;
+    }
+    /*First Check, if we have an audio sample*/
+    if (iframemode) {
+        //samplepos=0;
+        MILLISLEEP(10);
+        return 0; //Not in iframe mode!
+    }
+    IMediaSample* ms=NULL;
+    REFERENCE_TIME reftime1=0;
+    REFERENCE_TIME reftime2=0;
 
-  UINT headerstrip=0;
-  if (packet.disconti) {
-    firstsynched=false;
-    DeliverVideoMediaSample();
+    UINT headerstrip=0;
+    if (packet.disconti) {
+        firstsynched=false;
+        DeliverVideoMediaSample();
+    }
 
-  }
-  /*Inspect PES-Header */
-
-  if (*samplepos==0) {//stripheader
-    headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
-    *samplepos+=headerstrip;
-    if ( packet.synched ) {
-      DeliverVideoMediaSample();//write out old data
-   /*   if (packet.presentation_time<0) { //Preroll?
-        *samplepos=packet.length;//if we have not processed at least one
-        return packet.length;//synched packet ignore it!
-      }*/
-
-      reftime1=packet.presentation_time;
-      reftime2=reftime1+1;
-      firstsynched=true;
-    } else {
-      if (!firstsynched) {//
-        *samplepos=packet.length;//if we have not processed at least one
-        return packet.length;//synched packet ignore it!
-      }
+    
+
+    /*Inspect PES-Header */
+
+    if (*samplepos==0) {//stripheader
+        headerstrip=buffer[packet.pos_buffer+8]+9/*is this right*/;
+        *samplepos+=headerstrip;
+        if ( packet.synched ) {
+            DeliverVideoMediaSample();//write out old data
+            /*   if (packet.presentation_time<0) { //Preroll?
+            *samplepos=packet.length;//if we have not processed at least one
+            return packet.length;//synched packet ignore it!
+            }*/
+
+            reftime1=packet.presentation_time;
+            reftime2=reftime1+1;
+            firstsynched=true;
+        } else {
+            if (!firstsynched) {//
+                *samplepos=packet.length;//if we have not processed at least one
+                return packet.length;//synched packet ignore it!
+            }
+        }
     }
-  }
-  BYTE *ms_buf;
-  UINT ms_length;
-  UINT ms_pos;
-  UINT haveToCopy;
-  
-  if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
-    samplepos=0;
-    MILLISLEEP(10);
-    return 0;
-  }
-  ms_pos=ms->GetActualDataLength();
-  ms_length=ms->GetSize();
-  haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
-  if ((ms_length-ms_pos)<1) {
-    DeliverVideoMediaSample(); //we are full!
+    BYTE *ms_buf;
+    UINT ms_length;
+    UINT ms_pos;
+    UINT haveToCopy;
+
     if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
-      samplepos=0;
-      MILLISLEEP(10);
-      return 0;
+        //samplepos=0;
+        //MessageBox(0,"da isser","hei",0);
+        //MILLISLEEP(1);
+        return 0;
     }
     ms_pos=ms->GetActualDataLength();
     ms_length=ms->GetSize();
     haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
-  }
-  ms->GetPointer(&ms_buf);
+    if ((ms_length-ms_pos)<1 ) {
+        DeliverVideoMediaSample(); //we are full!
+        if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
+            //samplepos=0;
+            //MessageBox(0,"da isser","hei",0);
+            //MILLISLEEP(10);
+            return 0;
+        }
+        ms_pos=ms->GetActualDataLength();
+        ms_length=ms->GetSize();
+        haveToCopy=min(ms_length-ms_pos,packet.length-*samplepos);
+    }
+    ms->GetPointer(&ms_buf);
 
 
-  if (ms_pos==0) {//will only be changed on first packet
-    if (packet.disconti) {
-      ms->SetDiscontinuity(TRUE);
-    } else {
-      ms->SetDiscontinuity(FALSE);
-    }
-    if (packet.synched) {
-      ms->SetSyncPoint(TRUE);
-      ms->SetTime(&reftime1,&reftime2);
-      //ms->SetTime(NULL,NULL);
-      ms->SetMediaTime(NULL, NULL);
-    if (reftime1<0) ms->SetPreroll(TRUE);
-    else ms->SetPreroll(FALSE);
-    /*Timecode handling*/
-    lastreftimeRT=reftime1;
-       lastreftimePTS=packet.pts;
-
-    }else {
-      ms->SetSyncPoint(FALSE);
-      ms->SetTime(NULL,NULL);
-      ms->SetMediaTime(NULL, NULL);
-      ms->SetPreroll(FALSE);
-
-    //  ms->SetSyncPoint(TRUE);
+    if (ms_pos==0) {//will only be changed on first packet
+        if (packet.disconti) {
+            ms->SetDiscontinuity(TRUE);
+        } else {
+            ms->SetDiscontinuity(FALSE);
+        }
+        if (packet.synched) {
+            ms->SetSyncPoint(TRUE);
+            ms->SetTime(&reftime1,&reftime2);
+            //Log::getInstance()->log("VideoWin", Log::DEBUG , "Setted videotime to %lld %lld",reftime1,reftime2);
+            //Log::getInstance()->log("VideoWin", Log::DEBUG , "Packet pts %lld dts %lld",packet.pts,packet.dts);
+            //ms->SetTime(NULL,NULL);
+            ms->SetMediaTime(NULL, NULL);
+            if (reftime1<0) ms->SetPreroll(TRUE);
+            else ms->SetPreroll(FALSE);
+            /*Timecode handling*/
+            lastreftimeRT=reftime1;
+            lastreftimePTS=packet.pts;
+
+        }
+        else
+        {
+            ms->SetSyncPoint(FALSE);
+            ms->SetTime(NULL,NULL);
+            ms->SetMediaTime(NULL, NULL);
+            ms->SetPreroll(FALSE);
+
+            //  ms->SetSyncPoint(TRUE);
+        }
     }
-  }
+    
 
 
-  memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);
+    memcpy(ms_buf+ms_pos,buffer+packet.pos_buffer+*samplepos,haveToCopy);
     ms->SetActualDataLength(haveToCopy+ms_pos);
 
-  *samplepos+=haveToCopy;
+    *samplepos+=haveToCopy;
 
-  return haveToCopy+headerstrip;
+    return haveToCopy+headerstrip;
 
 #else
 
-       *samplepos+=packet.length;
-      MILLISLEEP(0); //yet not implemented//bad idea
-       return packet.length;
+    *samplepos+=packet.length;
+    MILLISLEEP(0); //yet not implemented//bad idea
+    return packet.length;
 #endif
 }
 
@@ -1406,12 +1864,12 @@ void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
 {
        if (!iframemode) EnterIframePlayback();
        if (!isdsinited()) return ;
+       
 #ifdef DO_VIDEO
   IMediaSample* ms=NULL;
   REFERENCE_TIME reftime1=0;
   REFERENCE_TIME reftime2=0;
   if (!videoon) return;
-
   if (!getCurrentVideoMediaSample(&ms) || ms==NULL) {// get the current sample
     MILLISLEEP(10);
     return ;
@@ -1475,8 +1933,10 @@ void VideoWin::displayIFrame(const UCHAR* buffer, UINT length)
       }
     }
   }
-
-  if (first) {ms->SetSyncPoint(TRUE);first=false;} 
+  if (first) {ms->SetSyncPoint(TRUE);
+  ms->SetDiscontinuity(TRUE);
+  first=false;} 
   else ms->SetSyncPoint(FALSE);
   ms->SetTime(NULL,NULL);
   ms->SetMediaTime(NULL, NULL);
@@ -1499,6 +1959,13 @@ bool VideoWin::supportsAc3(){
     }
 }
 
+bool VideoWin::supportsh264()
+{
+       if (videoH264filterlist.size()>0) return true;
+       else return false;
+}
+
+
 bool VideoWin::changeAType(int type,IMediaSample* ms){
     if (sourcefilter!= NULL) {
         lastaudiomode=type;
index 7bc868e9cafe2e68fc7c859d2381bbc413853b48..814efdc55ad49eac7e5eeda5764cb531d3fac820 100644 (file)
@@ -51,148 +51,166 @@ class DsAllocator;
 
 class VideoWin : public Video
 {
-  public:
-    VideoWin();
-    ~VideoWin();
-
-    int init(UCHAR format);
-    int shutdown();
-
-    int setFormat(UCHAR format);
-    int setConnection(UCHAR connection);
-    int setAspectRatio(UCHAR aspectRatio);   // This one does the pin 8 scart widescreen switching
-  UCHAR getAspectRatio(){return aspectRatio;};
-  UCHAR getMode(){return mode;};
-  UCHAR getPseudoTVsize() {return pseudotvsize;};
-  int setMode(UCHAR mode);
-    int setTVsize(UCHAR size);               // Is the TV a widescreen?
-    int setDefaultAspect();
-    int setSource();
-    int setPosition(int x, int y);
-    int sync();
-    int play();
-  int dsplay();
-  bool InIframemode() {return iframemode;};
-    int stop();
-  int dsstop();
-    int pause();
-  int dspause();
-    int unPause();
-  int dsunPause();
-    int fastForward();
-    int unFastForward();
-    int reset();
-  int dsreset();
-    int blank();
-    int signalOn();
-    int signalOff();
-    int attachFrameBuffer(); // What does this do?
-    ULONG timecodeToFrameNumber(ULLONG timecode);
-  ULLONG frameNumberToTimecode(ULONG framenumber);
-    ULLONG getCurrentTimestamp();
-
-    bool loadOptionsfromServer(VDR* vdr);
-    bool saveOptionstoServer();
-    bool addOptionPagesToWTB(WTabBar *wtb);
-    bool addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane);
-    bool handleOptionChanges(Option* option);
-
-    //Writing Data to Videodevice
-    virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);
-    virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos);
-    UINT DeliverMediaPacket(MediaPacket packet, const UCHAR* buffer, UINT *samplepos);
-
-
-
-    virtual bool supportsAc3();
-    
-  private:
-    MediaPacket mediapacket;
-  public:
-
-    int getCurrentAudioMediaSample(IMediaSample** ms);
-    int DeliverAudioMediaSample();
-
-    int getCurrentVideoMediaSample(IMediaSample** ms);
-    int DeliverVideoMediaSample();
-    int setAudioStreamType(UCHAR type);
-
-    virtual long long SetStartOffset(long long curreftime, bool *rsync);
-    long long SetStartAudioOffset(long long curreftime, bool *rsync);
-  virtual void ResetTimeOffsets();
-
-    void SetAudioState(bool state){audioon=state;};
-  void SetAudioVolume(long volume);
-
-    void turnVideoOn(){videoon=true;};
-    void turnVideoOff(){videoon=false;};
-
-    virtual void displayIFrame(const UCHAR* buffer, UINT length);
-
-  unsigned int getPosx() {return videoposx;};
-  unsigned int getPosy() {return videoposy;};
-  bool isVideoOn() {return videoon;};
-  bool isdsinited() {return dsinited;};
-  int lastAType() {return lastaudiomode;};
-  bool changeAType(int type,IMediaSample* ms);
-
-
-  const VideoFilterDescList *getVideoFilterList(int &selected);
-  bool selectVideoFilter(int filter);
-  DsSourceFilter* getSourceFilter() {return sourcefilter;};
+public:
+       VideoWin();
+       ~VideoWin();
+
+       int init(UCHAR format);
+       int shutdown();
+
+       int setFormat(UCHAR format);
+       int setConnection(UCHAR connection);
+       int setAspectRatio(UCHAR aspectRatio);   // This one does the pin 8 scart widescreen switching
+       UCHAR getAspectRatio(){return aspectRatio;};
+       UCHAR getMode(){return mode;};
+       UCHAR getPseudoTVsize() {return pseudotvsize;};
+       int setMode(UCHAR mode);
+       int setTVsize(UCHAR size);               // Is the TV a widescreen?
+       int setDefaultAspect();
+       int setSource();
+       int setPosition(int x, int y);
+       int sync();
+       int play();
+       int dsplay();
+       bool InIframemode() {return iframemode;};
+       int stop();
+       int dsstop();
+       int pause();
+       int dspause();
+       int unPause();
+       int dsunPause();
+       int fastForward();
+       int unFastForward();
+       int reset();
+       int dsreset();
+       int blank();
+       int signalOn();
+       int signalOff();
+       int attachFrameBuffer(); // What does this do?
+//     ULONG timecodeToFrameNumber(ULLONG timecode);
+//     ULLONG frameNumberToTimecode(ULONG framenumber);
+       ULLONG getCurrentTimestamp();
+
+       bool loadOptionsfromServer(VDR* vdr);
+       bool saveOptionstoServer();
+       bool addOptionPagesToWTB(WTabBar *wtb);
+       bool addOptionsToPanes(int panenumber,Options *options,WOptionPane* pane);
+       bool handleOptionChanges(Option* option);
+
+       //Writing Data to Videodevice
+       virtual void PrepareMediaSample(const MediaPacketList&, UINT samplepos);
+       virtual UINT DeliverMediaSample(UCHAR* buffer, UINT *samplepos);
+       UINT DeliverMediaPacket(const MediaPacket packet, const UCHAR* buffer, UINT *samplepos);
+
+       virtual bool supportsh264();
+
+
+       virtual bool supportsAc3();
+
+       enum VideoPresenter {
+               VMR9,
+               EVR
+       } ;
+
+
+
+private:
+       MediaPacket mediapacket;
+public:
+
+       int getCurrentAudioMediaSample(IMediaSample** ms);
+       int DeliverAudioMediaSample();
+
+       int getCurrentVideoMediaSample(IMediaSample** ms);
+       int DeliverVideoMediaSample();
+       int setAudioStreamType(UCHAR type);
+
+       virtual long long SetStartOffset(long long curreftime, bool *rsync);
+       long long SetStartAudioOffset(long long curreftime, bool *rsync);
+       virtual void ResetTimeOffsets();
+
+       void SetAudioState(bool state){audioon=state;};
+       void SetAudioVolume(long volume);
+
+       void turnVideoOn(){videoon=true;};
+       void turnVideoOff(){videoon=false;};
+
+       virtual void displayIFrame(const UCHAR* buffer, UINT length);
+
+       unsigned int getPosx() {return videoposx;};
+       unsigned int getPosy() {return videoposy;};
+       bool isVideoOn() {return videoon;};
+       bool isdsinited() {return dsinited;};
+       int lastAType() {return lastaudiomode;};
+       bool changeAType(int type,IMediaSample* ms);
+
+
+       const VideoFilterDescList *getVideoFilterList(int &selected);
+       bool selectVideoFilter(int filter);
+       DsSourceFilter* getSourceFilter() {return sourcefilter;};
+
+       const VideoFilterDescList *getVideoH264FilterList(int &selected);
+       bool selectVideoH264Filter(int filter);
+
 
 #ifdef DEV
-    int test();
-    int test2();
+       int test();
+       int test2();
 #endif
 private:
-  int EnterIframePlayback();
+       int EnterIframePlayback();
 #ifdef NEW_DS_MECHANISMENS
-  void dstest();  
-   void initFilterDatabase();
-  IBaseFilter *getVideoFilter();  VideoFilterDescList videofilterlist;
-  int  videofilterselected;
+       void dstest();  
+       void initFilterDatabase();
+       IBaseFilter *getVideoFilter();  
+       VideoFilterDescList videofilterlist;
+       int  videofilterselected;
+
+       void initH264FilterDatabase();
+       IBaseFilter *getVideoH264Filter();  
+       VideoFilterDescList videoH264filterlist;
+       int  videoH264filterselected;
 #endif
-  int dsInitVideoFilter();
-  IMediaControl* dsmediacontrol;
-
-  IGraphBuilder* dsgraphbuilder;
-  IMediaSample* cur_audio_media_sample;
-  IMediaSample* cur_video_media_sample;
-  IBaseFilter* dsvmrrenderer;
-  IVMRSurfaceAllocatorNotify9  *dsvmrsurfnotify;
-  IReferenceClock *dsrefclock;
-  IMediaFilter* dsmediafilter;
-  IBasicAudio* dsbasicaudio;
-  REFERENCE_TIME cr_time;
-
-  DsSourceFilter* sourcefilter;
-  DsAllocator* allocatorvmr;
-  HANDLE filtermutex;
-  void CleanupDS();
-  bool offsetnotset;
-  bool offsetvideonotset;
-  bool offsetaudionotset;
-  long long startoffset;
-  long long lastrefvideotime;
-  long long lastrefaudiotime;
-  bool dsinited;
-  bool firstsynched;
-  bool audioon;
-  bool videoon;
-  bool iframemode;
-  UCHAR pseudotvsize;
-  REFERENCE_TIME lastreftimeRT;
-  ULLONG lastreftimePTS;
-  unsigned int videoposx;
-  unsigned int videoposy;
-  int lastaudiomode;
-  int audiovolume;
-  UCHAR aud_type;
-  unsigned int vmrdeinterlacing; 
+       int dsInitVideoFilter();
+       IMediaControl* dsmediacontrol;
+
+       IGraphBuilder* dsgraphbuilder;
+       IMediaSample* cur_audio_media_sample;
+       IMediaSample* cur_video_media_sample;
+       IBaseFilter* dsrenderer;
+       IVMRSurfaceAllocatorNotify9  *dsvmrsurfnotify;
+       IReferenceClock *dsrefclock;
+       IMediaFilter* dsmediafilter;
+       IBasicAudio* dsbasicaudio;
+       REFERENCE_TIME cr_time;
+
+       DsSourceFilter* sourcefilter;
+       DsAllocator* allocatorvmr;
+       HANDLE filtermutex;
+       void CleanupDS();
+       bool offsetnotset;
+       bool offsetvideonotset;
+       bool offsetaudionotset;
+       long long startoffset;
+       long long lastrefvideotime;
+       long long lastrefaudiotime;
+       bool dsinited;
+       bool firstsynched;
+       bool audioon;
+       bool videoon;
+       bool iframemode;
+       UCHAR pseudotvsize;
+       REFERENCE_TIME lastreftimeRT;
+       ULLONG lastreftimePTS;
+       unsigned int videoposx;
+       unsigned int videoposy;
+       int lastaudiomode;
+       int audiovolume;
+       UCHAR aud_type;
+       unsigned int vmrdeinterlacing; 
+       VideoPresenter currentpresenter;
 #ifdef DS_DEBUG
-  DWORD graphidentifier;
+       DWORD graphidentifier;
 #endif
 };
 
index 00a7c06ab5a418295051a03c7edb3af9dd33d63c..af6cd2cfea272f7fe0d81c251abc8d0841b1fb98 100644 (file)
 #include "mediaplayer.h"
 #include "log.h"
 
+const int VMediaView::EVENT_SLIDESHOW=100;
+const int VMediaView::EVENT_DRAWINGDONE=101;
+const int VMediaView::EVENT_DRAWINGERROR=102;
+const int VMediaView::EVENT_DIRECTORYDONE=103;
+
+
 /**
   * the combined user interface for pictures and audio
   * has 2 surfaces to enable drawing in a separate thread
index ba4164c1883604ed73fbecc800b7968441098c0b..14073e4e04ff466c89a5c899ceab0120dc46e5c8 100644 (file)
@@ -75,10 +75,10 @@ class VMediaView : public Boxx, public TimerReceiver
     bool isAudioPlaying();
 
     //player event parameters - no interference with audioplayer! - so we start at 100
-    const static int EVENT_SLIDESHOW=100;
-    const static int EVENT_DRAWINGDONE=101;
-    const static int EVENT_DRAWINGERROR=102;
-    const static int EVENT_DIRECTORYDONE=103;
+    const static int EVENT_SLIDESHOW;
+    const static int EVENT_DRAWINGDONE;
+    const static int EVENT_DRAWINGERROR;
+    const static int EVENT_DIRECTORYDONE;
 
   private:
 
@@ -194,4 +194,6 @@ class VMediaView : public Boxx, public TimerReceiver
 
  };
 
+
+
 #endif
index 73db089693e7158e2053e4b043925bb427b65409..eeaaf4c3b8bc91c29f6b3c1f343bfe66dcf5d8fc 100644 (file)
@@ -35,6 +35,7 @@ class VDR;
 class Video;
 class PlayerRadio;
 class Timers;
+class BoxStack;
 
 class VRadioRec : public Boxx, public TimerReceiver
 {
index 965bbd93120331801d15fac90bee771403b1d0e6..f655ae01e12a0389dddf6c185ba8f4be01b23aa0 100644 (file)
@@ -66,7 +66,7 @@ VRecording::VRecording(RecMan* trecman, Recording* trec)
   summary.setSize(area.w - 20, area.h - 30 - 15 - 50);
   summary.setParaMode(true);
 
-  if (strlen(rec->recInfo->summary))
+  if (rec->recInfo &&strlen(rec->recInfo->summary))
     summary.setText(rec->recInfo->summary);
   else
     summary.setText(tr("Summary unavailable"));
index 2e96a3668104a17fc6859902ad36c45eccb9e97a..bf96f2b693f4c56cab1d3bd180a74a943c247114 100644 (file)
@@ -104,11 +104,12 @@ void VRecordingList::drawData(bool doIndexPop)
     currentRec = *j;
     time_t recStartTime = (time_t)currentRec->getStartTime();
     btime = localtime(&recStartTime);
-#ifndef _MSC_VER
-    strftime(tempA, 299, "%0d/%0m %0H:%0M ", btime);
-#else
+//NMT does not like this too!
+       //#ifndef _MSC_VER
+//    strftime(tempA, 299, "%0d/%0m %0H:%0M ", btime);
+//#else
     strftime(tempA, 299, "%d/%m %H:%M ", btime);
-#endif
+//#endif
     sprintf(tempB, "%s\t%s", tempA, currentRec->getProgName());
     currentRec->index = sl.addOption(tempB, 0, first);
     first = 0;
@@ -338,8 +339,9 @@ int VRecordingList::doPlay(bool resume)
   {
     toPlay->loadRecInfo(); // check if still need this
     toPlay->loadMarks();
+       bool ish264;
 
-    bool isRadio = toPlay->isRadio();
+    bool isRadio = toPlay->isRadio(ish264);
 
     if (isRadio)
     {
@@ -351,11 +353,30 @@ int VRecordingList::doPlay(bool resume)
     }
     else
     {
-      VVideoRec* vidrec = new VVideoRec(toPlay);
-      vidrec->draw();
-      boxstack->add(vidrec);
-      boxstack->update(vidrec);
-      vidrec->go(resume);
+               if (ish264 && !Video::getInstance()->supportsh264()) {
+                       VInfo* vi = new VInfo();
+                       vi->setSize(360, 200);
+                       vi->createBuffer();
+                       if (Video::getInstance()->getFormat() == Video::PAL)
+                               vi->setPosition(190, 170);
+                       else
+                               vi->setPosition(180, 120);
+                       vi->setOneLiner(tr("H264 video not supported"));
+                       vi->setExitable();
+                       vi->setBorderOn(1);
+                       vi->setTitleBarColour(Colour::DANGER);
+                       vi->okButton();
+                       vi->draw();
+                       boxstack->add(vi);
+                       boxstack->update(vi);
+                       
+               } else {
+                       VVideoRec* vidrec = new VVideoRec(toPlay, ish264);
+                       vidrec->draw();
+                       boxstack->add(vidrec);
+                       boxstack->update(vidrec);
+                       vidrec->go(resume);
+               }
     }
     return 1;
   }
index 1a506ed49d631723106094fc6b6f343b1f42c861..c84c9a6fac86c6eba5e1af535e9f4c324faa0e82 100644 (file)
@@ -18,6 +18,8 @@
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
 
+#include <math.h>
+
 #include "vvideorec.h"
 #include "vteletextview.h"
 
@@ -41,7 +43,7 @@
 #include "log.h"
 #include "channel.h"
  
-VVideoRec::VVideoRec(Recording* rec)
+VVideoRec::VVideoRec(Recording* rec, bool ish264)
 {
   boxstack = BoxStack::getInstance();
   vdr = VDR::getInstance();
@@ -53,8 +55,10 @@ VVideoRec::VVideoRec(Recording* rec)
   videoMode = video->getMode();
   myRec = rec;
 
+  video->seth264mode(ish264);
+
   player = new Player(Command::getInstance(), this, this);
-  player->init(myRec->IsPesRecording);
+  player->init(myRec->IsPesRecording,myRec->recInfo->fps);
 
   playing = false;
 
@@ -289,7 +293,7 @@ int VVideoRec::handleCommand(int command)
         // skip to previous mark
         Log* logger = Log::getInstance();
         int currentFrame = (player->getCurrentFrameNum()); // get current Frame
-        currentFrame -= 5 * video->getFPS(); // subtrack 5 seconds, else you cannot skip more than once back ..
+        currentFrame -= 5. * myRec->recInfo->fps; // subtrack 5 seconds, else you cannot skip more than once back ..
 
         int prevMark = myRec->getPrevMark(currentFrame); // find previous Frame
         if (prevMark)
@@ -453,7 +457,7 @@ void VVideoRec::processMessage(Message* m)
         {
           // chasing playback
           // Work out an approximate length in frames (good to 1s...)
-          lengthFrames = (myRec->recInfo->timerEnd - myRec->recInfo->timerStart) * video->getFPS();
+                       lengthFrames = (ULONG)((double)(myRec->recInfo->timerEnd - myRec->recInfo->timerStart) * myRec->recInfo->fps);
         }
         else
         {
@@ -866,6 +870,22 @@ void VVideoRec::timercall(int clientReference)
   }
 }
 
+hmsf VVideoRec::framesToHMSF(ULONG frames)
+{
+  hmsf ret;
+  /* from vdr */
+  double Seconds;
+  double fps=myRec->recInfo->fps;
+  ret.frames= int(modf((frames + 0.5) / fps, &Seconds) * fps + 1);
+  int s = int(Seconds);
+  ret.seconds=s % 60;
+  ret.minutes = s / 60 % 60;
+  ret.hours = s / 3600;
+
+
+  return ret;
+}
+
 void VVideoRec::drawBarClocks()
 {
   if (barScanHold)
@@ -907,15 +927,15 @@ void VVideoRec::drawBarClocks()
   {
     // chasing playback
     // Work out an approximate length in frames (good to 1s...)
-    lengthFrames = (myRec->recInfo->timerEnd - myRec->recInfo->timerStart) * video->getFPS();
+    lengthFrames =(ULONG) ((double)(myRec->recInfo->timerEnd - myRec->recInfo->timerStart) * myRec->recInfo->fps);
   }
   else
   {
     lengthFrames = player->getLengthFrames();
   }
 
-  hmsf currentFrameHMSF = video->framesToHMSF(currentFrameNum);
-  hmsf lengthHMSF = video->framesToHMSF(lengthFrames);
+  hmsf currentFrameHMSF = framesToHMSF(currentFrameNum);
+  hmsf lengthHMSF = framesToHMSF(lengthFrames);
 
   char buffer[100];
   if (currentFrameNum >= lengthFrames)
@@ -984,12 +1004,12 @@ void VVideoRec::drawBarClocks()
   {
     // Draw blips where start and end margins probably are
 
-    posPix = 302 * startMargin * video->getFPS() / lengthFrames;
+         posPix =(int) (302. * myRec->recInfo->fps * ((double)startMargin) /((double) lengthFrames));
 
     rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 - 2, 2, 2, Colour::LIGHTTEXT);
     rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 + 24, 2, 2, Colour::LIGHTTEXT);
 
-    posPix = 302 * (lengthFrames - endMargin * video->getFPS()) / lengthFrames;
+    posPix = (int)(302. * ((double)lengthFrames - ((double)endMargin) * myRec->recInfo->fps) / ((double)lengthFrames));
 
     rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 - 2, 2, 2, Colour::LIGHTTEXT);
     rectangle(barRegion.x + progBarXbase + 2 + posPix, barRegion.y + 12 + 24, 2, 2, Colour::LIGHTTEXT);
index 081c88b2ba7601c3df9da571861a9c0057cdddc6..3f10acf61b120aada6fff9c9b530dcb8d53ce969 100644 (file)
@@ -30,8 +30,9 @@
 #include "colour.h"
 #include "osdreceiver.h"
 
+#include "video.h"
+
 class VDR;
-class Video;
 class Timers;
 class Player;
 class Recording;
@@ -41,12 +42,15 @@ class BoxStack;
 class VInfo;
 class Bitmap;
 
+
+
+
 //#include "vepg.h" // for testing EPG in NTSC with a NTSC test video
 
 class VVideoRec : public Boxx, public TimerReceiver, public OSDReceiver
 {
   public:
-    VVideoRec(Recording* rec);
+    VVideoRec(Recording* rec, bool ish264);
     ~VVideoRec();
     void preDelete();
     int handleCommand(int command);
@@ -61,6 +65,8 @@ class VVideoRec : public Boxx, public TimerReceiver, public OSDReceiver
 
     void doTeletext();
 
+       hmsf framesToHMSF(ULONG frames); //moved from video, this is a recording property, if needed elsewhere -> recording
+
   private:
     BoxStack* boxstack;
     VDR* vdr;
index 6306fc6094d66e1222404355b5c87776a7e2234a..3f927930ddb1979b7eb2cb7733921ff1cf5b6c2d 100644 (file)
@@ -68,12 +68,24 @@ VWelcome::VWelcome()
   sl.addOption(tr("2. Radio"), 2, 0);
   sl.addOption(tr("3. Recordings"), 3, 0);
   sl.addOption(tr("4. Timers"), 4, 0);
+#ifndef _MIPS_ARCH 
+#ifndef WIN32 
   sl.addOption(tr("5. MediaPlayer"), 5, 0);
+#endif
+#endif
   sl.addOption(tr("6. Options"), 6, 0);
+#ifndef _MIPS_ARCH
   sl.addOption(tr("7. Reboot"), 7, 0);
+#else
+    sl.addOption(tr("7. Exit to Gaya"), 7, 0);
+#endif
 
   jpeg.setPosition(240, 60);
+#ifndef _MIPS_ARCH  
   jpeg.init("/vdr.jpg");
+#else
+  jpeg.init("vdr.jpg");
+#endif
   add(&jpeg);
 }
 
index befa19069fe3f7204419561e3d4d0d37cbbe8fd7..9b261f07c209973360f3c564754ac079cbc1481c 100644 (file)
@@ -341,8 +341,9 @@ INT WINAPI WinMain( HINSTANCE hinst , HINSTANCE previnst, LPSTR cmdline, int cmd
         };
       }
     } else {
-      //Render
-      ((OsdWin*)osd)->Render();
+      //Render, moved to OSD !
+               Sleep(20);
+      //((OsdWin*)osd)->Render();
     }
   }
   // When that returns quit ------------------------------------------------------------------------------------------
@@ -386,9 +387,15 @@ void CalculateWindowSize(RECT * size,ULONG size_mode) {
   }
   width=size->right-size->left-adjwidth;
   height=size->bottom-size->top-adjheight;
-  UCHAR mode=video->getMode();
-  UCHAR aspect=((VideoWin*)video)->getAspectRatio();
-  UCHAR tvsize=((VideoWin*)video)->getPseudoTVsize();
+  UCHAR mode=Video::PAL;
+  UCHAR aspect=Video::ASPECT4X3;
+  UCHAR tvsize=Video::ASPECT4X3;
+  if (video) {
+      mode=video->getMode();
+      aspect=((VideoWin*)video)->getAspectRatio();
+      tvsize=((VideoWin*)video)->getPseudoTVsize();
+  }
+
   double aspectrt=4./3.;
   if (tvsize==Video::ASPECT16X9) {
     if (aspect==Video::ASPECT16X9) {
@@ -568,10 +575,11 @@ LONG FAR PASCAL WindowProc(HWND wind, UINT msg, WPARAM wparam, LPARAM lparam)
         if (wparam == SIZE_MAXIMIZED) {
             ToggleFullscreen();
             return 0;
-        } else if (wparam == SIZE_MINIMIZED) {
+        } /*else if (wparam == SIZE_MINIMIZED) {
             ToggleFullscreen();
             return 0;
-        }
+        }*/
+        //AdjustWindow();
         }
         break;
    case WM_PAINT:
index 7b25abb96df249ed0817186fe254e4657711309c..2d6b387493ca3622e192a90c075a7e369d2a309d 100644 (file)
--- a/wjpeg.cc
+++ b/wjpeg.cc
@@ -464,6 +464,7 @@ get_exif_orient (j_decompress_ptr cinfo)
 {
         unsigned int tmp, offset, length, numtags;
         int orient=-1;
+        jpegUserData * ud=0;
         boolean swap;
         orient = 1;
         offset = 0;
@@ -507,7 +508,7 @@ get_exif_orient (j_decompress_ptr cinfo)
         if( orient==0 || orient>8 ) orient = 1;
         
         Log::getInstance()->log("WJpeg", Log::DEBUG, "read exif orientation %u", orient);
-        jpegUserData * ud=(jpegUserData *)(mysrc->userdata);
+        ud=(jpegUserData *)(mysrc->userdata);
         switch(orient) {
           case 3:
             ud->ctl->exifRotation=WJpeg::ROT_180;