-
Notifications
You must be signed in to change notification settings - Fork 314
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
new filter: Dynamic GPS text #703
Conversation
There are major changes happening with MLT with a major new version 7 whose branch I merged to master today. This probably does not affect you too much, but what will catch you soon is our removal of the old configure and Makefile-based build system and replaced by CMake. This addition will have to go into that branch and will not be accepted into the v6 branch. Shotcut development is already based on the new version, and there will be a new SDK soon. You just happened to become a new developer at a bad time for you. I can share you that one thing I am not happy about is the length of the filter code and its home-grown XML parser. I am no longer accepting just any contribution because there is a maintenance cost to it. On the Shotcut forum I did suggest that you use the xml module's libxml or qt module's Qt parser. |
I understood that completely different, as in I can't use the parsers unless I move the filter into that folder and that would create licensing problems or something, so I thought I have to make my own instead. |
Yes, you would need to move your filter into the module of the respective library you are using. But there is no hard requirement that you use the plus module for this filter. |
I assumed that because dynamic text was in plus module I also needed to put this filter in plus. |
You do not need to worry about the text rendering because you are driving an external text filter similar to dynamictext. Qt is C++ whereas libxml2 is plain old C. At least with libxml2 you can see our usage of it and follow it along with the docs. The xml producer uses the faster callback-based parser, but it has a object tree API if you prefer that. I guess a GPX file could have a lot of data, and that will be faster and less memory using the callback API. |
I want to mention that I do like the concept for this filter and appreciate the effort you have made to contribute! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are a few comments for your consideration. I will make a more thorough review after you have resolved the major comments.
I would also echo Dan's comments in thanking you for this great contribution. I expect many people will enjoy this fun feature. I hope you do not become discouraged by the review comments. We will help you usher this change to the end.
mutable: yes | ||
widget: text | ||
|
||
- identifier: minor_offset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it cumbersome that there are two offsets. Could there just be one offset and let the application be responsible for adding two different values if that is needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The minor_offset property appeared as a bugfix to the shotcut ui i made (it lost the value it stored in some circumstances, like after closing and opening the project, I think even if minimizing the window). The UI element is extermely useful and I would really not want to remove it, but the filter property I don't care about.
On the other hand it's completely optional so I didn't think it would matter much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it will be more obvious to me when I see the filter UI. But based on the YML text, I am imagining the UI has some abstract settings that might be difficult for users to understand. Why can't the UI just have one offset?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The major offset has textboxes for days/hours/mins/seconds, the minor one is just a slider with a -60 to 60 seconds range that can be changed (and processed in realtime) using the mouse scrollwheel. Of course I can just move the minor value into the major one but in practice I noticed I almost always end up splitting the video in multiple clips and just keep the major offset identical across the gps file while adjusting the minor one a few seconds forward/backwards to match some obvious movements in the particular clip.
I forgot to mention in the first post a sample run, for melt the minimum arguments would look like this: And this is a sample shotcut exported clip: https://youtu.be/29dsPm5l3jg |
Maybe tz_offset would be a good field to add? |
The videofile_timezone_seconds property does exactly that. I don't know how read only properties can be used in melt, I tried major_offset=videofile_timezone_seconds and it didn't seem to work. Maybe because it's not available at init and only after filter_process? |
https://www.msys2.org is your friend for windows dependencies outside of the ones included in the SDK. You also typically need to run |
I installed msys2 (and pkg-config + libxml2, not sure if these were needed) but I get this weird error that it can't find the tree.h file even though that header is at the path in the gcc command (c/Projects/libxml2-2.9.10/include/libxml). Any idea why it can't find it?
|
Did you install it using "pacman -S", or manually somehow? I usually install all these packages since that is what we use in our build system: |
I installed it both ways at some point trying to fix the problem.
|
I do not know the specific solution to your problem. There might be a hint here: I would suggest to start over:
Then, you should have a working build and build environment.
Or hook in QT Creator if you want to use that. |
IIRC there are also tricks regarding winmain when using SDL in melt... |
I think I got this figured out, it was a combination of having the entire msys lib folder added and not cleaning properly the entire project. I basically copied the needed stuff from pacman (btw needed the libxml2-devel package to get all dependencies) directly into shotcut's project folder /include and /lib, fixed the pkg-config file (I'm using a separate binary to remove the msys /bin from path, long story here, some other errors) and somehow it works now (I already did all this same stuff yesterday but somehow ended up crashing shotcut at startup). |
Quick update as it's been a long time since my last: I've switched to libxml2 for file read/parsing and I've also been updating the rest of the code into a way more organized format and should probably have a commit ready the next few days. I got stuck for a while into a weird crash some random seconds after reading the file, turns out I was calling xmlCleanupParser() at the end of my parsing routine (copied from the libxml's example code) which is only supposed to be called after finishing all work with xml lib. But the fun random part was triggered by shotcut's autosave feature (some time after my file read) which obviously needed the xml parser initialized and crashed the entire program when running. Not sure if this is a known/useful info, just writing it out here. I found out about it in the shotcut.RPT crash dump and not sure who's creating it (QT creator?) but it's a really good feature. |
Hm, not exactly what I wanted to do here, I'll try to figure out how to fix it. Actually, can I just delete this branch and create a new one with just the correct files for the new filter? |
Ok, so I fixed everything in the latest commit, I don't understand how squashing made extra commits instead of hiding them, github is not as intuitive as I hoped. Now onto the changes: What I didn't do: I'll update it and create a parallel pull request for the UI I have one question about printing int64_t type: in a printf() I can use the format "%I64d" but in mlt_log_info this is not recognised as a proper format and literally prints "%I64d" instead of the variable, does it work for you or are you using something else? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic work on this. My only open question is about the major and minor times. But I will make that discussion in the Shotcut review.
Also, you will need to rebase properly. git pull --rebase origin master
and then a force push should do it.
5db20e7
to
9c4e61f
Compare
Just did it, hope it's correct now. |
… add auto_gps_processing_start_now
… before-values later
One thing that's annoying me is getting the actual media start recording date on some files because I get the actual create date + video duration. It seems like every device has it's own rule about this, from what I've tested only the gopro seems to set the time to start of recording, my phone is setting it to video end, my sony camera (in AVCHD format) has a different date field (which is not read by shotcut, I assume it falls back to file modification time which is set at the end of the recording). Here's a sample from this camera: Looking at mlt_producer_get_creation_time(), it seems to read the properties by passing a string (like "creation_time") to mlt_properties_get(). How can I figure out the string for the above field? I'm thinking this could be worth adding to the mlt_producer_get_creation_time() implementation. The alternative would be to assume creation time is always start time + video duration, but of course this would break the files that don't do this. Another alternative would be to add another button that adds video length to the offset (so many buttons...) Thoughts? |
I am fairly confident there is not a universal standard to define a date for the start of all media file types. SMPTE time code exists for time (but not date). But many formats do not support SMPTE time codes.
The "creation_time" property is a way for an application to override the "discovered" time code. You can see in the function that if "creation_time" is not set by the application, then the code searches for properties set by ffmpeg: "meta.attr.com.apple.quicktime.creationdate" and "meta.attr.creation_time". If those are not set, then it falls back to using the file properties. I think you are right that some devices might uses the clip start time while some might use the end time. To top it off, some use UTC and some us local time. You are welcome to research ways to improve this code. |
Annoying that there's no standard for this. From a logical standpoint, would "creation_time" imply start of recording? Technically it can also mean when the file was fully created so I don't even know if this is a path I should try to work out.
Indeed, but how were those discovered? A ffprobe on the file shows no metadata at all, MediaInfo and exiftool show the datetime but under different names which I assume means it isn't a standard field. I think the only sane solution for this is to add a new button in the UI. Can I access the total length (seconds) of the current video straight from qml? I'd rather not add another filter property in the backend to expose this. |
I don't completely understand the question. The "creation_time" producer property can be set in Shotcut in the "hamburger" menu in the properties panel. The frame properties come from ffmpeg. You can see the millions of places that the "creation_time" metadata is set in ffmpeg:
It is not clear to me what the button would do, but we can probably find a better way. If we convince ourselves that MOST files set the creation time to the end of the clip, then we can apply the offset in the producer function. It would be good for that change to be in a different pull request. |
What I mean is: how were the "meta.attr.com.apple.quicktime.creationdate" and "meta.attr.creation_time" alternative strings found? Basically how can I search if there's some sort of "meta.attr[.mts].datetimeoriginal" that corresponds to the data found by exiftool in this .mts file from a sony camera.
Indeed, but there's one more variable here that would skew the priority: I think most footage that would make sense to be used with GPS stats would come from an action cam, so even if there are millions of android phones that set it at the end of recording, I'd still go with the begining as Gopro s (and one other action cam I have and tested that saves .MOV (quicktime)) set it at the start. Also when I sync 2 things it is very natural to go for the start times. so bonus points for easy of use here.
If you try to sync a gps track with a file that has a creation time at the end of the video, it will be out of sync by it's length. |
The avformat producer maps metadata from the ffmpeg context into the meta.attr properties: So any metadata provided by ffmpeg should be available there. More info here: Shotcut shows the container and stream metadata in the Metadata tab on the properties panel: |
Went through the links and I think I got the answer: the AVCHD (and mts container) is bad at storing metadata and the creation_time I see in mediainfo is not seen/supported by ffmpeg but extracted from deeper. This is also confirmed by this comment on the exiftool website:
(one cool thing about this stream-store mode is that it has complex camera info for every second so f-number, exposure time, focus distance, date+time etc for every second) This is also confirmed by the fact that the Metadata tab in properties in Shotcut is completely empty for this file. So I guess this settles it, .MTS metadata is not supported, it will fall back to file modification time. |
All the tests I could came up with are ok with the latest commit so I think this is the final version. There are 3, let's call them "known issues" that I don't plan to fix (don't think they need) unless there's a good argument against:
|
Looks good to me. I have no further comments. |
This is a filter I've been working for the last 2 months and I managed to implement most of the features I needed or wanted, there are still some small TODOs in the code but nothing major. As I'm not familiar at all with the mlt framework I suspect there's quite a bit of changes I need to make to be accepted so feel free to comment on them.
The file got pretty large but it's easy to follow from bottom up. The base logic is identical to dynamic text filter on top of which I added the gps related keywords.
One important note: I never got around to succesfully compiling the entire mlt project, I only got as far as compiling inside the plus folder to create libmltplus.dll to test with melt.exe (and shotcut) but after the latest pull from upstream I can't compile anymore at all (undefined references to mlt_event_data_from_frame and some other similar in folder). I probably messed up some paths or need to update some other dlls too. The files still compile succesfully on my original dev folder so I assume they are ok C-syntax-wise.
melt usage:
melt.exe <video file path> -filter dynamicgpstext gps.file=<.gpx or .tcx file path>
(+offset: "major_offset=-7200
" if video is 2h ahead of gps)Sample video with filter applied: https://youtu.be/29dsPm5l3jg