On Saturday 13 September 2008, Laz wrote:
> On Saturday 13 September 2008 17:24:46 Laz wrote:
> > On Saturday 13 September 2008 17:13:00 Stefan Lucke wrote:
> > > Can you both try attached patch ?

> > > 2nd Feature makes field selectable which is displayed in still picture
> > >     mode, but unfortunately this doesn't work at the moment.
> >
> 
> Excellent: I had toyed with the idea of implementing that in the past but 
> never got anywhere! I take it that this will remove flicker from a paused 
> interlaced stream?

Here is an other version of the patch.
2nd feature seems to work most of the time.

When switching between play / pause real fast, it doesn't work,
as the frame is displayed just before the Freeze() command arrives.

-- 
Stefan Lucke
Index: mpeg2decoder.c
===================================================================
RCS file: /cvsroot/softdevice/softdevice/mpeg2decoder.c,v
retrieving revision 1.83
diff -U3 -r1.83 mpeg2decoder.c
--- mpeg2decoder.c      20 Jul 2008 16:41:01 -0000      1.83
+++ mpeg2decoder.c      14 Sep 2008 16:29:56 -0000
@@ -1047,6 +1047,8 @@
   IsSuspended=false;
   Speed=1;
   pb = NULL;
+
+  useAVReadFrame = setupStore->useAVReadFrame;
 }
 
 cMpeg2Decoder::~cMpeg2Decoder()
@@ -1176,15 +1178,21 @@
           usleep(50000);
 
         BUFDEB("av_read_frame start\n");
-        ret = av_read_frame(ic, &pkt);
-        //ret = av_read_packet(ic, &pkt);
+
+        if (useAVReadFrame)
+            ret = av_read_frame(ic, &pkt);
+        else
+            ret = av_read_packet(ic, &pkt);
+
         if (ret < 0) {
             BUFDEB("cMpeg2Decoder Stream Error!\n");
             if (ThreadActive)
-                   usleep(10000);
+                usleep(10000);
             continue;
         }
-        av_dup_packet(&pkt);
+        if (useAVReadFrame)
+            av_dup_packet(&pkt);
+
         PacketCount++;
         BUFDEB("got packet from av_read_frame!\n");
 
@@ -1413,6 +1421,8 @@
 {
   CMDDEB("Play\n");
   freezeMode=false;
+fprintf(stderr,"MP Play\n");
+  videoOut->SetStillPictureMode (false);
   if (running)
   {
     aoutMutex.Lock();
@@ -1433,6 +1443,9 @@
 {
   curPlayMode=playMode;
   this->packetMode=packetMode;
+fprintf(stderr,"MP SetPlayMode (%d, packetMode(%s))\n",playMode, 
packetMode?"ON":"OFF");
+
+  videoOut->SetStillPictureMode (false);
   switch (curPlayMode) {
     case PmAudioVideo:
       CMDDEB("SetPlayMode PmAudioVideo\n");
@@ -1456,6 +1469,10 @@
   CMDDEB("Freeze Streams %d freeze %d\n",Stream,freeze);
   if (Stream & SOFTDEVICE_BOTH_STREAMS == SOFTDEVICE_BOTH_STREAMS )
     freezeMode=freeze;
+fprintf(stderr,"MP Freeze(%s)\n", freeze ? "ON":"OFF");
+  if (freeze)
+    videoOut->SetStillPictureMode (true);
+
   // sleep a short while before putting the
   // audio and video stream decoders to sleep
   usleep(20000);
@@ -1537,41 +1554,47 @@
 
 /* ----------------------------------------------------------------------------
  */
-
 static uint8_t pes_packet_header[] = {
      0x00,0x00,0x01, 0xe0,           0x00,0x00,   0x84, 0x00, 0x00,0x00};
      // startcode,  video-stream 0, packet length,      no pts
+
+/* ----------------------------------------------------------------------------
+ */
 int cMpeg2Decoder::StillPicture(uchar *Data, int Length)
 {
-  bool has_pesheader=false;
-  CMDDEB("StillPicture %p length %d \n",Data,Length);
+  bool has_pesheader = false;
+  CMDDEB("StillPicture %p length %d \n", Data,Length);
   // XXX hack to ingore audio junk sent by vdr in the still picture
-  AudioIdx=DONT_PLAY;
+  AudioIdx = DONT_PLAY;
 
   // check if data contains a valid pes header
 #define SEARCH_LENGTH 64
-  if (Length>SEARCH_LENGTH) {
-    uchar *start=Data+1;
+  if (Length > SEARCH_LENGTH) {
+    uchar *start = Data + 1;
     do {
       start++;
-      start=(uchar *)memchr(start,0x01,Data+SEARCH_LENGTH-start);
-      if ( start && start[-1]==0 && start[-2] == 0
-          && ((start[1] &0xF0)==0xe0) ) { // video stream pes header
-        has_pesheader=true;
+      start = (uchar *) memchr (start, 0x01, Data + SEARCH_LENGTH - start);
+      if ( start &&
+           start[-1] == 0 && start[-2] == 0 && 
+           ((start[1] &0xF0) == 0xe0) ) { // video stream pes header
+        has_pesheader = true;
         break;
-      };
-    } while (start<Data+SEARCH_LENGTH && start);
-  };
+      }
+    } while (start < Data + SEARCH_LENGTH && start);
+  }
 
-  for (int i=0; 4>i;i++) {
+  videoOut->SetStillPictureMode (true);
+  for (int i = 0; 4 > i; i++) {
     if (!has_pesheader) {
       // send a fake pes header
-      pes_packet_header[4]=(Length+2)>>8 & 0xFF;
-      pes_packet_header[5]=(Length+2) & 0xFF;
-      Decode(pes_packet_header,9);
-    };
-    Decode(Data,Length);
+      pes_packet_header[4] = (Length + 2) >> 8 & 0xFF;
+      pes_packet_header[5] = (Length + 2) & 0xFF;
+      Decode (pes_packet_header, 9);
+    }
+    Decode (Data,Length);
   }
+  //videoOut->SetStillPictureMode (false);
+
   CMDDEB("StillPicture end \n");
   return Length;
 }
@@ -1582,6 +1605,7 @@
 {
   mutex.Lock();
   CMDDEB("Clear\n");
+  videoOut->SetStillPictureMode (true);
   Stop(false);
   Start(false);
   CMDDEB("Clear finished\n");
@@ -1593,6 +1617,7 @@
 void cMpeg2Decoder::TrickSpeed(int trickSpeed)
 {
   CMDDEB("TrickSpeed %d\n",Speed);
+fprintf(stderr,"MP TrickSpeed A (%d -> %d)\n", Speed, trickSpeed);
   Speed=trickSpeed;
   // XXX hack to ingore audio junk sent by vdr in the
   if (trickSpeed!=1) {
@@ -1604,6 +1629,11 @@
     AudioIdx=DONT_PLAY;
   } else if (AudioIdx==DONT_PLAY)
     AudioIdx=NO_STREAM;
+
+  if (trickSpeed > 1)
+    videoOut->SetStillPictureMode (true);
+fprintf(stderr,"MP TrickSpeed B (%d -> %d)\n", Speed, trickSpeed);
+
   Play();
   if (running)
   {
Index: mpeg2decoder.h
===================================================================
RCS file: /cvsroot/softdevice/softdevice/mpeg2decoder.h,v
retrieving revision 1.44
diff -U3 -r1.44 mpeg2decoder.h
--- mpeg2decoder.h      26 Feb 2008 08:06:18 -0000      1.44
+++ mpeg2decoder.h      14 Sep 2008 16:29:56 -0000
@@ -284,6 +284,7 @@
 
     AVFormatContext *ic;
     ByteIOContext   *pb;
+    bool            useAVReadFrame;
     int LastSize;
     cMutex  mutex;
     cSigTimer EnablePutSignal;
Index: setup-softdevice.c
===================================================================
RCS file: /cvsroot/softdevice/softdevice/setup-softdevice.c,v
retrieving revision 1.56
diff -U3 -r1.56 setup-softdevice.c
--- setup-softdevice.c  20 Jul 2008 16:41:01 -0000      1.56
+++ setup-softdevice.c  14 Sep 2008 16:29:57 -0000
@@ -74,6 +74,8 @@
 
 const char *fieldOrderNames[SETUP_FIELD_ORDER_NAMES];
 
+const char *preferredFieldNames[SETUP_PREFERRED_FIELD_NAMES];
+
 /* ----------------------------------------------------------------------------
  */
 cSetupStore *setupStore=NULL;
@@ -116,6 +118,8 @@
   useStretchBlit    = 0;
   stretchBlitLocked = false;
   fieldOrderMode    = 2;
+  preferredField    = bothFields;
+  useAVReadFrame    = true;
   bufferMode      = 0;
   mainMenu  = 1;
   syncTimerMode = 2;
@@ -209,6 +213,11 @@
   fieldOrderNames[1] = "Top field first";
   fieldOrderNames[2] = "Auto";
   fieldOrderNames[3] = NULL;
+
+  preferredFieldNames[0] = tr("Both Fields");
+  preferredFieldNames[1] = tr("First Field");
+  preferredFieldNames[2] = tr("Later Field");
+  preferredFieldNames[3] = NULL;
 }
 
 bool cSetupStore::SetupParse(const char *Name, const char *Value)
@@ -381,6 +390,14 @@
     fieldOrderMode = clamp (0, fieldOrderMode, 2);
     fprintf(stderr, "[setup-softdevice] fieldOrderMode: %s\n",
             fieldOrderNames[fieldOrderMode]);
+  } else if (!strcasecmp(Name, "preferredField")) {
+    preferredField = (tPreferredField) atoi (Value);
+    preferredField = (tPreferredField) clamp (bothFields, preferredField, 
laterField);
+    fprintf(stderr, "[setup-softdevice] preferrenField: %s\n",
+            preferredFieldNames[preferredField]);
+  } else if (!strcasecmp(Name, "useAVReadFrame")) {
+    useAVReadFrame = (bool) atoi (Value);
+    fprintf(stderr, "[setup-softdevice] useAVReadFrame: %s\n", 
(useAVReadFrame) ? "yes": "no");
   } else if (!strcasecmp(Name, "vidBrightness")) {
     vidBrightness = atoi (Value);
     vidBrightness = clamp (-1, vidBrightness, 100);
Index: setup-softdevice.h
===================================================================
RCS file: /cvsroot/softdevice/softdevice/setup-softdevice.h,v
retrieving revision 1.46
diff -U3 -r1.46 setup-softdevice.h
--- setup-softdevice.h  10 Sep 2008 17:15:38 -0000      1.46
+++ setup-softdevice.h  14 Sep 2008 16:29:57 -0000
@@ -105,6 +105,9 @@
 #define SETUP_FIELD_ORDER_NAMES  4
 extern const char *fieldOrderNames[SETUP_FIELD_ORDER_NAMES];
 
+#define SETUP_PREFERRED_FIELD_NAMES  4
+extern const char *preferredFieldNames[SETUP_PREFERRED_FIELD_NAMES];
+
 /* ----------------------------------------------------------------------------
  * allow changing of output pixfmt
  */
@@ -116,6 +119,14 @@
 #define SETUP_SUSPENDVIDEO 3
 extern const char *suspendVideo[SETUP_SUSPENDVIDEO];
 
+/*-----------------------------------------------------------------------------
+ */
+typedef enum preferredField {
+        bothFields,
+        earlierField,
+        laterField
+} tPreferredField;
+
 /* ---------------------------------------------------------------------------
  */
 struct cSetupStore {
@@ -149,6 +160,7 @@
     int   ppQuality;
     int   mirror;
     int   syncOnFrames;
+    bool  useAVReadFrame;
     int   avOffset;
     int   screenPixelAspect;
     int   zoom;
@@ -182,6 +194,8 @@
     char  alsaAC3Device [ALSA_DEVICE_NAME_LENGTH];
 
     int   setupStoreShmid;
+
+    tPreferredField   preferredField;
 };
 
 #define OSDMODE_PSEUDO    0
Index: setup-softdevice-menu.c
===================================================================
RCS file: /cvsroot/softdevice/softdevice/setup-softdevice-menu.c,v
retrieving revision 1.15
diff -U3 -r1.15 setup-softdevice-menu.c
--- setup-softdevice-menu.c     20 Jul 2008 16:41:01 -0000      1.15
+++ setup-softdevice-menu.c     14 Sep 2008 16:29:57 -0000
@@ -370,6 +370,15 @@
                             (SETUP_FIELD_ORDER_NAMES-1),
                             fieldOrderNames));
 
+  Add(new cMenuEditStraItem(tr("Still Picture Field"),
+                            (int *) &data->preferredField,
+                            (SETUP_PREFERRED_FIELD_NAMES-1),
+                            preferredFieldNames));
+
+  Add(new cMenuEditBoolItem(tr("Use av_read_frame()"),
+                            (int *) &data->useAVReadFrame, tr("no"), 
tr("yes")));
+
+
 #if VDRVERSNUM >= 10334
   Add(new cOsdItem(" ", osUnknown, false));
 #else
@@ -489,6 +498,8 @@
   SetupStore ("mainMenu",             setupStore->mainMenu);
   SetupStore ("syncTimerMode",        setupStore->syncTimerMode);
   SetupStore ("fieldOrderMode",       setupStore->fieldOrderMode);
+  SetupStore ("preferredField",       setupStore->preferredField);
+  SetupStore ("useAVReadFrame",       setupStore->useAVReadFrame);
   SetupStore ("vidBrightness",        setupStore->vidBrightness);
   SetupStore ("vidContrast",          setupStore->vidContrast);
   SetupStore ("vidHue",               setupStore->vidHue);
Index: softdevice.c
===================================================================
RCS file: /cvsroot/softdevice/softdevice/softdevice.c,v
retrieving revision 1.93
diff -U3 -r1.93 softdevice.c
--- softdevice.c        18 Apr 2008 15:15:41 -0000      1.93
+++ softdevice.c        14 Sep 2008 16:29:58 -0000
@@ -113,7 +113,7 @@
 #define AOUT_OSS    3
 #define AOUT_MACOS  4
 
-//#define SOFTDEB(out...) {printf("softdeb[%04d]:",(int)(getTimeMilis() % 
10000));printf(out);}
+#define SOFTDEB(out...) {printf("softdeb[%04d]:",(int)(getTimeMilis() % 
10000));printf(out);}
 
 #ifndef SOFTDEB
 #define SOFTDEB(out...)
@@ -497,9 +497,9 @@
 void cSoftDevice::Freeze(void)
 {
     SOFTDEB("Freeze...\n");
-    cDevice::Freeze();
     if (decoder)
       decoder->Freeze();
+    cDevice::Freeze();
     SOFTDEB("Freeze finished.\n");
 }
 
@@ -585,7 +585,7 @@
 int cSoftDevice::PlayAudio(const uchar *Data, int Length)
 # endif
 {
-  SOFTDEB("PlayAudio... %p length %d\n",Data,Length);
+  //SOFTDEB("PlayAudio... %p length %d\n",Data,Length);
 #if VDRVERSNUM >= 10342
   if (SHOULD_SUSPEND && !Transferring()) {
     usleep(10000); // avoid burning CPU
@@ -646,7 +646,7 @@
  */
 int cSoftDevice::PlayVideo(const uchar *Data, int Length)
 {
-  SOFTDEB("PlayVideo %x length %d\n",Data,Length);
+  //SOFTDEB("PlayVideo %x length %d\n",Data,Length);
 #if VDRVERSNUM >= 10342
   if (SHOULD_SUSPEND && !Transferring()) {
     usleep(10000); // avoid burning CPU
Index: video.c
===================================================================
RCS file: /cvsroot/softdevice/softdevice/video.c,v
retrieving revision 1.77
diff -U3 -r1.77 video.c
--- video.c     20 Jul 2008 16:41:01 -0000      1.77
+++ video.c     14 Sep 2008 16:29:58 -0000
@@ -461,6 +461,60 @@
 
 /* ---------------------------------------------------------------------------
  */
+void cVideoOut::SetStillPictureMode(bool on)
+{
+fprintf(stderr,"SetStillPictureMode: %s\n", on ? "ON " : "OFF ");
+    stillPictureMode = on;
+}
+
+/* ---------------------------------------------------------------------------
+ */
+void cVideoOut::SelectField (sPicBuffer *pic)
+{
+                unsigned char   *dest, 
+                                *src;
+                int             i;
+
+        if (!pic->interlaced_frame)
+                return;
+        if (setupStore->preferredField == bothFields)
+                return;
+
+        dest = src  = pic->pixel[0]
+                      + (pic->edge_height) * pic->stride[0]
+                      + pic->edge_width;
+
+        if (setupStore->preferredField == earlierField) {
+
+                if (pic->top_field_first)
+                        dest += pic->stride[0];
+                else
+                        src  += pic->stride[0];
+
+        } else {
+
+                if (pic->top_field_first)
+                        src  += pic->stride[0];
+                else
+                        dest += pic->stride[0];
+        }
+
+        for (i = 0; i < pic->height; i += 2) {
+#if 1
+            // copy part
+            memcpy (dest, src, pic->stride[0]);
+#else
+            // set frame to very dark
+            memset (dest, 0, pic->stride[0]);
+            memset (src, 0, pic->stride[0]);
+#endif
+            dest += 2 * pic->stride[0];
+            src  += 2 * pic->stride[0];
+        }
+}
+
+/* ---------------------------------------------------------------------------
+ */
 void cVideoOut::DrawVideo_420pl(cSyncTimer *syncTimer,
                                 sPicBuffer *pic)
 {
@@ -472,6 +526,11 @@
     return;
   }
 
+  if (stillPictureMode) {
+fprintf(stderr,"0");
+    SelectField (pic);
+  }
+
   sPicBuffer *scale_pic=NULL;
   if (scaleVid != 0) {
           scale_pic=GetBuffer(pic->format,pic->max_width,pic->max_height);
@@ -554,7 +613,7 @@
   offsetIndex %= AVRG_OFF_CNT;
 
   softlog->Log(SOFT_LOG_TRACE, 0,
-                  "[VideoOut] A/V (%d - %d) off = %d avoff = %d\n",
+                  "[VideoOut] A/V (%lld - %lld) off = %d avoff = %d\n",
                   aPTS, pts, offset, offsetAverage);
 
   dropOffset = (useAverage4Drop) ? offsetAverage : offset;
Index: video.h
===================================================================
RCS file: /cvsroot/softdevice/softdevice/video.h,v
retrieving revision 1.56
diff -U3 -r1.56 video.h
--- video.h     20 Jul 2008 16:41:01 -0000      1.56
+++ video.h     14 Sep 2008 16:29:58 -0000
@@ -66,6 +66,7 @@
     //
     sPicBuffer  *oldPicture;
     cMutex      oldPictureMutex;
+    bool        stillPictureMode;
     void        SetOldPicture(sPicBuffer *pic);
 
 protected:
@@ -192,6 +193,8 @@
             oldPictureMutex.Unlock();
     };
 
+    virtual void SetStillPictureMode (bool on);
+    virtual void SelectField (sPicBuffer *pic);
 
     virtual void Action(void);
     // osd control thread. Refreshes the osd on dimension changes and
_______________________________________________
Softdevice-devel mailing list
Softdevice-devel@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/softdevice-devel

Reply via email to