Bug 115645 - [patch] getdata returns wrong results with MULTIPLY or LINCOM of fields with different samples/frame
Summary: [patch] getdata returns wrong results with MULTIPLY or LINCOM of fields with ...
Status: RESOLVED FIXED
Alias: None
Product: kst
Classification: Applications
Component: general (show other bugs)
Version: 1.x
Platform: Slackware Linux
: NOR normal
Target Milestone: ---
Assignee: George Staikos
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-11-04 00:48 UTC by D. V. Wiebe
Modified: 2005-11-09 05:47 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
patch for LINCOM and MULTIPLY of different samples per frame (4.03 KB, patch)
2005-11-04 00:50 UTC, D. V. Wiebe
Details

Note You need to log in before you can comment on or make changes to this bug.
Description D. V. Wiebe 2005-11-04 00:48:35 UTC
Version:           1.2.0_devel (using KDE KDE 3.4.2)
Installed from:    Slackware PackagesSlackware Packages
Compiler:          gcc (GCC) 3.3.6 
OS:                Linux

This patch fixes two bugs in getdata's MULTIPLY and LINCOM generation when dealing with fields with differing samples per frame.  The two bugs are:

* getdata didn't return the number of samples requested, even when it could, but rounded the number of samples returned to an integer multiple of one of the fields' samples per frame.

* getdata didn't fetch the proper range of data from the second field when the start of the range was specified in samples and not frames.  As a result the derived vector returned was incorrect.  This was because first_frame and first_samp were being passed naively to the second DoField without taking into account the difference in samples per frame.

The supplied patch fixes both of these bugs.  For the second bug, first_frame and first_samp are taken to refer exclusively to the first field in the LINCOM (or MULTIPLY).  The starting sample for successive fields is calculated relative to this.  This is what is expected, since the samples per frame of the vector returned by getdata is equal to the samples per frame of the first field in the derived field specification.
Comment 1 D. V. Wiebe 2005-11-04 00:50:17 UTC
Created attachment 13269 [details]
patch for LINCOM and MULTIPLY of different samples per frame
Comment 2 George Staikos 2005-11-04 04:48:34 UTC
I want to review this patch before committing.  I want to make sure it doesn't cause any regressions related to the last fix I did here.
Comment 3 George Staikos 2005-11-09 05:47:34 UTC
SVN commit 479081 by staikos:

apply getdata patch by Don
BUG: 115645


 M  +42 -15    getdata.c  


--- trunk/extragear/graphics/kst/kst/datasources/dirfile/getdata.c #479080:479081
@@ -1155,7 +1155,7 @@
   struct LincomEntryType *L;
   void *tmpbuf;
   int i;
-  int spf1, spf2;
+  int spf1, spf2, num_samp2, first_samp2;
   int n_read2;
 
   /******* binary search for the field *******/
@@ -1173,6 +1173,8 @@
   spf1 = GetSPF(L->in_fields[0], F, error_code);
   if (*error_code != GD_E_OK) return(1);
 
+  /* read and scale the first field and record the number of samples
+   * returned */
   *n_read = DoField(F, L->in_fields[0],
       first_frame, first_samp,
       num_frames, num_samp,
@@ -1187,28 +1189,37 @@
     for (i=1; i<L->n_infields; i++) {
       recurse_level++;
 
+      /* find the samples per frame of the next field */
       spf2 = GetSPF(L->in_fields[i], F, error_code);
       if (*error_code != GD_E_OK) return(1);
 
-      tmpbuf = AllocTmpbuff(return_type, *n_read * (int)ceil((double)spf2 / spf1));
+      /* calculate the first sample and number of samples to read of the
+       * next field */
+      num_samp2 = (int)ceil((double)*n_read * spf2 / spf1);
+      first_samp2 = (first_frame * spf2 + first_samp * spf2 / spf1);
+
+      /* Allocate a temporary buffer for the next field */
+      tmpbuf = AllocTmpbuff(return_type, num_samp2);
       if (!tmpbuf && return_type != 'n') {
         return(0);
       }
 
-      num_samp = (*n_read * spf2 / spf1) % spf2;
-
+      /* read the next field */
       n_read2 = DoField(F, L->in_fields[i],
-            first_frame, first_samp,
-            0, *n_read * spf2 / spf1,
-            return_type, tmpbuf,
-            error_code);
+          0, first_samp2,
+          0, num_samp2,
+          return_type, tmpbuf,
+          error_code);
+      recurse_level--;
+      if (*error_code != GD_E_OK)
+        return(1);
 
+      ScaleData(tmpbuf, return_type, n_read2, L->m[i], L->b[i]);
+
       if (n_read2 > 0 && n_read2 * spf1 != *n_read * spf2) {
         *n_read = n_read2 * spf1 / spf2;
       }
 
-      recurse_level--;
-      ScaleData(tmpbuf, return_type, *n_read, L->m[i], L->b[i]);
       AddData(data_out, spf1, tmpbuf, spf2, return_type, *n_read);
 
       free(tmpbuf);
@@ -1231,7 +1242,7 @@
   struct MultiplyEntryType tM;
   struct MultiplyEntryType *M;
   void *tmpbuf;
-  int spf1, spf2;
+  int spf1, spf2, num_samp2, first_samp2;
   int n_read2;
 
   /******* binary search for the field *******/
@@ -1246,9 +1257,13 @@
   /** if we got here, we found the field! **/
   /** read into dataout and scale the first element **/
   recurse_level++;
+
+  /* find the samples per frame of the first field */
   spf1 = GetSPF(M->in_fields[0], F, error_code);
   if (*error_code != GD_E_OK) return(1);
 
+  /* read the first field and record the number of samples
+   * returned */
   *n_read = DoField(F, M->in_fields[0],
       first_frame, first_samp,
       num_frames, num_samp,
@@ -1259,23 +1274,35 @@
   if (*error_code != GD_E_OK) return(1);
 
   recurse_level++;
+
+  /* find the samples per frame of the second field */
   spf2 = GetSPF(M->in_fields[1], F, error_code);
   if (*error_code != GD_E_OK) return(1);
 
-  tmpbuf = AllocTmpbuff(return_type, *n_read * (int)ceil((double)spf2 / spf1));
+  /* calculate the first sample and number of samples to read of the
+   * second field */
+  num_samp2 = (int)ceil((double)*n_read * spf2 / spf1);
+  first_samp2 = (first_frame * spf2 + first_samp * spf2 / spf1);
+
+  /* Allocate a temporary buffer for the second field */
+  tmpbuf = AllocTmpbuff(return_type, num_samp2);
   if (!tmpbuf && return_type != 'n') {
     return(0);
   }
 
+  /* read the second field */
   n_read2 = DoField(F, M->in_fields[1],
-      first_frame, first_samp,
-      0, *n_read * spf2 / spf1,
+      0, first_samp2,
+      0, num_samp2,
       return_type, tmpbuf,
       error_code);
+  recurse_level--;
+  if (*error_code != GD_E_OK)
+    return(1);
+
   if (n_read2 > 0 && n_read2 * spf1 < *n_read * spf2) {
     *n_read = n_read2 * spf1 / spf2;
   }
-  recurse_level--;
   MultiplyData(data_out, spf1, tmpbuf, spf2, return_type, *n_read);
   free(tmpbuf);