[gimp-gap] fixed bugs in storyboard composite playback and audiotrack generatiion



commit c6ca260df1ac395f972b220d2b4bb54e9cc00529
Author: Wolfgang Hofer <wolfgangh svn gnome org>
Date:   Tue Dec 29 13:04:19 2009 +0100

    fixed bugs in storyboard composite playback and audiotrack generatiion

 ChangeLog            |   17 +++-
 gap/gap_story_file.c |  298 ++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 269 insertions(+), 46 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 230d858..5ab2e1c 100755
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,19 @@
-2009-11-19 Wolfgang Hofer <hof gimp org>   UNCOMMITED
+2009-12-29 Wolfgang Hofer <hof gimp org>
+
+- fixed a bug in generating original audiotrack for storyboard
+  whre the generated audio track sometimes is shorter than orignal video playtime
+  when videoclips without audio are included in the storyboard.
+
+- fixed storyboard composite playback of selected frames.
+  The calculation of total selected frames did not work in
+  some special cases where clips with overlapping frames
+  are selected. In case the user selected a clip
+  that was fully overlapped by an unselected clip
+  a total number of 0 frames was the result.
+
+  * gap/gap_story_file.c
+
+2009-11-19 Wolfgang Hofer <hof gimp org>
 
  - fixed a bug in the storyboard clip properties
    that removed masks from video clips when the properties popup dialog was closed and opend again.
diff --git a/gap/gap_story_file.c b/gap/gap_story_file.c
index 119335a..58183d0 100644
--- a/gap/gap_story_file.c
+++ b/gap/gap_story_file.c
@@ -8434,6 +8434,39 @@ p_get_video_framerate(const char *videofile
   return(l_video_framerate);
 }  /* end p_get_video_framerate */
 
+
+/* --------------------------
+ * p_get_video_has_audiotrack
+ * --------------------------
+ */
+gboolean
+p_get_video_has_audiotrack(const char *videofile
+                     ,gint32 videotrack
+                     ,gint32 seltrack
+                     ,const char *preferred_decoder
+                     )
+{
+  gboolean l_video_has_audio = FALSE;
+#ifdef GAP_ENABLE_VIDEOAPI_SUPPORT
+  t_GVA_Handle *gvahand= NULL;
+
+  gvahand = GVA_open_read_pref(videofile
+                              , videotrack
+                              , seltrack
+                              , preferred_decoder
+                              , FALSE  /* use MMX if available (disable_mmx == FALSE) */
+                              );
+ if (gvahand->atracks > 0)
+ {
+   l_video_has_audio = TRUE;
+ }
+ GVA_close(gvahand);
+
+#endif
+
+  return(l_video_has_audio);
+}  /* end p_get_video_framerate */
+
 /* --------------------------
  * gap_story_gen_otone_audio
  * --------------------------
@@ -8443,6 +8476,10 @@ p_get_video_framerate(const char *videofile
  * all elements in the generated audio track will have the specified
  * aud_track number and are placed in the active_section of the storyboard.
  *
+ * the generated result includes audio silence for all cliptypes other than movie
+ * movie clips without audio, or played backwards or with non-original speed
+ * also results in silence.
+ *
  * IN: replace_existing_aud_track  TRUE ... replace audiotrack if already exists.
  *
  * return TRUE if ok,
@@ -8470,6 +8507,7 @@ gap_story_gen_otone_audio(GapStoryBoard *stb
   GapStoryElem *stb_elem_new;
   gdouble      l_std_framerate;
   gdouble      l_framerate;
+  gboolean     l_video_has_audio;
 
   gchar       *l_videoname = NULL;
   gdouble      l_video_framerate = 0.0;
@@ -8506,6 +8544,7 @@ gap_story_gen_otone_audio(GapStoryBoard *stb
   }
 
   l_overlapcount = 0;
+  l_video_has_audio = FALSE;
 
   /* generate the otone track (at the lists tail) */
   for(stb_elem = stb->active_section->stb_elem; stb_elem != NULL;  stb_elem = stb_elem->next)
@@ -8521,9 +8560,17 @@ gap_story_gen_otone_audio(GapStoryBoard *stb
         case GAP_STBREC_ATT_TRANSITION:
           l_overlapcount += stb_elem->att_overlap;
           break;
+        case GAP_STBREC_VID_SILENCE:
+        case GAP_STBREC_VID_COLOR:
+        case GAP_STBREC_VID_IMAGE:
+        case GAP_STBREC_VID_ANIMIMAGE:
+        case GAP_STBREC_VID_FRAMES:
+        case GAP_STBREC_VID_SECTION:
+        case GAP_STBREC_VID_BLACKSECTION:
         case GAP_STBREC_VID_MOVIE:
-          /* add otne for the movie when playing normal forward */
-          if((stb_elem->playmode == GAP_STB_PM_NORMAL)
+          /* add otone for the movie when playing normal forward */
+          if((stb_elem->record_type == GAP_STBREC_VID_MOVIE)
+          && (stb_elem->playmode == GAP_STB_PM_NORMAL)
           && (stb_elem->step_density == 1.0)
           && (stb_elem->from_frame <= stb_elem->to_frame)
           && (stb_elem->nframes > l_overlap_in_this_elem)
@@ -8555,6 +8602,7 @@ gap_story_gen_otone_audio(GapStoryBoard *stb
                   g_free(l_videoname);
                   l_videoname = NULL;
                   l_video_framerate = l_std_framerate;
+                  l_video_has_audio = FALSE;
                 }
               }
               if (l_check_videorate)
@@ -8565,6 +8613,12 @@ gap_story_gen_otone_audio(GapStoryBoard *stb
                                                    ,1
                                                    ,stb_elem->preferred_decoder
                                                    );
+                l_video_has_audio = p_get_video_has_audiotrack(l_videoname
+                                                   ,1
+                                                   ,1
+                                                   ,stb_elem->preferred_decoder
+                                                   );
+
                 if(l_framerate <= 0.0)
                 {
                   l_framerate = l_std_framerate;
@@ -8572,53 +8626,47 @@ gap_story_gen_otone_audio(GapStoryBoard *stb
                 l_video_framerate = l_framerate;
               }
 
-
-              /* initialise the new AUDIO element */
-              if((*first_non_matching_framerate == 0.0)
-              && (l_framerate != stb->master_framerate))
+              if (l_video_has_audio == TRUE)
               {
-                *first_non_matching_framerate = l_framerate;
-              }
-
-              stb_elem_new->aud_play_from_sec = 0.0;
-              stb_elem_new->track             = aud_track;
-              stb_elem_new->from_frame        = l_from_frame;
-              stb_elem_new->to_frame          = stb_elem->to_frame;
-              stb_elem_new->aud_filename      = g_strdup(stb_elem->aud_filename);
-              stb_elem_new->orig_filename     = g_strdup(stb_elem->orig_filename);
-
-              stb_elem_new->aud_play_from_sec = (gdouble)l_from_frame / l_framerate;
-              stb_elem_new->aud_play_to_sec   = (gdouble)stb_elem->to_frame / l_framerate;
-              stb_elem_new->aud_wait_untiltime_sec = 0.0;
-              stb_elem_new->aud_volume             = 1.0;
-              stb_elem_new->aud_volume_start       = 1.0;
-              stb_elem_new->aud_fade_in_sec        = 0.0;
-              stb_elem_new->aud_volume_end         = 1.0;
-              stb_elem_new->aud_fade_out_sec       = 0.0;
-              stb_elem_new->nloop                  = stb_elem->nloop;
-              stb_elem_new->aud_seltrack           = aud_seltrack;
-              stb_elem_new->preferred_decoder      = g_strdup(stb_elem->preferred_decoder);
-
-              stb_elem_new->aud_framerate          = l_framerate;
+                /* initialise the new AUDIO element */
+                if((*first_non_matching_framerate == 0.0)
+                && (l_framerate != stb->master_framerate))
+                {
+                  *first_non_matching_framerate = l_framerate;
+                }
 
-              gap_story_list_append_elem_at_section(stb
+                stb_elem_new->aud_play_from_sec = 0.0;
+                stb_elem_new->track             = aud_track;
+                stb_elem_new->from_frame        = l_from_frame;
+                stb_elem_new->to_frame          = stb_elem->to_frame;
+                stb_elem_new->aud_filename      = g_strdup(stb_elem->aud_filename);
+                stb_elem_new->orig_filename     = g_strdup(stb_elem->orig_filename);
+
+                stb_elem_new->aud_play_from_sec = (gdouble)l_from_frame / l_framerate;
+                stb_elem_new->aud_play_to_sec   = (gdouble)stb_elem->to_frame / l_framerate;
+                stb_elem_new->aud_wait_untiltime_sec = 0.0;
+                stb_elem_new->aud_volume             = 1.0;
+                stb_elem_new->aud_volume_start       = 1.0;
+                stb_elem_new->aud_fade_in_sec        = 0.0;
+                stb_elem_new->aud_volume_end         = 1.0;
+                stb_elem_new->aud_fade_out_sec       = 0.0;
+                stb_elem_new->nloop                  = stb_elem->nloop;
+                stb_elem_new->aud_seltrack           = aud_seltrack;
+                stb_elem_new->preferred_decoder      = g_strdup(stb_elem->preferred_decoder);
+
+                stb_elem_new->aud_framerate          = l_framerate;
+
+                gap_story_list_append_elem_at_section(stb
                     , stb_elem_new
                     , stb->active_section
                     );
+              }
+            }
+            if (l_video_has_audio == TRUE)
+            {
+              break;
             }
-            break;
           }
-          /* no break at this point,
-           * same handling as all other vid record types is required
-           */
-        case GAP_STBREC_VID_SILENCE:
-        case GAP_STBREC_VID_COLOR:
-        case GAP_STBREC_VID_IMAGE:
-        case GAP_STBREC_VID_ANIMIMAGE:
-        case GAP_STBREC_VID_FRAMES:
-        case GAP_STBREC_VID_SECTION:
-        case GAP_STBREC_VID_BLACKSECTION:
-
           if(stb_elem->nframes > l_overlap_in_this_elem)
           {
             /* add silence for the duration of those elements */
@@ -8657,7 +8705,6 @@ gap_story_gen_otone_audio(GapStoryBoard *stb
 
 }  /* end gap_story_gen_otone_audio */
 
-
 /* -------------------------------
  * gap_story_get_default_attribute
  * -------------------------------
@@ -9055,7 +9102,7 @@ p_story_add_selection_mapping_elem(GapStoryFrameNumberMap *mapping,
 
 
 /* -------------------------------------------
- * gap_story_create_new_mapping_from_selection
+ * gap_story_create_new_mapping_from_selection_OLD
  * -------------------------------------------
  * create mapping for framenumbers of selected clips in the specified video track
  * of the specified active section.
@@ -9065,7 +9112,7 @@ p_story_add_selection_mapping_elem(GapStoryFrameNumberMap *mapping,
  * to free up allocated memory when the mapping is no longer in use)
  */
 GapStoryFrameNumberMap *
-gap_story_create_new_mapping_from_selection(GapStorySection *active_section
+gap_story_create_new_mapping_from_selection_OLD(GapStorySection *active_section
   , gint32 vtrack)
 {
   GapStoryFrameNumberMap *mapping;
@@ -9134,8 +9181,169 @@ gap_story_create_new_mapping_from_selection(GapStorySection *active_section
   mapping->total_frames_selected = mapped_frame_number + rest_frames -1;
 
   return (mapping);
+}  /* end gap_story_create_new_mapping_from_selection_OLD */
+
+
+
+
+
+
+
+/* -------------------------------------------
+ * gap_story_create_new_mapping_from_selection
+ * -------------------------------------------
+ * create mapping for framenumbers of selected clips in the specified video track
+ * of the specified active section.
+ * The mapping is typically used for composite video playback of selected
+ * clips.
+ * (the caller shall use gap_story_free_selection_mapping
+ * to free up allocated memory when the mapping is no longer in use)
+ *
+ * Example:
+ * Storyboard track witch videoclip sequence:  a,b,(overlap 6),c,d,e
+ * 
+ *  1 2     5 6   8    11
+ * +-+-+-+-+-+-+-+     +-+-+-+-+
+ * | a=4   |b=3  |     | e=4   |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *   |c=2|     d=7     |
+ *   +-+-+-+-+-+-+-+-+-+
+ * 
+ * Selected: a,b,e     total_frames_selected = (4 + 3 + 4) - (0) = 11
+ * 
+ * Selected: a,b,c     total_frames_selected = (4 + 3 + 2) - (2) = 7
+ * 
+ * Selected: a,b,c,d   total_frames_selected = (4 + 3 + 2 + 7) - ( 2 + 4) = 10
+ * 
+ * Selected: a,b,d     total_frames_selected = (4 + 3 + 7) - (4) = 10
+ *                     in this case the 2 frames of clip 2 are not mapped (cause they are not selected)
+ *                     but due to overlapping those frames are involved at rendering of selected frames
+ *                     in clip a.
+ *                     for calculation of total frames the number of frames in clip c is not relevant,
+ *                     but it reduces the configured overlap amount (from 6 to 4 frames).
+ *                     the first 4 frames of clip d overlap frames of clip a and clip b,
+ *                     therefore 4 frames are subtracted from the total_frames_selected sum.
+ *                     
+ */
+GapStoryFrameNumberMap *
+gap_story_create_new_mapping_from_selection(GapStorySection *active_section
+  , gint32 vtrack)
+{
+  GapStoryFrameNumberMap *mapping;
+  GapStoryElem      *stb_elem;
+  gint32             mapped_frame_number;
+  gint32             orig_frame_number;
+  gint32             sum_all_selected;
+  gint32             sum_overlap_sel;
+  gint32             curr_overlap;
+  gint32             expect_next;
+  
+  gboolean           capture_maped_frame_number;
+
+  if (active_section == NULL)
+  {
+    return (NULL);
+  }
+
+
+  mapping = g_new(GapStoryFrameNumberMap, 1);
+  mapping->total_frames_selected = 0;
+  mapping->map_list = NULL;
+  mapped_frame_number = 1;
+  sum_all_selected = 0;
+  sum_overlap_sel = 0;
+  curr_overlap = 0;
+  expect_next = 1;
+  
+  orig_frame_number = 1;
+  capture_maped_frame_number = FALSE;
+
+  for(stb_elem = active_section->stb_elem; stb_elem != NULL;  stb_elem = stb_elem->next)
+  {
+    if((stb_elem->track == vtrack )
+    && (capture_maped_frame_number == TRUE)
+    && (gap_story_elem_is_video(stb_elem) == TRUE))
+    {
+      /* calculate mapping for the next selected element
+       * as differnence of the previous selected clip
+       * to its next video clip element in the same track.
+       * (if there is no further selected element, we have reached
+       * the total number of selected frames in the vtrack)
+       */
+      gint32 next_orig_frame_number;
+
+      next_orig_frame_number = gap_story_get_framenr_by_story_id(active_section
+                                                   ,stb_elem->story_id
+                                                   ,vtrack
+                                                   );
+      mapped_frame_number += (next_orig_frame_number - orig_frame_number);
+      capture_maped_frame_number = FALSE;
+
+      if (expect_next > next_orig_frame_number)
+      {
+        curr_overlap += expect_next - next_orig_frame_number;
+      }
+      
+      
+    }
+
+    if( (stb_elem->track == vtrack ) && (gap_story_elem_is_video(stb_elem) == TRUE))
+    {
+      gint32 overlap_for_this_frame;
+      
+      overlap_for_this_frame = MAX(0, MIN(curr_overlap, stb_elem->nframes));
+      curr_overlap -= overlap_for_this_frame;
+      
+      if (stb_elem->selected)
+      {
+        orig_frame_number = gap_story_get_framenr_by_story_id(active_section
+                                                   ,stb_elem->story_id
+                                                   ,vtrack
+                                                   );
+        p_story_add_selection_mapping_elem(mapping, orig_frame_number, mapped_frame_number);
+
+        /* trigger capture of mapped number for the
+         * video clip that follows this selected clip in the same track.
+         */
+        capture_maped_frame_number = TRUE;
+        sum_all_selected += stb_elem->nframes;
+        sum_overlap_sel += overlap_for_this_frame;
+        expect_next = orig_frame_number + stb_elem->nframes;  /* expected frame without overlapping */
+      }
+    }
+    
+  }
+
+  mapping->total_frames_selected = sum_all_selected - sum_overlap_sel;
+
+
+  /* debug code to verify new mathod for counting total_frames_selected
+   * versus the old implementation and log differences
+   * (diffs are expected in some special cases when overlapping clips are involved)
+   */
+  if(gap_debug)
+  {
+    GapStoryFrameNumberMap *old_mapping;
+    old_mapping = gap_story_create_new_mapping_from_selection_OLD(active_section, vtrack);
+    
+    if (old_mapping->total_frames_selected != mapping->total_frames_selected)
+    {
+      printf("\nOLD MAPPING\n");
+      gap_story_debug_print_mapping(old_mapping);
+      printf("\nNEW MAPPING\n");
+      gap_story_debug_print_mapping(mapping);
+      printf("\n-------\n");
+    }
+  }
+
+  return (mapping);
 }  /* end gap_story_create_new_mapping_from_selection */
 
+
+
+
+
+
 /* -------------------------------------------
  * gap_story_debug_print_mapping
  * -------------------------------------------



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]