Committing patch from Dan Fischer
authorJan Schmidt <thaytan@mad.scientist.com>
Mon, 6 Jan 2003 15:07:21 +0000 (15:07 +0000)
committerJan Schmidt <thaytan@mad.scientist.com>
Mon, 6 Jan 2003 15:07:21 +0000 (15:07 +0000)
Original commit message from CVS:
Committing patch from Dan Fischer
Adds ability to skip partial frames, and 'skip' and 'consecutive' parameters
Plugin now sets source caps to indicate PAL or NTSC
The kino developers relicensed the code snippet from kino under the LGPL

ext/raw1394/gst1394.c
ext/raw1394/gstdv1394src.c
ext/raw1394/gstdv1394src.h

index 9ad4ac7..e330205 100644 (file)
@@ -30,8 +30,9 @@ static GstElementDetails gst_dv1394src_details = {
   "LGPL",
   "Source for DV video data from firewire port",
   VERSION,
-  "Erik Walthinsen <omega@temple-baptist.com>",
-  "(C) 2001",
+  "Erik Walthinsen <omega@temple-baptist.com>\n"
+  "Daniel Fischer <dan@f3c.com>",
+  "(C) 2001-2002",
 };
 
 
index a14cb70..8efefe2 100644 (file)
@@ -1,5 +1,6 @@
 /* GStreamer
  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ *               <2000> Daniel Fischer <dan@f3c.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  */
 
 #include <gst/gst.h>
+#include <string.h>
 #include "gstdv1394src.h"
 
+#define N_BUFFERS_IN_POOL 3
+
+#define PAL_FRAMESIZE 144000
+#define NTSC_FRAMESIZE 120000
 
 /* Filter signals and args */
 enum {
@@ -28,7 +34,10 @@ enum {
 };
 
 enum {
-  ARG_0
+  ARG_0,
+  ARG_CONSECUTIVE,
+  ARG_SKIP,
+  ARG_DROP_INCOMPLETE,
 };
 
 #if 0
@@ -42,12 +51,18 @@ gst_dv1394src_factory (void)
       "src",
       GST_PAD_SRC,
       GST_PAD_ALWAYS,
-      gst_caps_new (
+      GST_CAPS_NEW (
         "dv1394src",
         "video/dv",
+/*
        gst_props_new (
-          "format", GST_PROPS_STRING ("NTSC"),
-         NULL)),
+          "format", GST_PROPS_LIST (
+                       GST_PROPS_STRING ("NTSC"),
+                       GST_PROPS_STRING ("PAL")
+                       ), 
+         NULL)
+       ),
+*/  
       NULL);
   }
   return template;
@@ -96,6 +111,16 @@ gst_dv1394src_class_init (GstDV1394SrcClass *klass)
   gobject_class = (GObjectClass*)klass;
   gstelement_class = (GstElementClass*)klass;
 
+  g_object_class_install_property( G_OBJECT_CLASS(klass), ARG_CONSECUTIVE,
+       g_param_spec_int("consecutive","consecutive frames","send n consecutive frames after skipping",
+                       1, G_MAXINT,1,G_PARAM_READWRITE));
+  g_object_class_install_property( G_OBJECT_CLASS(klass), ARG_SKIP,
+       g_param_spec_int("skip","skip frames","skip n frames",
+                       0, G_MAXINT,1,G_PARAM_READWRITE));
+  g_object_class_install_property( G_OBJECT_CLASS(klass), ARG_DROP_INCOMPLETE,
+       g_param_spec_boolean("drop_incomplete","drop_incomplete","drop incomplete frames",
+                       TRUE, G_PARAM_READWRITE));
+
   parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
 
   gobject_class->set_property = gst_dv1394src_set_property;
@@ -114,6 +139,18 @@ gst_dv1394src_init (GstDV1394Src *dv1394src)
   dv1394src->card = 0;
   dv1394src->port = 0;
   dv1394src->channel = 63;
+  
+  dv1394src->consecutive = 1;
+  dv1394src->skip = 0;
+  dv1394src->drop_incomplete = TRUE;
+  
+  /* initialized when first header received */
+  dv1394src->frameSize=0; 
+  dv1394src->pool = NULL;
+  dv1394src->buf = NULL;
+  dv1394src->frame = NULL;
+  dv1394src->frameSequence = 0;
 }
 
 static void
@@ -126,6 +163,15 @@ gst_dv1394src_set_property (GObject *object, guint prop_id, const GValue *value,
   filter = GST_DV1394SRC(object);
 
   switch (prop_id) {
+    case ARG_SKIP:
+       filter->skip = g_value_get_int(value);
+       break;
+    case ARG_CONSECUTIVE:
+       filter->consecutive = g_value_get_int(value);
+       break;
+    case ARG_DROP_INCOMPLETE:
+       filter->drop_incomplete = g_value_get_boolean(value);
+       break;
     default:
       break;
   }
@@ -141,6 +187,15 @@ gst_dv1394src_get_property (GObject *object, guint prop_id, GValue *value, GPara
   filter = GST_DV1394SRC(object);
 
   switch (prop_id) {
+    case ARG_SKIP:
+       g_value_set_int( value, filter->skip );
+        break;
+    case ARG_CONSECUTIVE:
+       g_value_set_int( value, filter->consecutive );
+        break;
+    case ARG_DROP_INCOMPLETE:
+        g_value_set_boolean( value, filter->drop_incomplete );
+       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -150,23 +205,103 @@ gst_dv1394src_get_property (GObject *object, guint prop_id, GValue *value, GPara
 static
 int gst_dv1394src_iso_receive(raw1394handle_t handle,int channel,size_t len,quadlet_t *data) {
   GstDV1394Src *dv1394src = GST_DV1394SRC (raw1394_get_userdata(handle));
-  unsigned char *ptr = (unsigned char *)&data[3];
-  GstBuffer *buf;
 
   if (len > 16) {
-/*fprintf(stderr,"section_type %d, dif_sequence %d, dif_block %d\n",ptr[0] >> 5,ptr[1] >> 4,ptr[2]); */
-fprintf(stderr,".");
-    if (((ptr[0] >> 5) == 0) &&
-        ((ptr[1] >> 4) == 0) && (ptr[2] == 0)) dv1394src->started = TRUE;
-    if (dv1394src->started) {
-      buf = gst_buffer_new();
-      GST_BUFFER_DATA(buf) = ptr;
-      GST_BUFFER_SIZE(buf) = 480;
-      GST_BUFFER_OFFSET(buf) = 0;
-      GST_BUFFER_FLAG_SET(buf,GST_BUFFER_DONTFREE);
-
-      dv1394src->buf = buf;
-    }
+       /*
+                the following code taken from kino-0.51 (Dan Dennedy/Charles Yates)
+       */
+        unsigned char *p = (unsigned char*) & data[3];
+        int section_type = p[0] >> 5;           /* section type is in bits 5 - 7 */
+        int dif_sequence = p[1] >> 4;           /* dif sequence number is in bits 4 - 7 */
+        int dif_block = p[2];
+
+        /* if we are at the beginning of a frame, 
+          we set buf=frame, and get a new buffer from pool for frame
+        */
+
+        if (section_type == 0 && dif_sequence == 0) {  // dif header
+       
+          if( dv1394src->pool == NULL ) {
+            // figure format (NTSC/PAL)
+            if( p[3] & 0x80 ) {
+              // PAL
+              dv1394src->frameSize = PAL_FRAMESIZE;
+              GST_DEBUG(0,"PAL data");
+              if (gst_pad_try_set_caps (dv1394src->srcpad, 
+                        GST_CAPS_NEW ( "dv1394src", "video/dv",
+                                      "format", GST_PROPS_STRING("PAL"),
+                                      NULL)
+              ) <= 0) {
+                GST_ERROR(GST_ELEMENT(dv1394src), "Could not set source caps for PAL");
+                return 0;
+              }
+            } else {
+              // NTSC (untested)
+              dv1394src->frameSize = NTSC_FRAMESIZE;
+              GST_DEBUG(0,"NTSC data [untested] - please report success/failure to <dan@f3c.com>");
+              if (gst_pad_try_set_caps (dv1394src->srcpad, 
+                        GST_CAPS_NEW ( "dv1394src", "video/dv",
+                                      "format", GST_PROPS_STRING ("NTSC"),
+                                      NULL)
+              ) <= 0) {
+                GST_ERROR(GST_ELEMENT(dv1394src), "Could not set source caps for NTSC");
+                return 0;
+              }
+            }
+
+            dv1394src->pool = gst_buffer_pool_get_default( dv1394src->frameSize, N_BUFFERS_IN_POOL );
+            if (dv1394src->pool == NULL) {
+              GST_ERROR(GST_ELEMENT(dv1394src), "gst_buffer_pool_get_default returned NULL");
+            }
+          }
+  
+          // drop last frame when not complete
+          if( !dv1394src->drop_incomplete || dv1394src->bytesInFrame == dv1394src->frameSize ) { 
+            dv1394src->buf = dv1394src->frame;
+          } else {
+            GST_INFO_ELEMENT(GST_CAT_PLUGIN_INFO, GST_ELEMENT(dv1394src), "incomplete frame dropped"); 
+          }
+          dv1394src->frame = NULL;
+
+          dv1394src->frameSequence++;
+
+          if( dv1394src->frameSequence % (dv1394src->skip+dv1394src->consecutive) < dv1394src->consecutive ) {
+            if( dv1394src->pool ) dv1394src->frame = gst_buffer_new_from_pool( dv1394src->pool, 0, dv1394src->frameSize );
+              dv1394src->bytesInFrame = 0;
+            }
+          }
+
+          if (dv1394src->frame != NULL) {
+            void *data = GST_BUFFER_DATA( dv1394src->frame );
+
+
+            switch (section_type) {
+            case 0: /* 1 Header block */
+                /* p[3] |= 0x80; // hack to force PAL data */
+                memcpy(data + dif_sequence * 150 * 80, p, 480);
+                break;
+
+            case 1: /* 2 Subcode blocks */
+                memcpy(data + dif_sequence * 150 * 80 + (1 + dif_block) * 80, p, 480);
+                break;
+
+            case 2: /* 3 VAUX blocks */
+                memcpy(data + dif_sequence * 150 * 80 + (3 + dif_block) * 80, p, 480);
+                break;
+
+            case 3: /* 9 Audio blocks interleaved with video */
+                memcpy(data + dif_sequence * 150 * 80 + (6 + dif_block * 16) * 80, p, 480);
+                break;
+
+            case 4: /* 135 Video blocks interleaved with audio */
+                memcpy(data + dif_sequence * 150 * 80 + (7 + (dif_block / 15) + dif_block) * 80, p, 480);
+                break;
+
+            default: /* we canĀ“t handle any other data */
+                break;
+            }
+            dv1394src->bytesInFrame += 480;
+        }
   }
 
   return 0;
@@ -234,6 +369,10 @@ gst_dv1394src_change_state (GstElement *element)
       raw1394_stop_iso_rcv(dv1394src->handle, dv1394src->channel);
       break;
     case GST_STATE_READY_TO_NULL:
+      if (dv1394src->pool != NULL) {
+        gst_buffer_pool_unref(dv1394src->pool);
+        dv1394src->pool = NULL;
+      }
       raw1394_destroy_handle(dv1394src->handle);
       break;
     default:
index b934033..8de7c54 100644 (file)
@@ -51,6 +51,11 @@ struct _GstDV1394Src {
 
   GstPad *srcpad;
 
+  // consecutive=2, skip=4 will skip 4 frames, then let 2 consecutive ones thru
+  gint consecutive;
+  gint skip;
+  gboolean drop_incomplete;
+
   int numcards,numports;
   int card,port,channel;
 
@@ -59,6 +64,12 @@ struct _GstDV1394Src {
 
   gboolean started;
   GstBuffer *buf;
+  
+  GstBuffer *frame;
+  guint frameSize;
+  guint bytesInFrame;
+  guint frameSequence;
+  GstBufferPool *pool;
 };
 
 struct _GstDV1394SrcClass {