Free run no gaps time code implementation
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 15 Dec 2011 12:18:09 +0000 (12:18 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 15 Dec 2011 12:18:09 +0000 (12:18 +0000)
This commit adds new timecode type which counts frames in gapless mode (counting
actually decoded frames instead of using pts to find frame number) which might
resolve issues with files which have got broken or incorrect base time value stored
in the header.

This timecode allows to deal with movies from #29388: Abnormal frame length on MP4 files

source/blender/imbuf/IMB_imbuf.h
source/blender/imbuf/intern/indexer.c
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesrna/intern/rna_sequencer.c

index 3586e8f1b5ef6eec9c40a89d503022a9117c3a3b..39282335f46bb501bf0276a088af57a356a928ed 100644 (file)
@@ -198,7 +198,8 @@ typedef enum IMB_Timecode_Type {
                                  record date and time written by recording
                                  device (*every* consumer camcorder can do
                                  that :) )*/
-       IMB_TC_MAX_SLOT   = 3
+       IMB_TC_RECORD_RUN_NO_GAPS = 8,
+       IMB_TC_MAX_SLOT   = 8
 } IMB_Timecode_Type;
 
 typedef enum IMB_Proxy_Size {
index 4088cf861e7bd638642fd3cd36c62f81bf610037..ce14951b5fb6bc027c9d1a34df0f48d920ef99f1 100644 (file)
@@ -52,8 +52,11 @@ static int proxy_sizes[] = { IMB_PROXY_25, IMB_PROXY_50, IMB_PROXY_75,
 static float proxy_fac[] = { 0.25, 0.50, 0.75, 1.00 };
 
 #ifdef WITH_FFMPEG
-static int tc_types[] = { IMB_TC_RECORD_RUN, IMB_TC_FREE_RUN,
-                          IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN };
+static int tc_types[] = { IMB_TC_RECORD_RUN,
+                          IMB_TC_FREE_RUN,
+                          IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN,
+                          IMB_TC_RECORD_RUN_NO_GAPS,
+                        };
 #endif
 
 #define INDEX_FILE_VERSION 1
@@ -102,7 +105,7 @@ anim_index_builder * IMB_index_builder_create(const char * name)
 }
 
 void IMB_index_builder_add_entry(anim_index_builder * fp, 
-                                int frameno,unsigned long long seek_pos,
+                                int frameno, unsigned long long seek_pos,
                                 unsigned long long seek_pos_dts,
                                 unsigned long long pts)
 {
@@ -344,6 +347,8 @@ int IMB_timecode_to_array_index(IMB_Timecode_Type tc)
                return 1;
        case IMB_TC_INTERPOLATED_REC_DATE_FREE_RUN:
                return 2;
+       case IMB_TC_RECORD_RUN_NO_GAPS:
+               return 3;
        default:
                return 0;
        };
@@ -401,8 +406,10 @@ static void get_tc_filename(struct anim * anim, IMB_Timecode_Type tc,
        char index_dir[FILE_MAXDIR];
        int i = IMB_timecode_to_array_index(tc);
        const char * index_names[] = {
-               "record_run%s.blen_tc", "free_run%s.blen_tc",
-               "interp_free_run%s.blen_tc" };
+               "record_run%s.blen_tc",
+               "free_run%s.blen_tc",
+               "interp_free_run%s.blen_tc",
+               "record_run_no_gaps%s.blen_tc"};
 
        char stream_suffix[20];
        char index_name[256];
@@ -696,7 +703,7 @@ static int index_rebuild_ffmpeg(struct anim * anim,
        unsigned long long start_pts = 0;
        double frame_rate;
        double pts_time_base;
-       int frameno = 0;
+       int frameno = 0, frameno_gapless = 0;
        int start_pts_set = FALSE;
 
        AVFormatContext *iFormatCtx;
@@ -858,13 +865,21 @@ static int index_rebuild_ffmpeg(struct anim * anim,
 
                        for (i = 0; i < num_indexers; i++) {
                                if (tcs_in_use & tc_types[i]) {
+                                       int tc_frameno = frameno;
+
+                                       if(tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS)
+                                               tc_frameno = frameno_gapless;
+
                                        IMB_index_builder_proc_frame(
                                                indexer[i], 
                                                next_packet.data, 
                                                next_packet.size,
-                                               frameno, s_pos, s_dts, pts);
+                                               tc_frameno,
+                                               s_pos, s_dts, pts);
                                }
                        }
+
+                       frameno_gapless++;
                }
                av_free_packet(&next_packet);
        }
index ce01f100239a555624e78b23ca7550b6fb3d6baa..ca2b7e0b2a99eb51374117a0196dc0e50dde66e0 100644 (file)
@@ -309,7 +309,8 @@ typedef struct SpeedControlVars {
 #define SEQ_PROXY_TC_RECORD_RUN                 1
 #define SEQ_PROXY_TC_FREE_RUN                   2
 #define SEQ_PROXY_TC_INTERP_REC_DATE_FREE_RUN   4
-#define SEQ_PROXY_TC_ALL                        7
+#define SEQ_PROXY_TC_RECORD_RUN_NO_GAPS         8
+#define SEQ_PROXY_TC_ALL                        15
 
 /* seq->type WATCH IT: SEQ_EFFECT BIT is used to determine if this is an effect strip!!! */
 #define SEQ_IMAGE              0
index 64adac7dd5ec796ba194c71f1b5f07fbee615f97..4da4e6573f7233d9dfb580f7bb3c78e9fe7decb3 100644 (file)
@@ -822,6 +822,9 @@ static void rna_def_strip_proxy(BlenderRNA *brna)
                {SEQ_PROXY_TC_INTERP_REC_DATE_FREE_RUN, "FREE_RUN_REC_DATE", 0, "Free Run (rec date)",
                                                        "Interpolate a global timestamp using the "
                                                        "record date and time written by recording device"},
+               {SEQ_PROXY_TC_RECORD_RUN_NO_GAPS, "FREE_RUN_NO_GAPS", 0, "Free Run No Gaps",
+                                                       "Record run, but ignore timecode, "
+                                                       "changes in framerate or dropouts"},
                {0, NULL, 0, NULL, NULL}};
        
        srna = RNA_def_struct(brna, "SequenceProxy", NULL);