Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SMPTE-esque timecodes #1011

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/framework/mlt.vers
Original file line number Diff line number Diff line change
Expand Up @@ -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;
75 changes: 75 additions & 0 deletions src/framework/mlt_producer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/framework/mlt_producer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
11 changes: 11 additions & 0 deletions src/mlt++/MltProducer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
2 changes: 2 additions & 0 deletions src/mlt++/MltProducer.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ class MLTPP_DECLSPEC Producer : public Service
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
Expand Down
10 changes: 10 additions & 0 deletions src/mlt++/mlt++.vers
Original file line number Diff line number Diff line change
Expand Up @@ -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;