This reads burned in timecodes from the headers of the two timecode
flavors I have floating around (Tentacle and GoPro), and provides them
to users.

Signed-off-by: Palmer Dabbelt <pal...@dabbelt.com>
---
I'm very new to all this video editing stuff, but I'm trying to get
multiple devices syced up via timecodes and I think I've mostly got it
working.  I'm using kdenlive and have a patch for that as well, but I
think the MLT side of things is going to need some work as what I have
here seems a bit clunky:

* I don't think converting to milliseconds was actually the right thing
  to do, as I'm just converting everything to/from frames.
* I'm not sure how cut clips are meant to work, but I don't have any
  code to handle timecode offsets either here or in kdenlive so I'm
  assuming they're going to be broken.
* I'm just sort of guessing at this metadata based on reading some files
  with ffprobe, I didn't read any specs.  So I have no idea if that
  pattern matching is going to be robust.

That said, I figured I'd just send this for now so at least I could get
it out on the list and see if anyone has a better idea...
---
 src/framework/mlt.vers       |  6 +++
 src/framework/mlt_producer.c | 75 ++++++++++++++++++++++++++++++++++++
 src/framework/mlt_producer.h |  2 +
 src/mlt++/MltProducer.cpp    | 11 ++++++
 src/mlt++/MltProducer.h      |  2 +
 src/mlt++/mlt++.vers         | 10 +++++
 6 files changed, 106 insertions(+)

diff --git a/src/framework/mlt.vers b/src/framework/mlt.vers
index 1b99babb..85d70a6d 100644
--- a/src/framework/mlt.vers
+++ b/src/framework/mlt.vers
@@ -657,3 +657,9 @@ MLT_7.22.0 {
     mlt_property_is_numeric;
     mlt_property_is_rect;
 } MLT_7.18.0;
+
+MLT_7.226.0 {
+  global:
+    mlt_producer_set_timecode;
+    mlt_producer_get_timecode;
+} MLT_7.22.0;
diff --git a/src/framework/mlt_producer.c b/src/framework/mlt_producer.c
index 904c9e02..fc9756c8 100644
--- a/src/framework/mlt_producer.c
+++ b/src/framework/mlt_producer.c
@@ -1284,6 +1284,81 @@ void mlt_producer_set_creation_time(mlt_producer self, 
int64_t creation_time)
     free(datestr);
 }
 
+/**  Get the timecode associated with the producer.
+ *
+ * \public \memberof mlt_producer_s
+ * \param self a producer
+ * \return The timecode for the given producer, in milliseconds.
+ */
+int64_t mlt_producer_get_timecode(mlt_producer self)
+{
+    mlt_producer producer = mlt_producer_cut_parent(self);
+
+    char *str = mlt_properties_get(MLT_PRODUCER_PROPERTIES(producer), 
"timecode");
+    if (str) {
+        int64_t ms;
+        char dummy;
+        int ret = sscanf(str, "%" SCNd64 "%c", &ms, &dummy);
+        if (ret != 1)
+            return -1;
+        return ms;
+    }
+
+    // Check for a "time_reference" in the metadata, which is the timecode
+    // counted in samples.  Convert that to milliseconds.  This is an audio
+    // file, so just assume it's the first source.
+    str = mlt_properties_get(MLT_PRODUCER_PROPERTIES(producer),
+                             "meta.attr.time_reference.markup");
+    if (str) {
+        int64_t samples;
+        char dummy;
+        int ret = sscanf(str, "%" SCNd64 "%c", &samples, &dummy);
+        if (ret != 1)
+            return -1;
+
+        str = mlt_properties_get(MLT_PRODUCER_PROPERTIES(producer),
+                                 "meta.media.0.codec.sample_rate");
+        if (!str)
+            return -1;
+        int64_t sample_rate;
+        ret = sscanf(str, "%" SCNd64 "%c", &sample_rate, &dummy);
+        if (ret != 1)
+            return -1;
+
+        return (samples * 1000) / sample_rate;
+    }
+
+    // Check for a "timecode" in GoPro format, which is HH:MM:SS;FRAME.
+    str = mlt_properties_get(MLT_PRODUCER_PROPERTIES(producer),
+                             "meta.attr.0.stream.timecode.markup");
+    if (str) {
+        int hh, mm, ss, frame;
+        int ret = sscanf(str, "%02d:%02d:%02d;%02d", &hh, &mm, &ss, &frame);
+        if (ret != 4)
+            return -1;
+        return (frame * 1000 / mlt_producer_get_fps(producer)) + (ss + mm * 60 
+ hh * 3600) * 1000;
+    }
+
+    return -1;
+}
+
+/** Set the timecode for the producer
+ *
+ * This allows callers to override the timecode deceted by MLT for a producer.
+ *
+ * \public \memberof mlt_producer_s
+ * \praam self a producer
+ * \param timecode The timecode, in milliseconds, to set
+ */
+
+void mlt_producer_set_timecode(mlt_producer self, int64_t timecode)
+{
+    char buf[32];
+    mlt_producer parent = mlt_producer_cut_parent(self);
+    snprintf(buf, sizeof(buf), "%" PRId64, timecode);
+    mlt_properties_set(MLT_PRODUCER_PROPERTIES(parent), "timecode", buf);
+}
+
 /** Probe the producer to publish metadata properties.
  *
  * After this call the producer will publish meta.media properties
diff --git a/src/framework/mlt_producer.h b/src/framework/mlt_producer.h
index 9b7bcff7..a6c7acd6 100644
--- a/src/framework/mlt_producer.h
+++ b/src/framework/mlt_producer.h
@@ -144,6 +144,8 @@ extern int mlt_producer_optimise(mlt_producer self);
 extern void mlt_producer_close(mlt_producer self);
 int64_t mlt_producer_get_creation_time(mlt_producer self);
 void mlt_producer_set_creation_time(mlt_producer self, int64_t creation_time);
+extern int64_t mlt_producer_get_timecode(mlt_producer self);
+extern void mlt_producer_set_timecode(mlt_producer self, int64_t timecode);
 extern int mlt_producer_probe(mlt_producer self);
 
 #endif
diff --git a/src/mlt++/MltProducer.cpp b/src/mlt++/MltProducer.cpp
index a837194d..40f305ad 100644
--- a/src/mlt++/MltProducer.cpp
+++ b/src/mlt++/MltProducer.cpp
@@ -262,6 +262,17 @@ void Producer::set_creation_time(int64_t creation_time)
     mlt_producer_set_creation_time(get_producer(), creation_time);
 }
 
+int64_t Producer::get_timecode()
+{
+    int64_t tc = mlt_producer_get_timecode(get_producer());
+    return tc;
+}
+
+void Producer::set_timecode(int64_t timecode)
+{
+    mlt_producer_set_timecode(get_producer(), timecode);
+}
+
 bool Producer::probe()
 {
     return mlt_producer_probe(get_producer());
diff --git a/src/mlt++/MltProducer.h b/src/mlt++/MltProducer.h
index 7afefbc3..b1ef4d21 100644
--- a/src/mlt++/MltProducer.h
+++ b/src/mlt++/MltProducer.h
@@ -77,6 +77,8 @@ public:
     int clear();
     int64_t get_creation_time();
     void set_creation_time(int64_t creation_time);
+    int64_t get_timecode();
+    void set_timecode(int64_t timecode);
     bool probe();
 };
 } // namespace Mlt
diff --git a/src/mlt++/mlt++.vers b/src/mlt++/mlt++.vers
index 1934decd..d9ff3764 100644
--- a/src/mlt++/mlt++.vers
+++ b/src/mlt++/mlt++.vers
@@ -710,5 +710,15 @@ MLT_7.14.0 {
     extern "C++" {
       "Mlt::Producer::probe()";
       "Mlt::Chain::attach_normalizers()";
+      "Mlt::Producer::get_timecode()";
+      "Mlt::Producer::set_timecode(int64_t)";
     };
 } MLT_7.12.0;
+
+MLT_7.26.0 {
+  global:
+    extern "C++" {
+      "Mlt::Producer::get_timecode()";
+      "Mlt::Producer::set_timecode(int64_t)";
+    };
+} MLT_7.14.0;
-- 
2.45.2



_______________________________________________
Mlt-devel mailing list
Mlt-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mlt-devel

Reply via email to