-
Notifications
You must be signed in to change notification settings - Fork 53
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
Implement AVOptions support #27
Comments
@maxruby, sorry not to get back to you sooner. I moved this discussion to #27 because I thought the discussion might get long for #38. The files you pointed out were auto generated by Clang.jl, using the script in the When Clang.jl wraps a bunch of header files, such as those for each library in ffmpeg, it
The wrapped functions end up in a file with the same base name as the header file. Everything else (types, type aliases, and constants) are collected together and put in one big file (e.g., libavcodec_h.jl). For ffmpeg, there's a larger overall structure which is described in detail in various README files. For AVOption, I would suggest focusing first on getting something simple working with one of the types/structs that supports the AVOption interface, such as one of those you mentioned. I would focus on supporting the string interface first, since (I think) all options can be set using strings (ffmpeg does the conversion). It's also possible that the structs currently in use aren't initialized properly to support AVOptions, so that might need to change. Hope this helps. Let me know what might not be clear. Cheers! |
This definitely helps! The overall structure of ffmpeg is nicely described in README - I got that far. The part I did not understand is to do with calling all the private (rather than generic) options from AVOptions since they are all dependent on the container, device or codec. Although I am still trying to work it out, I think that you might be right that the structs are not currently initalized in a way that they can be used directly to support AVOptions. I am hoping to clear this up first before moving to the next level. . . |
Having gone through your files, its now much more clear what I need to do to access the parameters in the immutable types AVCodecContext and AVForrmatConext. I see you created e.g., the AVFrame() function in LIBAVCODEC.jl. to call all the parameters (types) from AVFrame (defined in libavcodec_h.jl). I have a couple of related questions: 1.LIBAVCODEC.jl in AVCodecs v53 and v54 contains the AVFrame() function, but there isn´t one in v55. Is there a reason for this? Are those the versions you were working with? The latest ffmpeg release of libavcodec (as of today) has changed to v56 and the rest of them too. Do you think we should take this into account when completing the wrappers? How much change is there between recent versions? 2.Since I plan to add a function AVCodecContext() similar tot AVFrame() to access the parameters from the AVCodecContext type, I wonder whether it is really is useful to support multiple version of the libraries (v52, v53, v55). I assume that support for v55/v56 should be sufficient to do the job? Cheers, |
Addressing your second question first: it would certainly be easier to support only the latest version of ffmpeg/libav. However, the main reason I went the more complicated route is that I run Linux, and
In particular, some users who have expressed interest in using this package (e.g., Lucas Beyer) have some of these issues. This affects Mac and Windows users less, since we have greater control over what's installed there. In general, the libraries haven't changed much since the first version I mentioned, so this hasn't been too much of a problem so far. But, e.g., We should wrap the latest ffmpeg versions. Would you mind creating an issue for it? |
Now it makes sense! Sure, I will create a new issue entitled "Wrapping latest versions of ffmpeg". |
Especially Ubuntu 12.04 LTS will still be used for quite some time in and around my office, and they only ship v53. That's why I'd like to keep support for that version as long as the effort for it stays reasonable. Edit: if you ever need testing for something with these old versions, just ping me. |
OK. I will work on support for as many libraries as I can. Personally I would prefer to support the latest ones and those essential for Linux systems like v53. |
Hopefully, the files under |
@kmsquire. I have been testing several ideas about how to create access to the AVOptions in ffmpeh/libav within avio.jl and possibly some in LIBCODEC.jl, LIBAVUTIL.jl depending on what is appropriate. One is simple with minimal interface, the other might involve better documentation info, e.g., show() to the user, so that we can have better control to choose which parameters can be changed in e.g., AVInput, AVFrame, AVCodecContext, AVFrameContext, etc. I think this is actually something even FFMPEG/LIBAV could improve as it is challenging for a beginner especially to remember all the options available, even if they are available at the shell prompt. I am finding it rather challenging to keep track of the many types and parameters from which AVCodecContext and AVFormatContext inherit their types. For example, in your avio.jl, I noticed your comment to create av_opt_set as follows:
I got that avin is an AVInput type, with apFormatContext, a vector of pointers to AVFormatContext that contains "probesize" a AVRational type. I assume your idea here was to set probesize (Uint32) to "100000000". Here are my questions:
Thanks for your help. |
Hi Max, I really appreciate you looking into this, and I think I haven't been that clear what I had in mind.
At this point, I would just include any needed functions in
Again, I wouldn't want to support everything right now, because we don't use most of the ffmpeg/libav API. That said: julia> using VideoIO
julia> collect(zip(names(AVCodecs.AVFrame), AVCodecs.AVFrame.types))
42-element Array{(Symbol,DataType),1}:
(:data,Array_8_Ptr)
(:linesize,Array_8_Cint)
⋮
(:sample_rate,Int32)
(:channel_layout,Uint64) ( |
That is a relief. Being a perfectionist-type, I thought that I should pursue a general support of as many AVOptions as possible. . . But I also agree that it is much better to start with a basic support for the immediately essential functions at least internally. That said, my main motivation is to access the filtering/encoding options from ffmpeg to do live video streaming for now (and hoping eventually to link this with an OpenCV wrapper) . I noticed that some people are using OpenCV with ffmpeg and it would be fantastic to transfer this combination to Julia for live streaming/computer vision. |
:+1 |
Hi Kevin, Q1. Is it possible to use the av_setfield function (defined in util.jl) to set iformat, probesize and max_analyze_duration (the same way it was used to set pb -> apAVIOContext[1] in line 193 of avio.jl)? iformat::Ptr{AVInputFormat} -> avin.apAVInputFormat[1]
probesize::Uint32 -> 100000000
max_analyze_duration::Int32 -> 1000000
Q2. Should iformat = avin.apAVInputFormat[1]? If so should apAVInputFormat be added to the type declaration?
|
Hi Max, No worries! I've been finding it difficult to make time to actually work on this stuff, and it really will be easier in the long run if someone other than just me understands it. So I'm quite happy to help you in that direction.
Short answer: only as a short-term solution. Long answer: from version to version of ffmpeg, the structs supporting the AVOption interface can change (even for minor versions), and the fields set with the AVOption interface may disappear, even if the option itself doesn't (see, e.g., here). If we implement things right, eventually we wouldn't even need definitions for structs that support That said, it might be nice just to get something working for now, and if we can fix #25 and #31 with
I don't really know. For #25, we're wanting to get the list of video devices, which means we don't know the format. I only know that it needs to be set by looking at the source. |
I am happy to implement properly the library AVOptions API in VideoIO. After reading carefully the ffmpeg h files (e.g., avformat.h), it is more clear what these different options mean. I suggest the following plan:
|
Sounds like a plan! |
@kmsquire. By the way, I think we should include in the VideoIO.jl file: |
The current situation was actually requested, to reduce startup times for I haven't followed all of the module related changes recently, however, so Cheers, On Tuesday, September 30, 2014, Maximiliano Suster notifications@github.com
|
Even I can understand why you might want to support running without That said, the best solution is to make loading fast, and then make use of these two packages. I'm keeping a close eye on (and mildly helping out with) https://github.com/vtjnash/Speed.jl. |
@kmsquire. In addition to the av_opt_set and av_opt_get AVOptions we can also use the AVDictionary structure and set key,value pairs by calling av_opt_set_dict() on either AVFormatContext or AVCodecContext. One particular case where this is crucial is when we don´t know the input file format, i.e., before the file is actually opened. I found the AVDictionaryEntry declaration in livabutil_h.jl, but the declaration of AVDictionary fields in dict.c is not present in VideoIO. I would like to try to use AVDictionary (and it should not be difficult to use) - so we can have a a more global solution. I can not find a declaration of AVDictionary like this in the AVUtil module, is there a reason for this?
Cheers, |
Hi Max, making Actually, I think |
Thanks for the explanation. Yes, I have used AVDictionary in VideoIO for the simple case above, used av_dict_set() and passed the AVDictionary to avformat_open_input. The AVOptions API also relies on key, value pairs like AVDictionary but has more functionality (e.g., we can use av_opt_find to search all the formats, codecs, etc in the AVFormatContext or AVCodecContext structures). And we can also use AVDictionary as input to av_opt_set_dict. . . |
Hi Max, I'm on vacation this week and have limited internet access. I'll On Wednesday, October 8, 2014, Maximiliano Suster notifications@github.com
|
No problem, have a nice holiday! I have finished the AVOptions wrapper and I will be testing it over the next couple of days. It has support for all essential functions with AVDictionary, AVDeviceCapabilitiesQuery. It is all contained in a new file called avoptions.jl. Hopefully I will have polished it further by Monday when you get a chance to look into it. Meanwhile, can you please suggest what is the best way for me to test the new module together with the VideoIO.jl module? In other words, how should I update the Package just for testing/debugging? Thank you. |
I think this is what you're asking; if not, let me know. What you'll want to do is create an You'll probably want to move When you submit the PR, automated (Travis) testing runs Thanks again for taking this on. My intention is to add you as a collaborator in this repo after reviewing the PR. |
Thanks for the info. I will test thoroughly the new functions with test/avoptions.jl and get back to you as soon as I see the tests pass. . . |
@kmsquire. I am sorry for the delay - I wished to have this done by today, but I also had to spend time on a C++/OpenCV project. I will try to get back to you latest end of the week. Is it possible at all to run my modified version of the VideoIO package this way? Then test any new functions in the REPL? Max |
It seems it should be possible to rapidly test changes by adding files/modifying my ~/.julia/VideoIO folder and then: Or do you have an alternative suggestion for rapid testing Pkg module scripts without committing changes/PR to github? |
No worries, Max. Regarding testing, you can run package tests with In general,
Sorry not to be able to give a canonical answer here! |
I have two questions now:
julia> Pkg.test("VideoIO") failed process: Process( However, if I simply use the example in your tutorial, VideoIO.playvideo("anne_oakley"), this works fine and I can see the video in the display window. The fatal "ERROR: test failed: img == first_frame" refers to the macro @test I suppose this is to do with the swapping of .ogg to .png extension (which you do elegantly with swaptext)? which is indicated in the file. I would like to know if this is the only problem with the current version of Pkg.test("VideoIO") before I go on using this approach.
|
Regarding 2, the easiest way is to do the actual fork and development in julia> unshift!(LOAD_PATH, ".")
3-element Array{Union(ASCIIString,UTF8String),1}:
"."
"/Users/kevin/Source/julia/usr/local/share/julia/site/v0.4"
"/Users/kevin/Source/julia/usr/share/julia/site/v0.4" Regarding the first issue: I'm not sure what the exact issue is. I'm running on a recently updated system, and I need to update VideoIO for the libraries available first. For the tests, I previously had extracted the first (non-blank) image from each video. These exist as It may be that something is being read differently by a recent version of ffmpeg. I'll try to take a closer look once I update the VideoIO libraries. |
Simple testing doesn´t look straighforward . . . I tried so far
I am wondering whether there is a simple way to set up /.julia/v0.3/VideoIO with my modified VideoIO version without these type of complications with BinDeps and/or paths. Sorry for the trouble. |
ok, I will just work directly with the files in /.julia/v0.3 and try to write over them (same as 1 above but using your original master obtained via the Pkg manager). I think this is the simplest since it preserves the original configuration of the folder/files. |
Good news is that I have several of the AVOptions functions tested now and they seem to be working. |
I would start smile to get things working--maybe just focus on the string That said, if the names are somewhat regular, it might be possible to use On Wednesday, October 15, 2014, Maximiliano Suster notifications@github.com
|
I often try that too 😄 |
I know this is extremely basic but setting with Dictionary should also hopefully work soon too.
|
@kmsquire. I now have some AVOption functionality for listing, finding and setting option values using key, value string pairs. For example, we can get a complete list of all options available that can be set to defaults or individually using the AVOptions API and like this:
Setting options is as simple as:
However, when trying to retrieve values from an opaque pointer to AVDictionary or AVDeviceInfoList, e.g., avdevice_list_devices, I encouter repeatedly an "assertion" error (av_assert0) of AVDeviceInfoList** (goes back to line 187 of libavdev or libavformat.c). Any thoughts on what we could do to check where the problem originates? For example,
Here is the avdev_list_devices function:
|
Hi Max, nice! I think the error is because part of the struct needs to be initialized before passing it in to the function call. (See my comments in the relevant bug report.). For example, when calling this function through Why don't you submit this as a PR, marking it "WIP" so it isn't merged until it's ready? |
OK. I created a PR but please keep in mind that this is still very rough and I need to do a lot of tidying up, presenting the documentation and adding as much functionality for AVDictionary/DeviceCapabilityQuery as possible. I look forward to making this as useful as it can be. |
Can you tell me which "comments in the relevant bug report" you refer to? I saw one where you comment on the dummy at the command line, but I am not so much wiser after reading this . . . I understand that AVDeviceInfoList must be initialized - so I will try again assigning the fields in AVDeviceInfoList (devices, nb_devices, default_device) appropriately and hopefully solve this too. |
Thanks! The PR lets me (and others) test, comment on the design and offer On Friday, October 17, 2014, Maximiliano Suster notifications@github.com
|
Nope, that was it. Maybe this was something I was thinking about when On Friday, October 17, 2014, Maximiliano Suster notifications@github.com
|
avopt_get_value() is also fixed now! (line 271 in avoptions.jl) |
Lots of progress since last night - most things are now working (both getting and setting) . . . |
Excellent! On Saturday, October 18, 2014, Maximiliano Suster notifications@github.com
|
@kmsquire. I can document all AVOptions, make a Dict and print all of them, find, get and set AVOptions with strings and with the dictionary API. We can also get pixel formats compatible with the device with a new function called get_pixel_formats() in avio.jl. Interestingly, I had to change the declaration of AVDictionary for this API to work (it can not be declared simply as typealias Void in Julia). These functions work: However, I am struggling to get avdevice_capabilities_create() to work for the Device Capabilities API. It gives a negative (-78) error no matter how I initialize the AVDeviceCapabilitiesQuery structure. I am not sure whether there is something about this structure that needs to be initialized differently. Any thoughts? Here is my code for for initializing AVDeviceCapabilitiesQuery
|
When trying to implement av_dict_get which is necessary for get_metadata, it turns out that it requires AVUTIL ver >= 53. Since we only have v52 it can not be implemented.
|
I'm working on updating this now. |
If you update to the latest version, |
Thats ok. I have enough for now with ffmpeg. It should be relatively straightforward to implement the AVOptions in libavutil once everything works with ffmpeg. Thanks. |
Of course, that doesn't make it easy to support earlier versions of ffmpeg/libav. |
I just need to solve the errors with AVDeviceCapabilitiesQuery and then I will be very happy. . . |
AVOptions
is meant to be a version-independent method for getting and setting options in ffmpeg/libav structs. It works kind of like a dictionary.This would make solutions like #26 much nicer, in that they could properly call library functions instead of command line tools.
The text was updated successfully, but these errors were encountered: