Compare commits

...

403 Commits

Author SHA1 Message Date
Niels Martin Hansen 41d6719278 Oops, have to commit to 2.1.7 tag, the configuration used for the Windows build didn't get into the original tag.
Originally committed to SVN as r3143.
2009-07-15 00:26:36 +00:00
Niels Martin Hansen 26d3877bcf More cleanup of local config:
* Remove option from Options dialogue, it's an install-time thing really
 * Don't try to do file associations at startup if we're portable
 * General clean up of config handling code; properly make ?user point to ?data and then everything magically follows, makes a lot of handling cleaner

Originally committed to SVN as r3131.
2009-07-14 04:51:35 +00:00
Niels Martin Hansen 81515f024f Properly fix "local config" option, previously it only made config.dat local and kept everything else in %APPDATA% still. Now fixed, along with a load of other problematic uses of relative paths. Still a lot more to go.
This also makes a bit of sense of the default options for various paths that previously were implicitly relative to ?user or ?data but never explicitly specified in options.

Originally committed to SVN as r3130.
2009-07-14 03:02:17 +00:00
Karl Blomster 26d07c7aea Remove the dangerous CopyFile function that on Unix attempted to create hard links of files instead of copying them. Replace it with wxCopyFile instead. Patch by jfs. Fixes #912.
Originally committed to SVN as r3129.
2009-07-14 02:20:40 +00:00
Niels Martin Hansen ccd001fbbd Apply patch to fix #910.
Originally committed to SVN as r3128.
2009-07-14 02:00:56 +00:00
Niels Martin Hansen 28bf657fda More minor fixes to Windows installer... we're installing VSFilter 2.39e from guliverkli2 and not one from MPC-HC, and list a couple more files for the pre-install cleanup jobs.
Originally committed to SVN as r3127.
2009-07-14 00:15:42 +00:00
Amar Takhar 712fd197c3 Add src/core/*.h not core/*.h to SOURCES for distfiles.
Originally committed to SVN as r3126.
2009-07-13 23:26:03 +00:00
Niels Martin Hansen 27bb28190b Even more changes to Windows installer:
* Include ffms2.pdb
 * Have some files/actions depend on multiple components

Originally committed to SVN as r3125.
2009-07-13 23:09:30 +00:00
Niels Martin Hansen eaf507ca97 Fix include path for MSVC project to point to the new location of ffms2 sources.
Originally committed to SVN as r3124.
2009-07-13 22:43:46 +00:00
Amar Takhar d298d21e5d Update libass to 94d4104 from http://greg.geekmind.org/viewgit/.
Originally committed to SVN as r3123.
2009-07-13 22:43:25 +00:00
Niels Martin Hansen 9bc0d84862 Remove further deprecated compiler flags causing warnings from MSVC projects.
Originally committed to SVN as r3122.
2009-07-13 22:42:17 +00:00
Amar Takhar 32c6f54be7 Actually fix libosxutil includes, as many times as I'd like to belive using 'diff' to transfer from a working copy to a non-working copy is the safest I always endup convincing myself that it's impossible to screw-up a _two_ line patch.
Originally committed to SVN as r3121.
2009-07-13 22:38:43 +00:00
Niels Martin Hansen 0e22e6dfd9 Remove a deprecated compiler flag causing warnings during universalcharset build on Windows.
Originally committed to SVN as r3120.
2009-07-13 22:37:19 +00:00
Amar Takhar 9bfdc30102 I can't belive these snuck in, I specifically ensured they wern't there but obviously I didn't do nearly a good enough job!
Originally committed to SVN as r3119.
2009-07-13 22:35:26 +00:00
Amar Takhar cc4fd946d8 Wrap libosxutils headers with "extern C"
Originally committed to SVN as r3118.
2009-07-13 22:32:11 +00:00
Amar Takhar c0c9d99700 Build changes for the new ffms, TheFluff will be comitting the aegisub changes shortly.
Originally committed to SVN as r3117.
2009-07-13 22:30:49 +00:00
Karl Blomster 83960dcce3 Update the FFMS2 audio and video providers to use the new API features.
Originally committed to SVN as r3116.
2009-07-13 22:30:48 +00:00
Amar Takhar ccf07d8a8a Update to the latest ffms (r116) from http://code.google.com/p/ffmpegsource/.
Originally committed to SVN as r3115.
2009-07-13 22:27:40 +00:00
Amar Takhar 7455f77ad3 Rename FFmpegsource2/ to libffms/ before the update to r115 from the ffms repo. This doens't make any build changes so things will be broken in this commit.
Originally committed to SVN as r3114.
2009-07-13 22:19:44 +00:00
Niels Martin Hansen 7bf71d3ee3 More little changes to Windows installer:
* Don't include dictionaries and thesaurii if they don't exist on the machine building the installer
 * Sprinkle some more 'solidbreak' flags around, hoping to make compact/custom installations spend less time decompressing huge files that won't be installed

Originally committed to SVN as r3113.
2009-07-13 21:48:53 +00:00
Niels Martin Hansen d8161a9071 Add Russian dictionary and thesaurus files to Windows installer.
Originally committed to SVN as r3112.
2009-07-13 21:38:58 +00:00
Niels Martin Hansen a78bbf6323 Some changes to file ordering, and cosmetic changes, in Windows installer script.
Originally committed to SVN as r3111.
2009-07-13 21:26:28 +00:00
Niels Martin Hansen d02b75b199 Preparing for 2.1.7 release, new URLs for latest.txt.
Originally committed to SVN as r3110.
2009-07-13 18:31:43 +00:00
Karl Blomster 3dc40e5c34 Missed two renamings in the last commit.
Originally committed to SVN as r3109.
2009-07-13 02:48:07 +00:00
Karl Blomster 80a8ea634b Hack in some compatibility #defines in FFMS2's utils.h so it'll compile with both older and newer ffmpeg versions. Reverts r3012. Part of this change based on a patch by CharlieB. Fixes #909.
Originally committed to SVN as r3108.
2009-07-13 02:34:41 +00:00
Amar Takhar 9074ebec70 * BUILD_DARWIN was a define used for libass only, change it to __APPLE__ (sigh)
* char config_path -> const char *config_path for non-MAC builds. not sure how the first version got in.

Originally committed to SVN as r3107.
2009-07-12 20:10:25 +00:00
Thomas Goyne 21d675bd7b Made selecting a line via the visual typesetting drag mode also update the grid's selection, fixing one way of getting the edit box out of sync with the other non-time controls.
Originally committed to SVN as r3106.
2009-07-12 05:30:01 +00:00
Amar Takhar 10041ef502 Fix OSX: Move our local libass patch into aegisub itself as libass now supports specifying a fontconfig config file.
Originally committed to SVN as r3105.
2009-07-11 17:28:27 +00:00
Amar Takhar ea5a3b7a73 Nuke the Windows (MSVC) support as libass will be adding their own official support, it's not like we're using it anyway..
Originally committed to SVN as r3104.
2009-07-11 15:55:52 +00:00
Amar Takhar d35712946e Remove mputils.(c|h) as they're no longer needed.
Originally committed to SVN as r3103.
2009-07-11 15:54:38 +00:00
Amar Takhar 516db6c901 Update libass to 15df37.
Originally committed to SVN as r3102.
2009-07-11 15:48:50 +00:00
Amar Takhar 1ec77b7576 Disable Fortran checks, thanks Greg! For whatever reason I only looked at the autoconf source, sigh.
Originally committed to SVN as r3101.
2009-07-11 03:45:03 +00:00
Karl Blomster a9b479bd53 Re-fix the fix in r3091; the issue wasn't what I thought it was, it was that memory was being freed twice. Fixes #906.
Originally committed to SVN as r3100.
2009-07-08 13:30:24 +00:00
harukalover d1e5ff32e6 Fixed a memory leak that occurred when resetting hotkey defaults
Originally committed to SVN as r3099.
2009-07-06 05:01:55 +00:00
Amar Takhar 493f219a7e Even when we don't have any audio players audio_player.cpp is still required in order to register the fact that there are no audio players.
Originally committed to SVN as r3098.
2009-07-04 15:53:52 +00:00
Thomas Goyne 1033427265 Made the edit box only retain its internal undo history for changes made since the last commit or line switch rather than every state it has had since the program was started, fixing a gradual memory leak.
Originally committed to SVN as r3097.
2009-07-04 01:46:06 +00:00
harukalover 4dc14ed973 Increased the default size of the time edit control on wxGTK since it was still too small on some OS's after r3094
Originally committed to SVN as r3096.
2009-07-03 23:40:26 +00:00
Thomas Goyne 6e3b30c43b Fixed an issue with the Set Start/End to Video and Snap to Scene hotkeys and toolbar buttons where any uncommited changes in the editbox would be reverted. They now behave the same as setting the time via the text boxes.
Originally committed to SVN as r3095.
2009-07-03 18:35:46 +00:00
harukalover 61c0cbcb17 Fixed the "Overwrite-Insertion in time boxes" option on Linux and enabled it as the default mode for the time edit boxes on all OS's instead of just Windows
Originally committed to SVN as r3094.
2009-07-02 17:29:20 +00:00
harukalover c2d89e8898 Fixed an issue with the spectrum slider not updating the color spectrum in the color picker dialog on Linux
Originally committed to SVN as r3093.
2009-07-02 03:33:28 +00:00
harukalover 49423c613e Fixed removal of the color dropper tool on non-Windows platforms (it was still appearing, though misaligned in the color picker). updates #861
Originally committed to SVN as r3092.
2009-07-01 03:16:47 +00:00
Karl Blomster 1c630e60cf Fix a potential crash on exiting. (An invalid memory location could under certain circumstances be assigned to in the OpenGLTextTexture destructor.)
Originally committed to SVN as r3091.
2009-06-30 20:44:38 +00:00
harukalover 47f0a51e87 * Fixed an issue with aegisub not trying to open the local config.dat in Windows builds, fixes #902
* Fixed an issue with aegisub failing to start if a local config.dat existed but aegisub did not have permission to write to it

Originally committed to SVN as r3090.
2009-06-30 05:55:03 +00:00
harukalover 9dcd3add79 Fixed a new[]/delete mismatch
Originally committed to SVN as r3089.
2009-06-30 05:29:15 +00:00
Amar Takhar 4952b5168d Add ass_cache_template.c to EXTRA_DIST. I remember fixing it, however I forgot to commit it..
Originally committed to SVN as r3088.
2009-06-28 23:39:42 +00:00
Amar Takhar 085dd94f0d Unbreak Unix/OSX from r3085, I'll let jfs do a proper fix when he's around. Updates #884.
Originally committed to SVN as r3087.
2009-06-25 02:31:35 +00:00
Niels Martin Hansen 4aafee2ac9 For whatever reason, the right-click-to-play-syllable code in karaoke mode was calling the audio player directly, instead of using the usual Play function in the audio display. Fixes #598 for real.
Originally committed to SVN as r3086.
2009-06-25 00:32:33 +00:00
Niels Martin Hansen 0367fd37d4 Fix #884, annoying wxString::Trim is destructive and there's no non-destructive variant. Adding a new function to utils.cpp to test whether a string is "blank", ie. empty or whitespace-only, as well as a function to check if a wchar_t is a whitspace character.
Trimming was used to test whether a string was blank or not, and this caused the source syllable texts to be altered when the kanji interpolation algorithm was run.

Originally committed to SVN as r3085.
2009-06-24 22:22:45 +00:00
Karl Blomster 86a1f2931b Adjust the way VFR is handled in VideoContext::SetVideo; should be cleaner and less prone to odd bugs now (hopefully). Doesn't try to set CFR framerates on VFR videos anymore, for one thing. Fixes #864.
Originally committed to SVN as r3084.
2009-06-24 18:16:03 +00:00
Karl Blomster f2415a4d65 Implement timestamp reading from the container in the ffmpeg video provider. Updates #864.
Originally committed to SVN as r3083.
2009-06-24 17:43:36 +00:00
Karl Blomster 2434fbd70a Updated Czech translation by Christof (christof a totan d cz). Fixes #900
Originally committed to SVN as r3082.
2009-06-24 15:47:51 +00:00
harukalover 17af911fa6 Fixed an issue with Shift to Current Frame not updating the time edit boxes in the subs edit box, resulting in commit using the previous no longer valid times. Fixes #897
Originally committed to SVN as r3081.
2009-06-19 22:18:30 +00:00
Niels Martin Hansen 69ed7c4e3e Add iconv project to Windows tinderbox solution file, and make the Aegisub project dependent on it, in preparation of iconv patch.
Originally committed to SVN as r3079.
2009-06-17 18:24:15 +00:00
Niels Martin Hansen 6bff95373a Put iconv.vcproj in line with the other contrib etc. vcprojs:
* Add x64 configurations
 * Add contrib-outdirs.vsprop property sheet to put output dirs in line

Originally committed to SVN as r3078.
2009-06-17 17:55:30 +00:00
Thomas Goyne 2bcdeb0692 Added a stripped down version of iconv with everything but libiconv and libcharset removed and a vcproj for building in MSVC added.
Originally committed to SVN as r3077.
2009-06-17 17:48:27 +00:00
Niels Martin Hansen 5dddb9dc9a I can't spell names...
Originally committed to SVN as r3076.
2009-06-17 04:10:11 +00:00
Niels Martin Hansen 3be2db2037 New config for Windows buildbot.
* Add ffms2 support to build
 * Make sure Avisynth and ffms2 support is only built in 32 bit builds, as they can't work in 64 bit yet.

Originally committed to SVN as r3075.
2009-06-17 03:57:03 +00:00
Niels Martin Hansen 580341ea26 Change some nicknames for real names in About box, updates #894.
Originally committed to SVN as r3074.
2009-06-17 02:42:26 +00:00
harukalover e0ac4c7490 Fixed a memory leak that occurred from canceling loading of audio with cache type set to RAM
Originally committed to SVN as r3073.
2009-06-17 02:04:01 +00:00
Amar Takhar 1a85b179dc Add cs (Czech) to LINGAS, anytime a language is added don't forget to add the file here!
Originally committed to SVN as r3072.
2009-06-17 01:45:13 +00:00
Niels Martin Hansen fd87b3efe7 New background for DMG for Mac OS X installs. Closes #869.
Originally committed to SVN as r3071.
2009-06-17 01:43:00 +00:00
Amar Takhar 8cd33bd57f Remove whats probably a cut and paste-o introduced in r3069.
Originally committed to SVN as r3070.
2009-06-17 01:02:32 +00:00
Niels Martin Hansen 6b0b37039d Update credits in About box, see #894.
Originally committed to SVN as r3069.
2009-06-17 00:49:41 +00:00
Niels Martin Hansen 485881fb7c Fix #885, for some reason mouse events were firing in the audio display while some internal variables were invalid. Now mouse events are skipped if the display is missing a player or provider.
Originally committed to SVN as r3068.
2009-06-16 23:44:06 +00:00
Niels Martin Hansen 7654458b0f Got all the Unicode codepoints listed in Plorkyeran's patch and listed them in an array, to avoid encoding the source file as UTF-8 or UTF-16. Updates #710, seems to fix it but someone please confirm.
Originally committed to SVN as r3067.
2009-06-16 23:29:56 +00:00
Niels Martin Hansen dbf286136e Add all translations to installer, comment out those that aren't up to date.
This should be all required for 2.1.7, so close #863.

Originally committed to SVN as r3066.
2009-06-16 21:23:53 +00:00
Niels Martin Hansen 688cea62f4 Fix #892, LuaScriptReader wasn't checking if opening the file actually succeeded.
Check, and throw an exception if it fails.

Originally committed to SVN as r3065.
2009-06-16 21:21:25 +00:00
Niels Martin Hansen 293f6fb32e * Change version string formatting to a cleaner format.
* Non-FINAL_RELEASE builds no longer show a version number, only SVN revision.
 * FINAL_RELEASE builds show SVN revision in About box only.
 * Also change FINAL_RELEASE version number to 2.1.7.

Originally committed to SVN as r3064.
2009-06-16 19:11:08 +00:00
Niels Martin Hansen 5cae92b4ae New splash screen, following theme from Windows installer splash: Faded out and cropped shield in background, logo superimposed.
Closes #858 unless someone complains loudly.

Originally committed to SVN as r3063.
2009-06-16 19:08:54 +00:00
Niels Martin Hansen 8329868894 Updates to installer, see #863.
* Add bitmaps for large fonts configurations of Windows to installer.
 * Add auto-complete support to dir entry box in installer.
Thanks to ender.

Originally committed to SVN as r3062.
2009-06-16 18:17:33 +00:00
Niels Martin Hansen 5f097338e4 Remove unused RuntimeTestLibrary code.
Originally committed to SVN as r3061.
2009-06-16 17:34:21 +00:00
Niels Martin Hansen c31b39952a Updated splash image for Windows installer, updates #863.
Also includes Paint.NET source image.

Originally committed to SVN as r3060.
2009-06-16 17:33:41 +00:00
Niels Martin Hansen dac09935ae Update license file installed with Windows version, also see #863.
Originally committed to SVN as r3059.
2009-06-16 17:23:59 +00:00
Niels Martin Hansen 624c81c0b2 More updates to installer, updates #863.
* Use a simple but (hopefully) very reliable way of detecting whether runtimes need to be installed: Check for an uninstaller entry for the runtimes.
 * Clean up from most, hopefully all, 2.x alpha and pre-release installers we have previously put out.
 * Also clean combinations of 1.x and 2.x pre-rel versions installed on top of each other.
 * TODO: List all completed translation files for installation.

Originally committed to SVN as r3058.
2009-06-16 17:09:42 +00:00
Niels Martin Hansen 52271d6a56 Installer updates for 2.1.7:
* Now picks up (almost) all files from a tree in src/ under dir with the .iss file
 * Perfect (I think) upgrade from 1.x versions
 * Remove the compile defines stuff, there's only one installer version
 * Good, old-fashioned unconditional installation of MSVC runtimes
To be done:
 * Upgrades from earlier 2.x versions (need to collect samples to test against)

Originally committed to SVN as r3057.
2009-06-16 02:06:09 +00:00
harukalover 33d15e8c09 Fixed a memory leak that would occur when loading audio while using the hard disk cache
Originally committed to SVN as r3056.
2009-06-14 04:29:20 +00:00
Niels Martin Hansen 022c948205 Fix #890, make the output formatting for Adobe Encore format use a format string for clearness, instead of string building.
Originally committed to SVN as r3055.
2009-06-14 02:42:52 +00:00
Amar Takhar 58862610bc Add -I../FFmpegSource2 to AM_CXXFLAGS. This is *definatly* not the right way to do it, it's a temp measure until I figure out the best way to handle it.. updates #883.
Originally committed to SVN as r3054.
2009-06-12 17:26:56 +00:00
Niels Martin Hansen 9d51917ac5 Add FINAL_RELEASE and WITH_STARTUPLOG defines (both commented out) in config_windows0.h base.
Originally committed to SVN as r3053.
2009-06-12 17:13:22 +00:00
Karl Blomster db2ba854dc - Moved lib/ffms2.lib to FFmpegSource2/ffms2.lib.
- Deleted the lib folder since nothing uses it anymore.
- Modifed the #include of ffms.h in ffmpegsource_common.h to make it easier to use an external ffms2 instead of the one in the repository.
- Updated vs2008 project file to reflect these changes.
- Easily claims build breaker's hat.

Originally committed to SVN as r3052.
2009-06-12 17:10:45 +00:00
Niels Martin Hansen 03a2a70c92 Add super secret WITH_STARTUPLOG define, if enabled it causes insane amounts of message box spam during startup. Currently only implemented on Windows and should be disabled for almost all conceivable purposes.
Originally committed to SVN as r3051.
2009-06-12 16:59:53 +00:00
harukalover 3568774cab Fixed a memory leak that would occur after using any help button
Originally committed to SVN as r3050.
2009-06-12 00:04:35 +00:00
harukalover 0ff5b0194e Fixed compilation support with wxWidgets 2.9.0 (seems to work correctly besides some minor gui issues)
Originally committed to SVN as r3049.
2009-06-11 23:30:33 +00:00
harukalover 1a44455205 Update link to bug tracker in Help menu
Originally committed to SVN as r3048.
2009-06-11 18:04:48 +00:00
harukalover be9a4a8319 Oops, r3045 caused crashing issues when closing the translation assistant again. Fixed the crash without having to revert the fix for the memory leaks again.
Originally committed to SVN as r3047.
2009-06-11 08:13:54 +00:00
Amar Takhar 9654e58881 Remove *portaudio2.(cpp|h) from the vcproj.
Originally committed to SVN as r3046.
2009-06-11 03:00:12 +00:00
harukalover bf1ddf4f7b * Fixed an issue with the translation assistant not remembering the last position it was placed at before closing it
* Fixed some memory leaks in the translation assistant

Originally committed to SVN as r3045.
2009-06-11 02:33:21 +00:00
harukalover de26551082 Fixed a memory leak in the auto4 ScriptFactory
Originally committed to SVN as r3044.
2009-06-11 02:17:42 +00:00
Amar Takhar 905b41dd5a Supplant the portaudio player with the portaudio2 player. This still doesn't handle some of the issues that happen on linux, that will be fixed in a later commit, updates #876.
Originally committed to SVN as r3043.
2009-06-10 04:45:57 +00:00
Amar Takhar 322467e32b Completely revert r2970 as line 84 causes crashes elsewhere. While the rest may not cause any issues it's better to deal with some leaking memory than hard crashes.
Originally committed to SVN as r3042.
2009-06-10 03:49:59 +00:00
harukalover bc3b986df7 Fixed a memory leak that would occur when using the visual typesetting tools
Originally committed to SVN as r3041.
2009-06-10 03:32:18 +00:00
Amar Takhar 816f77e192 Revert line 85 from r2970 as it causes aegisub to crash in very interesting ways. It's most likely not aegisubs fault entirely however removing this does fix the issue.
Originally committed to SVN as r3040.
2009-06-10 03:32:15 +00:00
Amar Takhar 14e0a51876 Remove support for old FFMPEG releases, if you require or want this support you are officially on your own, closes #875.
Originally committed to SVN as r3039.
2009-06-10 02:21:20 +00:00
Amar Takhar f1c598ef58 The finance department (jfs) let me know that we don't depreciate things here, only deprecate.
Originally committed to SVN as r3038.
2009-06-10 02:15:40 +00:00
Amar Takhar e0beddbaf0 Ensure the system 'convert' utility is actually from ImageMagick.
Originally committed to SVN as r3037.
2009-06-10 02:13:24 +00:00
Amar Takhar 3e0ef96103 Disable FFMPEG provider, use --with-provider-ffmpeg to enable, closes #874.
Originally committed to SVN as r3036.
2009-06-10 02:09:00 +00:00
Amar Takhar 1006a36539 Set versions for ffmpeg: avcodec 52.27.0, avformat 52.32.0, avutil 50.3.0, postproc 51.2.0 and swscale 0.7.1, all of these are from r18642 in ffmpeg.. updates #831
Originally committed to SVN as r3035.
2009-06-09 20:47:28 +00:00
Niels Martin Hansen 6bbbe474b4 Updated Russian translation, closes #865.
Originally committed to SVN as r3034.
2009-06-08 15:04:01 +00:00
Niels Martin Hansen 9c79258f6c Fix #872, make the gridlines colour be the same as the text colour in the kanji timer display.
Originally committed to SVN as r3033.
2009-06-08 03:34:09 +00:00
Niels Martin Hansen b2ff338dd8 Mostly rewrite the kanji timer. Now using a custom control that avoids most of the problems the old implementation using text-boxes had. The new implementation unifies the pre-grouping and post-grouping display into one.
The auto-matching algorithm for Japanese was also rewritten, I think the new code works somewhat better. (For the song I used for testing, I can just hit Enter most of the way through, more than I remember being able to with the old.)
There are some slight oddities with the way the display scrolls when the input goes too close to the edge, but while it can feel confusing it should still keep everything you want to see, visible.
Fixes #847 and #708.

Originally committed to SVN as r3032.
2009-06-08 02:37:09 +00:00
Niels Martin Hansen 1c9f3f9ce0 Extend the kana table with a bunch more specialty characters and notations, and comment the existing esoteric katakana entries.
Updates #847.

Originally committed to SVN as r3031.
2009-06-07 23:51:15 +00:00
Niels Martin Hansen 5a162e53bf The KanaTable was missing a destructor. Nobody noticed because the old kanji timer code created but never deleted KanaTable objects on the heap... yes that was a memory leak that'll also get plugged by the rewrite of the kanji timer.
Updates #847.

Originally committed to SVN as r3030.
2009-06-07 23:15:02 +00:00
harukalover f73c129b55 Made the styling assistant require a double click to select a style, this fixes issues with mistakenly selecting a style when the user is just trying to focus the assistant
Originally committed to SVN as r3029.
2009-06-07 03:43:12 +00:00
Niels Martin Hansen 513fcb4121 The AssEntry::Clone() function ought to have been const all the time... make it. (Ugh, I had to make a const_cast in AssStyle::Clone().)
Originally committed to SVN as r3028.
2009-06-07 00:22:36 +00:00
Niels Martin Hansen e4ef6ebf72 The AssKaraoke parser can just as well take a const AssDialogue for parameter.
Originally committed to SVN as r3027.
2009-06-07 00:20:30 +00:00
Amar Takhar 72b94648e8 Fix #846, patch from pomyk, thanks!
Originally committed to SVN as r3026.
2009-06-06 21:05:31 +00:00
Niels Martin Hansen 9e931f341c A bit of const correctness for AssDialogue
Originally committed to SVN as r3025.
2009-06-06 19:32:17 +00:00
Niels Martin Hansen d1fe4bc8ea Close #491 (again), force the min-size of the detached video to be (1,1) after creation and layout.
Originally committed to SVN as r3024.
2009-06-06 14:36:22 +00:00
Niels Martin Hansen e3d10e1896 Fix #491: Let the detached video dialogue take a parameter indicating the initial video size.
Originally committed to SVN as r3023.
2009-06-06 02:57:42 +00:00
Niels Martin Hansen ba3df8b4e5 Fix #598, repaint the audio display upon playback to get rid of any junk on it.
Originally committed to SVN as r3022.
2009-06-06 02:32:31 +00:00
Niels Martin Hansen 8be4101d70 Fix #787, make the Paste and Paste Over commands in the Edit menu sensitive to the current format on the clipboard and only enable them if plain text is a supported format. They will also be enabled if the clipboard fails to open, as a safety device.
Originally committed to SVN as r3021.
2009-06-06 02:16:20 +00:00
Niels Martin Hansen 286ffcfaae Close #861, remove colour dropper tool on non-Windows platforms for now.
Originally committed to SVN as r3020.
2009-06-06 01:59:33 +00:00
Niels Martin Hansen 8b9e3844a6 Fix #607: Have style editor save its position and size during the session, similar to how several other dialogues already do. The stored position is not persistent, it is lost when Aegisub is closed.
Originally committed to SVN as r3019.
2009-06-05 02:02:55 +00:00
Niels Martin Hansen 4e00153303 Clean up code in Style Editor a bit, remove no longer needed performance measurement code.
Originally committed to SVN as r3018.
2009-06-05 01:49:06 +00:00
Niels Martin Hansen 3ca48f660e Close #839, the Shift Times function will now only do something if shifting by a non-zero number of milliseconds, or always if shifting by a number of frames (even zero).
Originally committed to SVN as r3017.
2009-06-05 00:02:26 +00:00
Niels Martin Hansen 62671f8f7a Add sample endianness info to all audio providers (except one, intentionally; see the stream provider changeset), and make the converting audio provider convert to native endian when required. Updates #725 but needs some testing. Might break compilation in some places, but shouldn't. ("Works for me.")
Originally committed to SVN as r3016.
2009-06-04 23:02:29 +00:00
Niels Martin Hansen 3ce395544f Adjust calculation of secondary colour for checkerboard pattern in dummy video provider. New calculation produces better results for dark colours, the old calculation produced very high contrast patterns for dark colours.
Originally committed to SVN as r3015.
2009-06-04 02:28:46 +00:00
Niels Martin Hansen d1251757ef Another shot at fixing wxGLCanvas woes on Mac, updates #850. This time the code is also considerably simpler!
Originally committed to SVN as r3014.
2009-06-04 02:05:11 +00:00
Niels Martin Hansen cf9fb5ae9a Experimental stuff trying to fix wxGLContext errors on Mac, updates #850. Untested, might break build for Mac.
Originally committed to SVN as r3013.
2009-06-04 01:35:11 +00:00
Amar Takhar 222f075778 Revert part of r3005, rename AV_PKT_FLAG_KEY back to PKT_FLAG_KEY, ffmpeg has added a compat define for any programs still using the old define. This is a temporary measure until we figure out how to properly handle it.
Originally committed to SVN as r3012.
2009-06-04 00:17:14 +00:00
Niels Martin Hansen a1f1514038 Remove all traces of local configuration support ("portable application") in non-Windows builds. Closes #856.
Originally committed to SVN as r3011.
2009-06-03 23:42:47 +00:00
Niels Martin Hansen 08e0c2373c Make the visual typesetting toolbar a bit prettier on Vista and probably also Win7, by removing themed background that didn't blend in with the surroundings.
Originally committed to SVN as r3010.
2009-06-03 23:18:40 +00:00
Niels Martin Hansen 332cd7b42e Really fix detached video, closes #853.
Originally committed to SVN as r3009.
2009-06-03 23:08:40 +00:00
Niels Martin Hansen 8212f6944b Work on fixing detached video, still broken but works a little better now. Updates #853.
Originally committed to SVN as r3008.
2009-06-03 23:01:03 +00:00
harukalover 016ed435b1 Fixed a memory leak that occurred when using undo/redo, fixes #330
Originally committed to SVN as r3007.
2009-06-03 19:55:39 +00:00
harukalover 5c89ff4a50 Add some sanity checking to SelectRow to prevent an invalid row from being selected when undoing line insertions
Originally committed to SVN as r3006.
2009-06-03 19:04:54 +00:00
Fredrik Mellbin ec297a5f11 FFMS2:
Flag keyframes in generated packets more properly
Requires FFmpeg r19078 to compile because of the changed define names

Originally committed to SVN as r3005.
2009-06-03 14:35:21 +00:00
Amar Takhar 5fa6858d92 Work around ancient versions of intltool...
Originally committed to SVN as r3004.
2009-06-02 01:58:00 +00:00
Amar Takhar d21292667a Print the configure commandline before running it.
Originally committed to SVN as r3003.
2009-06-02 01:56:47 +00:00
Amar Takhar f6198f7fe8 Fix FreeBSD dist building under buildbot.
Originally committed to SVN as r3002.
2009-06-02 01:56:29 +00:00
Amar Takhar 4783530e9f Fix osx-bundle and osx-dmg breakage after adding buildbot support, both scripts now accept spaces in the directory names.
Originally committed to SVN as r3001.
2009-06-02 00:16:45 +00:00
Niels Martin Hansen 703ae3f7a6 Fix #859, or rather work around it. There's no good way to detect problematic regexes like the example, and the regex engine lies in wx, so we'll have to do with what wx offers. Put a limit of at most 1000 replacements per line processed, that "should be enough for everyone", and avoids infinite looping.
(Also 3000 GET!)

Originally committed to SVN as r3000.
2009-06-01 15:44:59 +00:00
Niels Martin Hansen 721d8aad79 Reword error messages introduced in r2998 to make it Aegisub's fault and not the graphics drivers'. Even if our code is technically correct, it's still our problem.
Updates #799.

Originally committed to SVN as r2999.
2009-06-01 15:29:22 +00:00
Niels Martin Hansen 66821aa145 Add some error catching in the OpenGL code, this should make most OpenGL-related problems less fatal, though it can still cause funky UI problems I think.
At least the user should get a slightly more useful error message now.
Updates #799.

Originally committed to SVN as r2998.
2009-06-01 15:26:26 +00:00
Niels Martin Hansen 49ba78c08e Make DSound2 audio player use dynamic latency trickery and only do streaming (looping buffer) playback for long playback durations. This should fix most if not all "could not lock buffer" errors and close #855.
Originally committed to SVN as r2997.
2009-06-01 14:53:18 +00:00
Niels Martin Hansen d7d07dc797 Fix #599, the wrong overload for wxSpinCtrl::SetValue was used causing only the edit control part to be updated.
Originally committed to SVN as r2996.
2009-06-01 13:57:34 +00:00
Karl Blomster 9e22e1456c Update ffms2.lib
Originally committed to SVN as r2995.
2009-06-01 13:55:06 +00:00
Fredrik Mellbin 72bb9214fb FFMS2: Improve LAVF audio seeking in weird files
Originally committed to SVN as r2994.
2009-05-29 16:35:10 +00:00
Fredrik Mellbin 974bad3b6e FFMS2: beta 9 TAG!
Originally committed to SVN as r2993.
2009-05-28 20:26:18 +00:00
Fredrik Mellbin 02065a7509 Changes required to compile because of the previous commit
Originally committed to SVN as r2992.
2009-05-28 19:34:52 +00:00
Fredrik Mellbin 38c420c7bd FFMS2:
Renamed a public api function just because I can
Less access violations (AGAIN!)
Dumping now implies indexing too
Much better logic for automatically indexing files when FFAudioSource is used in avisynth
Changed defaults for FFIndex
Now FFmpeg's internal codec lists are used for lookup from the non-lavf based parts

Originally committed to SVN as r2991.
2009-05-28 19:33:14 +00:00
harukalover 68a7d04f06 Revert r2965 and r2961, although they fixed the memory leaks they also caused a crash when closing either dialog under some operating systems
Originally committed to SVN as r2990.
2009-05-27 02:08:21 +00:00
Karl Blomster 114bc5b367 Do COM initialization more properly (I think) in the FFMS2 providers.
Originally committed to SVN as r2989.
2009-05-25 16:42:33 +00:00
Karl Blomster 4ba221a931 Another missing ifdef in ffmsindex
Originally committed to SVN as r2988.
2009-05-25 16:28:28 +00:00
Fredrik Mellbin 64242fd363 FFMS2: unix ifdefs in ffmsindex
Originally committed to SVN as r2987.
2009-05-25 16:25:43 +00:00
Karl Blomster 5a193a73ec Update FFMS2 providers to initialize COM when running under Windows, as per the new FFMS2 init procedure.
Originally committed to SVN as r2986.
2009-05-25 15:52:42 +00:00
Karl Blomster 3a947259f7 Update FFMSIndex to work with the new audio dump method.
Also update ffms2.lib (again).

Originally committed to SVN as r2985.
2009-05-25 15:50:31 +00:00
Fredrik Mellbin 5857345b8d FFMS2: revert the initialization mess, instead require the caller to initialize com where it's needed
Originally committed to SVN as r2984.
2009-05-25 14:05:04 +00:00
Karl Blomster c60b4b449f Update ffms2.lib
Originally committed to SVN as r2983.
2009-05-25 13:44:27 +00:00
Niels Martin Hansen 29a9d1fcf1 Turn broken hotkeys.dat file into a non-fatal error. If the file is broken (usually meaning exists but empty) the existing file will now be copied to hotkeys.bak and the defaults restored and saved as hotkeys.dat.
Originally committed to SVN as r2982.
2009-05-24 23:19:28 +00:00
Fredrik Mellbin 12482ac418 FFMS2: more initialization fun
Originally committed to SVN as r2981.
2009-05-24 23:04:11 +00:00
Karl Blomster 72dc17af28 Update ffms2.lib as per usual
Originally committed to SVN as r2980.
2009-05-23 23:03:57 +00:00
Fredrik Mellbin 45dc8d8819 FFMS2: The usual small fixes
Originally committed to SVN as r2979.
2009-05-23 20:04:38 +00:00
Fredrik Mellbin da8163055c FFMS2:
Simplify the avisynth filters
Small api change => you can now list a group of desired colorspace output formats for automatic selection, less functions can return errors
Less singnedness warnings

Originally committed to SVN as r2978.
2009-05-23 14:18:51 +00:00
Fredrik Mellbin 3a7618cd64 FFMS2: Use the average fps for files opened with Haali's splitters
Originally committed to SVN as r2977.
2009-05-22 23:41:37 +00:00
Fredrik Mellbin cb1a9ba0b3 FFMS2:
Fix the weird crash bug
Fix *nix compilation

Originally committed to SVN as r2976.
2009-05-22 23:28:08 +00:00
Fredrik Mellbin 24c0a673b9 FFMS2: Missing #ifdef
Originally committed to SVN as r2975.
2009-05-22 22:12:31 +00:00
Karl Blomster edc10f752c Fix ffms2 providers to work with latest FFMS2 API changes.
Originally committed to SVN as r2974.
2009-05-22 21:44:02 +00:00
Karl Blomster 6b42083504 Update ffms2.lib to get in sync with last commit.
Originally committed to SVN as r2973.
2009-05-22 21:30:57 +00:00
Fredrik Mellbin d2c469e3e0 FFMS2:
Added audio decoding using Haali's splitters
Restructuring
Big API changes
Many bug fixes

Originally committed to SVN as r2972.
2009-05-22 21:28:02 +00:00
Niels Martin Hansen 8a04053ff2 Increase grabbing zone for karaoke split markers from 4 to 7 pixels, makes dragging much easier, speeding up work.
Originally committed to SVN as r2971.
2009-05-22 14:30:51 +00:00
harukalover 9550bc6366 Fixed some of the larger memory leaks in the LibassSubtitlesProvider detected by valgrind
Originally committed to SVN as r2970.
2009-05-22 04:09:09 +00:00
harukalover 8a417de164 Initialize a variable in the audio display that sometimes was used without any initial value being assigned to it.
Originally committed to SVN as r2969.
2009-05-22 02:27:36 +00:00
Niels Martin Hansen d40b0f36f6 Make error handling in DSound2 audio player more robust. When an error happened in the playback thread, the error_happened flag was set, but was never cleared when the error was detected in the main thread. Furthermore, the main thread didn't act upon the error besides showing it, it kept acting as if the playback thread was still alive and playing, causing the error to be triggered continuously requiring you to kill Aegisub to get out.
Made the error_happened event reset itself after being checked so the check only succeeds the first time. (The playback thread returns from its threadproc upon error.) Mark playback thread as dead when error is detected, such that a new thread will be created next time playback is started, effectively making errors non-fatal.
Playback still works as expected, however I haven't tested what actually happens now when an error occurs.

Originally committed to SVN as r2968.
2009-05-22 01:41:31 +00:00
harukalover 82f02efba8 Fixed some mismatched new[]/deletes in the audio display detected by valgrind
Originally committed to SVN as r2967.
2009-05-22 00:05:25 +00:00
harukalover b4a250122a Fixed a memory leak in the CSRISubtitlesProvider
Originally committed to SVN as r2966.
2009-05-21 23:02:34 +00:00
harukalover e771de5483 Fixed some memory leaks in the kanji timer
Originally committed to SVN as r2965.
2009-05-21 22:57:43 +00:00
harukalover b5d7851413 Fixed a memory leak in the style manager, the storage of catalog styles was never being cleared when closed.
Originally committed to SVN as r2964.
2009-05-21 22:24:52 +00:00
harukalover eadf49d10e Fixed some memory leaks in the style manager detected by valgrind
Originally committed to SVN as r2963.
2009-05-21 22:15:32 +00:00
harukalover bfce57662e Fixed a memory leak in the dummy video provider detected by valgrind. The video frame was being allocated but never deallocated.
Originally committed to SVN as r2962.
2009-05-21 19:49:23 +00:00
harukalover 68d705fd22 Fixed some memory leaks in the translation assistant detected by valgrind
Originally committed to SVN as r2961.
2009-05-21 18:37:36 +00:00
Fredrik Mellbin 73dbcf6ecd FFMS2: More ICL warning inspired fixes
Originally committed to SVN as r2960.
2009-05-21 10:39:14 +00:00
Fredrik Mellbin 7b0efd10f8 FFMS2: ICL compilation fix
Originally committed to SVN as r2959.
2009-05-21 10:05:53 +00:00
Niels Martin Hansen 4f14cddf4f Remove outdated VSFilter code.
All Aegisub patches to VSFilter were ported to the "guliverkli2" fork project on SourceForge. and several new patches were applied to that project since then.

Originally committed to SVN as r2958.
2009-05-21 00:03:20 +00:00
Fredrik Mellbin 3d2ad9525a FFMS2: Another small typo after all the changes
Originally committed to SVN as r2957.
2009-05-20 22:40:55 +00:00
Fredrik Mellbin 9d636c3cfb FFMS2: Missing #ifdef
Originally committed to SVN as r2956.
2009-05-20 19:05:42 +00:00
Fredrik Mellbin cd7932d6ee FFMS2:
Split indexing into a 2 step process so track numbers/types become known in advance
Big code cleanup and renaming

Originally committed to SVN as r2955.
2009-05-20 18:57:03 +00:00
harukalover 1e52702f0a Initialized a variable that was being used before it was assigned an initial value
Originally committed to SVN as r2954.
2009-05-20 18:29:01 +00:00
Niels Martin Hansen bd485315a8 Update #742, attempt fixing the bug. Removing wxEXPAND from some sizers, seems to work fine on Windows. Will test Mac build when tinderbox builds it.
Originally committed to SVN as r2953.
2009-05-18 23:37:41 +00:00
harukalover bace72cf29 * Fixed some more memory leaks reported by valgrind and msvc by reimplementing a couple of singleton pattern based classes
* Fixed a memory leak that occurred from never deleting a wxBitmap allocated in OpenGLTextGlyph

Originally committed to SVN as r2952.
2009-05-18 05:51:37 +00:00
harukalover 14e3cb4323 Fix a bunch of memory leaks reported by valgrind and msvc about the registered factories never being cleared.
Originally committed to SVN as r2951.
2009-05-18 05:42:54 +00:00
harukalover 55f4a80904 Add a corresponding PopEventHandler call for each PushEventHandler call, this fixes a couple of memory leaks reported by valgrind and msvc.
Originally committed to SVN as r2950.
2009-05-18 05:33:49 +00:00
harukalover 2feb39393d Call TestDestroy() to ensure we can delete the FontsCollectorThread, fixes #561
Originally committed to SVN as r2949.
2009-05-18 05:24:07 +00:00
Karl Blomster ea8841932b Update FFMS2 providers to account for FFMS2 API change in last commit.
Also update ffms2.lib to corresponding version.

Originally committed to SVN as r2948.
2009-05-17 22:12:46 +00:00
Fredrik Mellbin fdf73126b9 FFMS2:
Some more API cleanup
General cleanup

Originally committed to SVN as r2947.
2009-05-17 22:02:43 +00:00
Karl Blomster cf96f7c8ad Update Japanese translation.
Originally committed to SVN as r2946.
2009-05-17 15:17:52 +00:00
harukalover 5b9bd7ac6d Prevent an out of range exception from being thrown. (was commonly being thrown when commit was used on the last row of the grid)
Originally committed to SVN as r2945.
2009-05-17 05:47:28 +00:00
Niels Martin Hansen a60d16913d Make FFmpegSource video and audio providers build again after FFMS2 changes last night.
Originally committed to SVN as r2944.
2009-05-16 12:47:23 +00:00
Niels Martin Hansen d6cea9d93e Updated ffms2.lib.
Originally committed to SVN as r2943.
2009-05-16 12:46:50 +00:00
Niels Martin Hansen 741c3fbd4e Split video backend and UI into separate groups in MSVC project file.
Originally committed to SVN as r2942.
2009-05-16 12:46:22 +00:00
Amar Takhar e5eb667879 As required by r2940 supply -DFFMS_EXPORTS when building the library.
Originally committed to SVN as r2941.
2009-05-16 12:13:27 +00:00
Fredrik Mellbin 80a209e95a FFMS2:
Rename lots of things, THIS BREAKS THE AEGISUB BUILD because of changed exported type and function names.
Fixed an uninitialized memory bug that would make it crash on unindexed audio tracks in mastroska.
Made ffms.h C-friendlier.
Exports the start time of an audio track in the audio properties.
Less signedness and type conversion warnings.

Originally committed to SVN as r2940.
2009-05-15 23:11:18 +00:00
Niels Martin Hansen 6a999030f6 Hack to fix #687, if playing to end of audio, changing the selection end shouldn't affect the playback end: it should still play to end of audio.
Originally committed to SVN as r2939.
2009-05-15 15:23:34 +00:00
Niels Martin Hansen 0d1b45f7d1 Apply Plorkyeran's patch to close #843.
Originally committed to SVN as r2938.
2009-05-15 12:44:36 +00:00
Karl Blomster 1dbb23f106 Fix gcc breakage caused by last commit, and remove an unused variable while at it.
Originally committed to SVN as r2937.
2009-05-15 12:31:09 +00:00
Karl Blomster 5e214986e1 Add a bit of sanity checking to FractionalTime.
Originally committed to SVN as r2936.
2009-05-15 12:18:33 +00:00
harukalover 3011ade060 Fixed Replace Next not marking the script as modified.
Originally committed to SVN as r2935.
2009-05-15 02:50:43 +00:00
Niels Martin Hansen 3ce80afadf Fix #809, properly close all SRT overrides during export and ensure overrides in recombined lines do not affect each other (per the example I gave in the report.)
Originally committed to SVN as r2934.
2009-05-15 01:34:00 +00:00
Niels Martin Hansen 6e6447f215 Converting audio provider didn't know about channel count during bitdepth and samplerate conversion and intermixed samples from channels and more, resulting in garbage output. Fixes #726.
Originally committed to SVN as r2933.
2009-05-15 00:48:43 +00:00
Niels Martin Hansen a8bd30487b aegisub_endian.h was missing from MSVC project.
Originally committed to SVN as r2932.
2009-05-14 23:58:24 +00:00
Niels Martin Hansen c7c95d20c0 Fix #825 for good, I hope. Get some sense worked into the handling of AssEntry::StartMS and AssDialogue::Start using some private members and virtual getter/setter functions.
Originally committed to SVN as r2931.
2009-05-14 23:45:20 +00:00
Niels Martin Hansen 153cfbcd5f More const correctness in AssTime, broke build because I forgot to add const keyword to implementation too.
Originally committed to SVN as r2930.
2009-05-14 23:27:38 +00:00
Niels Martin Hansen 20477198e6 Const correctness in AssTime.
Originally committed to SVN as r2929.
2009-05-14 23:09:04 +00:00
Niels Martin Hansen 33696616f4 Change audio autoscroll behaviour:
* In karaoke mode, instead of scrolling start to end of active line into view, scroll start of selection to end of line into view. This gives sensible results when horizontal zoom is great enough that the entire line isn't visible at once and the syllable is too far from the start of the line. This fixes #677.
* If the line is too long to fit in the display, always left-align it instead of sometimes left-aligning and sometimes centering. (I think the old behaviour depended on the actual scroll position.)

Originally committed to SVN as r2928.
2009-05-14 22:12:05 +00:00
Niels Martin Hansen b19d604de4 Undo last change, code *was* used after all. Strangely my compiler didn't complain on first try...
Removing the comment about "is this even used?" as well...

Originally committed to SVN as r2927.
2009-05-14 21:44:43 +00:00
Niels Martin Hansen 00df76c4fb Remove some unused code from karaoke UI.
Originally committed to SVN as r2926.
2009-05-14 21:26:39 +00:00
Niels Martin Hansen ef03e3050d Split audio sources in MSVC project into Backend and UI groups.
Originally committed to SVN as r2925.
2009-05-14 21:25:08 +00:00
harukalover 82fca6e35f * Fixed a mismatched new[]/delete
* Fixed a memory leak that would occur when loading subtitles from a matroska file

Originally committed to SVN as r2924.
2009-05-14 18:28:57 +00:00
harukalover 370b986181 * Fixed the styling assistant marking the script as modified when it was unfocused and the Enable preview checkbox was unchecked even if no changes actually were made in the styling assistant.
* Removed some no longer needed code in the styling assistant.

Originally committed to SVN as r2923.
2009-05-14 17:29:07 +00:00
Niels Martin Hansen 5a4ffa1005 Fix #845 by counting how many output lines were produced by applying a template to a line, instead of assuming that a template always gets applied, even if it's a code template.
Originally committed to SVN as r2922.
2009-05-14 15:34:37 +00:00
harukalover d8e6d94754 Made the styling assistant modeless so the user can access other controls within aegisub without having to close the styling assistant, fixes #397
Originally committed to SVN as r2921.
2009-05-14 07:02:01 +00:00
Karl Blomster 6a42e17409 - Reworked the SMPTE timecode handling with Plorkyeran's help. It does now handle dropframe timecodes as well; the ms->SMPTE handling has been tested and seems reasonably correct, while the reverse conversion remains untested and unused. The Adobe Encore export filter will now use dropframe timecodes properly (previously it would play pretend with wallclock hours/minutes/seconds and incorrect frame numbers).
- Changed the SubtitleFormat::AskForFPS dialog box; removed the "PAL/NTSC only" choice and added a "show SMPTE dropframe" parameter instead. Also added 50fps as a choice.

- While I was at it, reworked the TranStation export filter so it actually looks ahead to see if the next line will overlap with the current, and if so, move the end time of the current line backwards one frame, which fixes #767

Originally committed to SVN as r2920.
2009-05-13 20:24:21 +00:00
Karl Blomster 887b9b1988 Update ffms2.lib as per Myrsloik's last commit.
Originally committed to SVN as r2919.
2009-05-12 21:31:44 +00:00
Fredrik Mellbin 16f3f59cb2 FFMS2: api change so the logging level can be set arbitrarily, it also defaults to quiet now
Originally committed to SVN as r2918.
2009-05-12 20:50:40 +00:00
Niels Martin Hansen ae988ed37b Apparently not all platforms agree on providing MININT and MAXINT constants. Work around it by calculating those values ourselves.
Originally committed to SVN as r2917.
2009-05-12 20:48:05 +00:00
Niels Martin Hansen f425b58017 Integer-edits in Auto 4 Lua config dialogues now always get spin buttons. If no min/max is specified, minint/maxint are assumed.
Originally committed to SVN as r2916.
2009-05-12 20:26:19 +00:00
Niels Martin Hansen e87a031828 Normalise case for style section names.
fixes #690 (hopefully)

Originally committed to SVN as r2915.
2009-05-12 18:10:13 +00:00
Niels Martin Hansen 86e70e9094 Bump kara-templater version number.
Originally committed to SVN as r2914.
2009-05-12 16:39:53 +00:00
Niels Martin Hansen 7e90cdcf09 Add support for variable loops in kara-templater, and add a few more utility functions.
- Variable loops are controlled using the tenv.maxloop(newmax) function to set the loop counter max. This is a wrapper around setting tenv.maxj.
- Add tenv.relayer(newlayer) function for changing the Layer of an output line.
- Add tenv.restyle(newstyle) function for changing the Style of an output line, despite this usually breaking positioning/sizing information.
- tenv.maxloops is an alias for tenv.maxloop.
- tenv.loopctl(newj, newmaxj) controls both loop variables if anyone wants to do that.
This closes #753 but documentation still needs to be written.

Originally committed to SVN as r2913.
2009-05-12 16:36:51 +00:00
Niels Martin Hansen 95d71d1dcf Fix a bunch of bugs with config dialogues in Auto 4 Lua:
- When default buttons were present, pushing OK caused no button code to be returned at all.
- A load of controls not handling default/initial values properly, closes #775 and #776

Originally committed to SVN as r2912.
2009-05-12 15:32:11 +00:00
Niels Martin Hansen cad5b98e1b Extend Auto 4 Lua config dialogues test case to cover most interesting cases of controls.
Updates #775 and #776 since they need those cases.

Originally committed to SVN as r2911.
2009-05-12 15:24:07 +00:00
Niels Martin Hansen 54037c56e7 Make AssColor::Parse() also understand HTML colours with a bit of help from wx.
Originally committed to SVN as r2910.
2009-05-12 15:14:35 +00:00
Karl Blomster d56982ed4a Move the SMPTE timecode stuff out of the AssTime class and put it in a class of its own, FractionalTime. The AssTime to SMPTE part is tested and verified to work (in fact it looks like I unintentionally fixed an overlap bug in the TranStation export filter), while the SMPTE to AssTime part is completely untested (but it's currently not used anywhere so it's not like it matters).
Originally committed to SVN as r2909.
2009-05-10 03:50:58 +00:00
Karl Blomster 179d23fd5c Fix a memleak in the FFMS2 video provider (the frame was never unallocated on video close). Patch by Harukalover, fixes #838
Originally committed to SVN as r2908.
2009-05-10 00:12:04 +00:00
Fredrik Mellbin 2cab187fd8 FFMS2: beta 8
Originally committed to SVN as r2907.
2009-05-09 21:59:24 +00:00
Karl Blomster 3bdbcd7b5e Fix a minor bug that caused the add leadin/leadout buttons to not update the time edit boxes. Patch by Harukalover, fixes #836.
Originally committed to SVN as r2906.
2009-05-07 17:52:29 +00:00
Karl Blomster 87a39833b8 The buffer length/wanted latency in the dsound2 audio player are now tweakable in config.dat; the options are called "audio dsound buffer latency" and "audio dsound buffer length" respectively. Defaults to 100/5 respectively (should work for the people who used to get buffer errors); for better responsiveness try 80/4.
Originally committed to SVN as r2905.
2009-05-07 14:47:36 +00:00
Karl Blomster bfe40a6667 Fix a bug (in a somewhat questionable manner) that would cause the text file writer to occasionally think the system locale was Unicode when it wasn't (by using an uninitialized variable in a condition). Should fix the issue with the SRT export filter failing to write "1" on the first line when using "local" as the text encoding.
Originally committed to SVN as r2904.
2009-05-06 19:14:10 +00:00
Karl Blomster c6fe68c76d Add Aegisub::Script::set_undo_point() to auto4-perl. Currently not all that useful since auto4-perl currently only supports macros and nothing else, and using a macro sets an undo point after execution automatically anyway.
Originally committed to SVN as r2903.
2009-05-06 12:25:08 +00:00
Karl Blomster 02f7d0006c change how ffmsindex is linked to ffms2 (use a #pragma instead of an extra dependency in the project file)
Originally committed to SVN as r2902.
2009-05-05 21:43:49 +00:00
Niels Martin Hansen 36dbd86dd6 Oops, had swapped size and value parameters in a memset call.
Originally committed to SVN as r2901.
2009-05-04 19:15:57 +00:00
Amar Takhar c9affe9aeb Sigh, make gawk happy, I despise gawk someone please get rid of it forever.
Originally committed to SVN as r2900.
2009-05-04 08:06:26 +00:00
Amar Takhar 8c8a0abe38 Add a note why the 'sed' hack is nessicary.
Originally committed to SVN as r2899.
2009-05-04 06:52:45 +00:00
Amar Takhar f893e8a29f Add a crappy sed hack to silence gcc warnings, sigh, I wish ImageMagick would update convert already.
Originally committed to SVN as r2898.
2009-05-04 06:51:02 +00:00
Amar Takhar 5b356f2755 s/static/const/ to silence gcc warnings.
Originally committed to SVN as r2897.
2009-05-04 06:50:37 +00:00
Amar Takhar 2090994256 Silence a bunch of gcc 'newline' warnings.
Originally committed to SVN as r2896.
2009-05-04 06:50:12 +00:00
Amar Takhar b00e485149 Plug a bunch of memory leaks from uau in the mplayer2 repo: http://repo.or.cz/w/mplayer.git?a=commit;h=312d9e4b104741b834aa5d71b02228d0cd988a4e
libass: Fix cache lookup problem causing memory bloat

The cache code did hash lookups by storing key values in struct fields
and then hashing and comparing the struct as a single memory block. In
at least one case such a struct contained uninitialized padding bytes
which prevented the complete memory area of the struct from matching
even though the fields did. As a result the code failed to find
existing objects in the cache and stored new versions of them, causing
gigabytes of memory use in some circumstances. Initializing the struct
memory to zero before writing the fields avoided such memory use in
tests but is not guaranteed to work if I interpret the C standard
correctly (the compiler is allowed to write garbage over padding bytes
when changing struct member values).

Change the code to use struct-specific hashing and comparison
functions that work field by field to guarantee correct behavior.
Create these by replacing the struct definition with a template that
lists the fields and can be used the generate each of struct
definition, hash function and compare function with some preprocessor
magic (otherwise every field would need to be listed separately in all
three).

Originally committed to SVN as r2895.
2009-05-04 06:48:21 +00:00
Fredrik Mellbin 0a221706d5 FFMS2:
Fix an old bug that would drop the first or second video frame
Greatly improved audio decoding by adding a small internal cache

Originally committed to SVN as r2894.
2009-05-03 19:25:54 +00:00
Karl Blomster 869e5c7594 Implemented an automated cache cleaner that keeps the FFMS2 index cache at a manageable size. Cleaning is started when video is opened with the FFMS2 video provider and runs in its own thread. Removal is based on last access time, and the FFMS2 providers now explicitly touch the index files on reading to make sure access time is updated.
By default the cache is kept below 42MB and 20 files; to change the defaults change "FFmpegSource max cache size" and "FFmpegSource max cache files" in config.dat. Either or both may be set to 0, but the cleaner will not delete the last index file in the directory, regardless of cache settings and of the file's size.

Originally committed to SVN as r2893.
2009-05-03 18:05:30 +00:00
Karl Blomster e3ce74248d Fix compilation breakage introduced in r2891.
Originally committed to SVN as r2892.
2009-05-02 20:06:06 +00:00
Karl Blomster 45627548d6 Don't let the MKV parser crash on certain MKV's for which it cannot determine the filesize by itself. (Adaption of Myrsloik's similar fix for FFMS2.)
Originally committed to SVN as r2891.
2009-05-02 19:40:55 +00:00
Fredrik Mellbin 487dc50409 FFMS2: Add a missing function the updated matroska parser expects
Originally committed to SVN as r2890.
2009-05-01 16:58:15 +00:00
Amar Takhar 1cbd29531c Add an sh script to generate snap tarballs upon successful builds of UNIX platforms (excluding Darwin).
Originally committed to SVN as r2889.
2009-05-01 03:58:23 +00:00
Niels Martin Hansen b840c9f97e Ensure some fields in VideoContext get initialised.
Originally committed to SVN as r2888.
2009-04-30 22:13:10 +00:00
Karl Blomster 4445d812ce Re-update the license on Haali's matroska parser.
Originally committed to SVN as r2887.
2009-04-29 21:19:45 +00:00
Amar Takhar a9e1f80c8c Update libass from MPlayer r29129: Don't automatically wrap lines when WrapStyle==2.
Originally committed to SVN as r2886.
2009-04-29 21:06:54 +00:00
Fredrik Mellbin fad9a58240 FFMS2: Update Haali's matroska parser
Originally committed to SVN as r2885.
2009-04-29 21:06:07 +00:00
Karl Blomster 2f7b62d206 Update Haali's MatroskaParser.c/.h in the main source tree (there's a copy in the FFMS2 folder as well, which will be updated later). Should fix a crash with x264-generated MKV's.
Originally committed to SVN as r2884.
2009-04-29 21:00:08 +00:00
Niels Martin Hansen f0b442f4b4 Let AudioProvider::GetAudioWithVolume() catch exceptions in AudioProvider::GetAudio() and return blank audio when that happens. Errors are not logged or otherwise handled. This fixes #800 for most cases, even if poorly.
Originally committed to SVN as r2883.
2009-04-29 19:30:02 +00:00
Niels Martin Hansen a2822356bf Some more delayload vsprops files.
Originally committed to SVN as r2882.
2009-04-29 19:08:40 +00:00
Karl Blomster 1f062a5553 remove duplicate variable
Originally committed to SVN as r2881.
2009-04-29 17:42:48 +00:00
Karl Blomster 9c93aeb179 Fix a few memory leaks in the FFMS2 providers. Patch by Myrsloik.
Originally committed to SVN as r2880.
2009-04-29 17:40:02 +00:00
Fredrik Mellbin 27e90e973f FFMS2: Beta 7 release
Fix 3 gcc warnings

Originally committed to SVN as r2879.
2009-04-29 16:39:15 +00:00
Karl Blomster 8bc3a39d0c Don't fail to read subtitles from MKV's that are named .mks or .mka, both of those are reported as supported formats in the "open subtitles" dialog box.
Originally committed to SVN as r2878.
2009-04-29 14:04:23 +00:00
Amar Takhar 29721b983e s/32/??/ to include 64bit builds (what was I thinking?).. it's better than using '*' which could lead to a disaster.
Originally committed to SVN as r2877.
2009-04-29 08:07:22 +00:00
Amar Takhar 1fb14af113 Use 'SetFile' instead of '/usr/bin/SetFile' when creating the .dmg, 10.5 puts it in /usr/bin, on 10.4 it's in /Developer/Tools/.
Originally committed to SVN as r2876.
2009-04-29 07:55:40 +00:00
Amar Takhar 05af876c1d * Favour '/usr/bin/perl' over 'perl' to ensure the base perl is always used. (it's required)
Originally committed to SVN as r2875.
2009-04-29 06:50:08 +00:00
Amar Takhar 02210e3669 * Re-format the arch detection case.
* Fix an annoying buy, I hate the loops configure gets stuck in when you do "$blah" = "$blah" vs test "$blah..

Originally committed to SVN as r2874.
2009-04-29 00:49:38 +00:00
Amar Takhar d769707641 * Add support in configure.in to detect the arch.
* Add two new targets, osx-tinderbox-(bundle|dmg) to handle tinderbox building.

Originally committed to SVN as r2873.
2009-04-28 23:25:42 +00:00
Amar Takhar 3267c11fed Change the buildslave dist name to dist.7z so the waterfall isn't cluttered. There's a link to the archive so it won't be an issue.
Originally committed to SVN as r2872.
2009-04-28 17:59:03 +00:00
Karl Blomster 876f726a6d Don't try to synch audio when there is no audio player/provider present. (Could cause a crash under certain rare conditions.) Thanks Avi for report and fix.
Originally committed to SVN as r2871.
2009-04-28 10:23:20 +00:00
Amar Takhar 800e57897b Add a batch file to generate a distfile that can be uploaded.
Originally committed to SVN as r2870.
2009-04-28 07:04:53 +00:00
Amar Takhar 9774fbb1c8 Remove an extra line (more testing.)
Originally committed to SVN as r2869.
2009-04-28 05:25:37 +00:00
Amar Takhar 77643ae596 Remove some EOF whitespace (more testing.)
Originally committed to SVN as r2868.
2009-04-28 05:24:28 +00:00
Amar Takhar 9079f1576f Remove some EOF whitespace.
Originally committed to SVN as r2867.
2009-04-28 05:21:23 +00:00
Amar Takhar 8a13a78229 Add some error-checking and exit 1's.
Originally committed to SVN as r2866.
2009-04-28 05:17:33 +00:00
Amar Takhar d929e60b4c Add exit codes to various commands to ensure the script fails and doesn't proceed to the next step(s).
Originally committed to SVN as r2865.
2009-04-28 05:11:32 +00:00
Amar Takhar 501782d605 Testing the tinderbox (a stub commit but still useful.)
Originally committed to SVN as r2864.
2009-04-28 05:08:18 +00:00
Amar Takhar bf99cbcd58 Testing the tinderbox.
Originally committed to SVN as r2863.
2009-04-27 20:58:42 +00:00
Niels Martin Hansen 03ec2ae033 Fix include file search path in CSRI project file for VC++ in x64 configurations.
Originally committed to SVN as r2862.
2009-04-26 21:01:18 +00:00
Karl Blomster 9444ebd0d1 Fix some more minor editbox regressions introduced in r2859. Patch by Harukalover, updates #794
Originally committed to SVN as r2861.
2009-04-26 04:31:19 +00:00
Karl Blomster 2ba20b12c8 Fix a minor graphical glitch in the time edit boxes introduced in r2859. Patch by Harukalover. updates #794
Originally committed to SVN as r2860.
2009-04-26 01:23:01 +00:00
Karl Blomster fe05adb64e Fix a number of odd quirks regarding how grid selection is moved after committing multiple lines, and how audio selection moves after committing. See #794 for full details. Patch by Harukalover.
closes #64, #420, #794

Originally committed to SVN as r2859.
2009-04-26 01:02:23 +00:00
Karl Blomster c8908fd2d1 Fix a bug that would cause a crash under certain conditions when trying to change the properties of a recently deleted line. Patch by Plorkyeran, closes #815
Originally committed to SVN as r2858.
2009-04-26 00:25:33 +00:00
Karl Blomster 2d11cb6769 Fix a bug that would cause the program to crash if CSRI was selected as subtitle renderer but no CSRI renderer was actually installed. Patch by Plorkyeran, closes: 462
Originally committed to SVN as r2857.
2009-04-26 00:11:29 +00:00
Karl Blomster 78736ce617 Use less magic numbers
Originally committed to SVN as r2856.
2009-04-25 23:08:45 +00:00
Karl Blomster 8c5e380264 Update ffms2.lib
Originally committed to SVN as r2855.
2009-04-25 23:04:06 +00:00
Amar Takhar 8d11b72059 Sigh, add @set before the recently added environment variables (r2847)
Originally committed to SVN as r2854.
2009-04-25 23:00:29 +00:00
Fredrik Mellbin bc46304aa1 FFMS2: Another much needed set of fixes to the Haali part
Originally committed to SVN as r2853.
2009-04-25 22:09:49 +00:00
Fredrik Mellbin 3655fbb7fa Fix the video provider after the FFMS2 changes part2
Originally committed to SVN as r2852.
2009-04-25 10:31:39 +00:00
Fredrik Mellbin 4c4df5f17a Fix the video provider after the FFMS2 changes
Originally committed to SVN as r2851.
2009-04-25 09:26:03 +00:00
Fredrik Mellbin 61d14a7b89 FFMS2: Even less enum forward declarations
Originally committed to SVN as r2850.
2009-04-25 09:09:14 +00:00
Fredrik Mellbin 4e7bff9bd6 FFMS2: Less enum forward declaration?
Originally committed to SVN as r2849.
2009-04-25 08:55:14 +00:00
Amar Takhar ac63f69e06 Add CommonProgramFiles CommonProgramFiles(x86) ProgramFiles ProgramFiles(x86) to the build environment.
Originally committed to SVN as r2847.
2009-04-25 02:04:33 +00:00
Amar Takhar dbb192b01a vc++ needs TMP/TEMP to be set in the env in order to work correctly.
Originally committed to SVN as r2846.
2009-04-24 23:23:48 +00:00
Fredrik Mellbin 4b74827df6 FFMS2:
Remove the dependency of pixfmt.h in ffms.h
Added the alternative FFMS_GetPixFmt() for getting the different pixel format values

Originally committed to SVN as r2845.
2009-04-24 19:56:19 +00:00
Karl Blomster 518678b930 Update ffms2.lib again
Originally committed to SVN as r2844.
2009-04-24 18:41:34 +00:00
Fredrik Mellbin b8cf6fce8e FFMS2:
Several bugfixes which should fix crashes in recent versions
Added a simple regression test application
Removed a few useless functions from the API
Add TheFluff's FFmpegSource 1.21 syntax compatibility script

Originally committed to SVN as r2843.
2009-04-24 17:42:21 +00:00
Amar Takhar 4777905b0a Whoops, remove trunk\ from the solution path.
Originally committed to SVN as r2842.
2009-04-24 04:16:01 +00:00
Amar Takhar 80ce8b4d77 Add a bath file to compile aegisub, these will exist _per_ buildslave. It's probably better to keep it here anyway as build environments will not be changable without a historical record being kept. (it's also easier!)
Originally committed to SVN as r2841.
2009-04-24 04:00:04 +00:00
Amar Takhar bcf82c0f9f Add a solution and windows config for Windows tinderbox building. Submitted by jfs, thanks!
Originally committed to SVN as r2840.
2009-04-23 20:26:07 +00:00
Karl Blomster b97bbf9792 Updated German translation (by Sebastian Billau).
Originally committed to SVN as r2839.
2009-04-23 10:32:00 +00:00
Karl Blomster 22faf80cdb Avisynth video provider will now use ffmpegsource2 instead of ffmpegsource when so required.
Originally committed to SVN as r2838.
2009-04-23 02:09:05 +00:00
Fredrik Mellbin bd0f1dcd10 FFMS2: Various fixes to haali stuff
Originally committed to SVN as r2837.
2009-04-22 18:38:28 +00:00
Amar Takhar 71c29969a3 Add a cross-compile condition to AC_RUN_IFELSE in AC_AGI_COMPILE to make cross-compiling work.
Originally committed to SVN as r2836.
2009-04-21 22:32:07 +00:00
Amar Takhar 09d32d8151 Bunk commit to trigger the build cluster.
Originally committed to SVN as r2835.
2009-04-21 18:48:59 +00:00
Amar Takhar 1118dcac4a Add a command to autogen --skip-configure to allow the autogen/configure steps
to be split for the build tinderbox.

Originally committed to SVN as r2834.
2009-04-20 02:45:35 +00:00
Amar Takhar f5124e7763 Fix typo.
Originally committed to SVN as r2833.
2009-04-20 02:43:32 +00:00
Niels Martin Hansen e8d1767428 Remove outdated and unused Windows installer scripts.
Originally committed to SVN as r2832.
2009-04-19 20:48:08 +00:00
Niels Martin Hansen b842a3ea76 Remove the annoyance known as Tip of the Day. Right now it's completely inaccessible, but might return in a different incarnation when we get out of strings freeze.
Originally committed to SVN as r2831.
2009-04-18 15:29:13 +00:00
Niels Martin Hansen 58ec137621 Simplify code to pick mapping size in PCMWAV provider, just use sizeof(void*) to determine address space size.
Originally committed to SVN as r2830.
2009-04-18 15:16:15 +00:00
Niels Martin Hansen 5a50efac9f Move more project settings into property sheet files.
Originally committed to SVN as r2829.
2009-04-18 13:40:52 +00:00
Niels Martin Hansen 30422e5ca8 Rename auto3 DLL to something less ugly.
Originally committed to SVN as r2828.
2009-04-18 13:31:08 +00:00
Karl Blomster 254a7ae359 revert revision 2825 since apparently it broke all of jfs' changes
Originally committed to SVN as r2827.
2009-04-18 13:02:13 +00:00
Karl Blomster c806ba8d72 "Fix" an issue that would cause the FFMS2 audio provider to crash when fed with a unicode filename/path. The solution involves getting the "short path", no idea if it works on Unix. Fixes bugtracker issues #810 and #808.
Originally committed to SVN as r2826.
2009-04-18 10:54:20 +00:00
Karl Blomster 3e70c0af81 add portaudio_x86.dll to the list of delay-loaded dll's in the vs2008 project file
Originally committed to SVN as r2825.
2009-04-18 09:37:54 +00:00
Karl Blomster f12a3a8af7 Fix an issue where the grid font face option's font browser button wouldn't actually update the setting. Patch by Harukalover, resolves bugtracker issues #706 and (partially) #821.
Originally committed to SVN as r2824.
2009-04-18 09:12:26 +00:00
Niels Martin Hansen 4787a2fcdb Visual Studio loves not saving property sheets unless told to VERY explicitly. Missed one for Lua 5.0.
Originally committed to SVN as r2823.
2009-04-17 22:39:43 +00:00
Niels Martin Hansen ffde7daec5 Adjust hunspell VC project to also use property sheets.
Originally committed to SVN as r2822.
2009-04-17 22:34:03 +00:00
Niels Martin Hansen 4fc3b7faf0 No longer support anything for Windows-builds but Visual Studio 2008/VC9.
Remove all outdated, unmaintained project files and some unused dirs, and other stuff related to outdated build methods.

Originally committed to SVN as r2821.
2009-04-17 22:08:37 +00:00
Niels Martin Hansen af538651ef Some changes to property sheets went unsaved before previous commit, oops.
(This made linking in various things impossible.)

Originally committed to SVN as r2820.
2009-04-17 21:58:17 +00:00
Niels Martin Hansen 2c392407c4 Refactor Visual Studio 2008 build and make libauto3 and Lua 5.0 build on VC9.
* The most important project properties (especially paths) are now stored in VSProps files in generalised ways.
* Projects share VSProps files so they place output files in same locations and thus agree on where to find them.
* Avoid inconsistencies between build configurations/platforms as has happened often before.
* Now distributable binaries (aegisub.exe and aegisub-auto3.dll) will be placed in $(SolutionDir)/bin/, static libraries under $(SolutionDir)/lib/ and object files etc. under $(SolutionDir)/build/. Note that those locations are controlled by where the solution file is placed in the file system.
* libauto3 is no longer pulled in by a #pragma in auto4_auto3.c, but must instead be pulled in by making the aegisub project depend on the auto3 project, which must in turn depend on the lua50 project.
* Final binary filenames are now somewhat different. You get aegisub32.exe, aegisub64d.exe, aegisub-auto3lib32d.dll and more.
* There's still more that can be factored out, things like optimisation flags and defines.

Originally committed to SVN as r2819.
2009-04-17 21:53:48 +00:00
Niels Martin Hansen 6d1207900b The lines.n value produced by Auto3 implementation was 1 too small causing the last line in a file to be eaten by karaskel.
Originally committed to SVN as r2818.
2009-04-17 21:34:43 +00:00
Niels Martin Hansen a3600f8ca1 Make callables.c error properly if it's attempted compiled separately.
Originally committed to SVN as r2817.
2009-04-17 20:55:48 +00:00
Niels Martin Hansen 2d64f5079f Make libauto3 better liked by MSVC 2008.
Originally committed to SVN as r2816.
2009-04-17 20:51:58 +00:00
Niels Martin Hansen e977f3c991 Force use of ANSI versions of Windows API's for runtime+loading of DLL's, causing problems when building with UNICODE defined.
Originally committed to SVN as r2815.
2009-04-17 20:20:37 +00:00
Karl Blomster 59eb07c79f add portaudio2 player to the vs2005 project as well while I'm at it
Originally committed to SVN as r2814.
2009-04-17 19:45:33 +00:00
Karl Blomster 80ce8e7508 add portaudio2 audio player to config/config_windows0.h and the vs2008 project file
Originally committed to SVN as r2813.
2009-04-17 19:44:07 +00:00
Karl Blomster 6a69da3331 change buffer length/wanted latency in the dsound2 audio player to 80/4 (down from 100/5); should make it a bit more responsive
Originally committed to SVN as r2812.
2009-04-17 19:40:29 +00:00
Karl Blomster 13c59b5af0 update ffms2.lib
Originally committed to SVN as r2811.
2009-04-17 19:38:12 +00:00
Niels Martin Hansen 19b5544a2a Fix crash in PCM audio provider when using files larger than the mapping size (256 MB on 32 bit). The length of mappings closer than mapping-size to the end of the file, when the file was larger, would not be adjusted to not cross the end of file.
Originally committed to SVN as r2810.
2009-04-17 16:34:06 +00:00
Amar Takhar 28470e309d Re-order the functions so they're in line with every other player: Constructor,
Destructor, Open, Close, Play, Stop..  I rue the fact that I didn't do this at
the start.

Originally committed to SVN as r2809.
2009-04-17 13:58:44 +00:00
Karl Blomster 0ad0b6d5c9 Fix a bug in FFMS2 that caused it to write timecodes with scientific notation.
Originally committed to SVN as r2808.
2009-04-17 03:25:10 +00:00
Amar Takhar 235af35603 * Remove a short-lived hack (hours?) and replace it with a
PaStreamFinishedCallback which is called anytime a PaCallback is exited with
  anything other than 0. (normal operation)  paStreamFinishedCallback handles
  stopping the audio stream when we've run to the end of the current selection
  or the stream is stopped.
* Add framesPerBuffer to paCallback debug output in preperation for dynamic
  buffers.
* Set paPrimeOutputBuffersUsingStreamCallback in Pa_OpenStream to prime the
  output buffer using the callback rather than initing with empty space which
  is the default.
* Indent paCallback decleration another level.

Originally committed to SVN as r2807.
2009-04-17 02:14:42 +00:00
Amar Takhar a3f9735d38 * Fold entire callback into a single if-else block.
* Remove 'end' variable and just return 0 if we have more to play.

Originally committed to SVN as r2806.
2009-04-16 20:55:14 +00:00
Amar Takhar 0d7af5f333 * Remove variable 'avail'.
* Fold lenAvailable logic into a ternary operator.
* Use GetAduioWithVolume instead of applying volume ourselves.
* Remove code used to zero rest of the buffer. (not required)

Originally committed to SVN as r2805.
2009-04-16 20:49:37 +00:00
Amar Takhar 89fa60082e * Set Pa_OpenStream to use paClipOff as we don't need any clipping
* Update comment (realPlayPos has been removed).
* Return from paCallback with paAbort if there is no more audio to play.
  Also set endPos to be less than the current playPos to stop the audio
  event timer.
* Add CPU usage statistics to debug printf in paCallback.

Originally committed to SVN as r2804.
2009-04-16 19:55:52 +00:00
Amar Takhar eebde56363 Make debug printf's a perm fixture wrapped with PORTAUDIO2_DEBUG.
Originally committed to SVN as r2803.
2009-04-16 14:22:46 +00:00
Niels Martin Hansen bcc8cede88 Forgot to put license on VideoSink.h as well.
Originally committed to SVN as r2802.
2009-04-16 13:01:05 +00:00
Niels Martin Hansen 103c407a64 Clarify license for VideoSink.cpp.
<jfs> hmm Haali, the VideoSink.cpp you have contributed to aegisub doesn't have a license attached... I see you put MatroskaParser.c into 3-clause BSD like the rest of aegisub though, what about VideoSink ?
<Haali> jfs: BSD license is ok for that file

Originally committed to SVN as r2801.
2009-04-16 12:15:57 +00:00
Amar Takhar fd16c4ff13 Move the comment for the PortAudio library to setup.cpp.
Requested by: TheFluff

Originally committed to SVN as r2800.
2009-04-15 20:16:54 +00:00
Amar Takhar d689a486c0 Don't initalise favorite to 0 (it's a a wxString).
Originally committed to SVN as r2799.
2009-04-15 20:11:53 +00:00
Amar Takhar 96a33b1331 Don't set the current position via the PortAudio callback, instead set
GetCurrentPosition() to return the correct value using Pa_GetStreamTime().  Not
only does it not work on every platform, there is no point in setting it during
the callback as GetCurrentPosition() isn't called very often (in comparison)
when updating the play bar.  Eventually this should be changed to update the
playbar via a callback to get a position that's a lot more accurate.

Originally committed to SVN as r2798.
2009-04-15 17:50:16 +00:00
Amar Takhar 218c9877ac Add hidden option 'Audio PortAudio Device' to set the default portaudio output device.
Originally committed to SVN as r2797.
2009-04-15 11:26:43 +00:00
Amar Takhar af84de21ab * Fix paCallback decleration
* Switch from PaOpenDefaultStream to Pa_OpenStream.
* Add Debug output
* Add GetOutputDevices which returns a list of available devices (unused)

Originally committed to SVN as r2796.
2009-04-15 10:26:22 +00:00
Niels Martin Hansen 50679014ea Make the default ALSA device default.
(It should be "default", not "default:0" as the old default was.)

Originally committed to SVN as r2795.
2009-04-13 17:08:13 +00:00
Amar Takhar e6a09d383c Move FOUND_AUDIO_PLAYER above the rest of the audio players to preserve
link ordering.  Also add libaudio_player.a to the final link.

Originally committed to SVN as r2794.
2009-04-12 10:52:40 +00:00
Amar Takhar 41034545e7 Early morning code-o, setting AM_CONDITIONAL _after_ the Makefiles are
generated isn't going to work very well.

Originally committed to SVN as r2793.
2009-04-12 10:48:20 +00:00
Amar Takhar 55afc7c29a * Update comment
* Include audio_player_portaudio2.h instead of audio_player_portaudio.h.

Originally committed to SVN as r2792.
2009-04-12 10:30:38 +00:00
Amar Takhar fb4d7e67e2 Split audio_player.cpp into it's own convenience to avoid sending audio library
CFLAGS to every source file.

Originally committed to SVN as r2791.
2009-04-12 10:30:07 +00:00
Amar Takhar 11c341030b Add support for ALSA_(LD|C)FLAGS.
Originally committed to SVN as r2790.
2009-04-12 10:28:42 +00:00
Amar Takhar f6d8cca7aa Add block for WITH_PORTAUDIO2.
Originally committed to SVN as r2789.
2009-04-12 10:08:59 +00:00
Amar Takhar 72bfc9862a * s/$found_audio/$found_audio_player/ for clarity.
* Add AM_CONDITIONAL for FOUND_AUDIO_PLAYER and FOUND_VIDEO_PROVIDER.

Originally committed to SVN as r2788.
2009-04-12 10:08:28 +00:00
Amar Takhar c674034054 Update PortAudio v19 support.
Originally committed to SVN as r2787.
2009-04-12 10:04:10 +00:00
Amar Takhar 2c3e71b098 Move the PortAudio v19 check above the v18 check.
Originally committed to SVN as r2786.
2009-04-11 23:40:15 +00:00
Amar Takhar 7ecdd1035a Add 'PortAudio2' as an audio player.
Originally committed to SVN as r2785.
2009-04-11 23:23:30 +00:00
Amar Takhar ebdeeec267 Change WITH_PORTAUDIO -> WITH_PORTAUDIO2
Originally committed to SVN as r2784.
2009-04-11 23:18:04 +00:00
Amar Takhar 907484a602 Update audio_player_portaudio2.* for PortAudio v19.
Originally committed to SVN as r2783.
2009-04-11 23:16:58 +00:00
Amar Takhar c12f35f9c6 Verbatium copy of audio_player_portaudio.* -> audio_player_portaudio2.*
Originally committed to SVN as r2782.
2009-04-11 23:15:45 +00:00
Fredrik Mellbin 6ca864b88c FFMS2 GCC compilation fix
Originally committed to SVN as r2781.
2009-04-11 19:43:18 +00:00
Fredrik Mellbin cae545b1eb FFMS2 beta 6 (the real commit)
Requires a recent FFmpeg
Changes the HAALITS define into HAALISOURCE

Originally committed to SVN as r2780.
2009-04-11 18:45:40 +00:00
Amar Takhar 8631bd42e1 * Fix check for libavutil/pixfmt.h
* Add detection for PortAudio2 (v19)

Originally committed to SVN as r2779.
2009-04-11 18:06:23 +00:00
Amar Takhar bf5146f937 Add a check for libavutil/pixfmt.h as a low-brow check for FFMPEG r18129+, this
needs to be fixed to check exact versions of the library.  For now this should
work.

Originally committed to SVN as r2778.
2009-04-11 08:13:09 +00:00
Amar Takhar 77a4983219 Fix an error message to be clearer.
Originally committed to SVN as r2777.
2009-04-11 07:51:50 +00:00
Amar Takhar 00339fefd0 Update libass to r29169 of MPlayer.
Originally committed to SVN as r2776.
2009-04-11 07:42:48 +00:00
Karl Blomster ff1a4fb8fc Add a -v option to ffmsindex.
Originally committed to SVN as r2775.
2009-04-07 01:12:12 +00:00
Karl Blomster eed309f187 Fix ffms2 video provider to work with new ffms2 version (b6)
Originally committed to SVN as r2774.
2009-04-06 20:53:01 +00:00
Karl Blomster f80421d2e6 Updated ffms2.lib
Originally committed to SVN as r2773.
2009-04-06 20:19:33 +00:00
Karl Blomster ac2c8bbed6 FFMS2 compile fix for ffmpeg revisions >18129. Probably breaks backwards compatibility so it doesn't compile with older revisions anymore, have fun.
Originally committed to SVN as r2772.
2009-04-06 20:15:49 +00:00
Karl Blomster 72cc224f5b Rename a few internal utility functions (FloatToString, IntegerToString, StringToInt, StringToFix) to Aegi* so they do not conflict with identically named wxWidgets functions. Fixes bugtracker issue #819.
Originally committed to SVN as r2771.
2009-04-06 20:01:42 +00:00
Karl Blomster 6bb861c7ef FFmpegSource2 beta 6, see ffms2.html for change details
Originally committed to SVN as r2770.
2009-04-06 19:14:55 +00:00
Karl Blomster 546f41e1a3 Add new (VSFilter 2.39) override tags to call tips and fix a typo. Patch by Harukalover.
Originally committed to SVN as r2769.
2009-03-30 22:10:24 +00:00
Karl Blomster 89c465dc71 FFmpegSource2 beta 5.
Fixes a bug with timecode writing, adds some additional documentation and resolves the issue with reading ffmsindex's progress reporting from another program.

Originally committed to SVN as r2768.
2009-03-30 22:09:33 +00:00
Rodrigo Braz Monteiro 261d9c21f1 Fixed windows project.
Originally committed to SVN as r2766.
2009-03-14 20:52:01 +00:00
Amar Takhar c6e55826f5 * Add a (small) hack for scripts/osx-bundle.sh to handle libtools weirdness.
* Update path to reflect new repo changes.

Originally committed to SVN as r2765.
2009-03-13 04:27:24 +00:00
Amar Takhar 67af0c3661 Fix auto3 build after repo change.
Originally committed to SVN as r2764.
2009-03-13 04:13:11 +00:00
Amar Takhar 6f090f9027 Fix libass on OSX after the repo changes.
Originally committed to SVN as r2763.
2009-03-13 04:12:45 +00:00
Amar Takhar 4c02eb0984 Fix vs2008 build (Patch from Haruka)
Originally committed to SVN as r2762.
2009-03-12 05:56:02 +00:00
Amar Takhar 514624f83a Sync libass with r28935 from MPlayer.
Originally committed to SVN as r2761.
2009-03-12 03:46:44 +00:00
Amar Takhar 908e9381e8 Missed patch: Fix build for auto3 it moved from ./auto3 -> src/libauto3.
Originally committed to SVN as r2760.
2009-03-09 05:48:13 +00:00
Amar Takhar 3df8846bcb Remove dummy.txt it was used ages ago for testing the svn repository.
Originally committed to SVN as r2759.
2009-03-09 01:15:01 +00:00
Amar Takhar d7e023e57f Update the build system for the new repository layout.
Originally committed to SVN as r2757.
2009-03-09 00:58:38 +00:00
Amar Takhar 27cdb7d7a4 SVN Transition Step 7/7
1. svn mv specs art-sources docs

* See r2749 for full description.

Originally committed to SVN as r2756.
2009-03-08 08:32:10 +00:00
Amar Takhar aa506bfe40 SVN Transition Step 6/7
1. svn mv OverLua SSATool athenasub avisynth_prs kanamemo \
     motiontracker prs traydict unit_test vsfilter devel/

* See r2749 for full description.

Originally committed to SVN as r2755.
2009-03-08 08:31:54 +00:00
Amar Takhar b8d6be1ee3 SVN Transition Step 5/7
1. svn mv assdraw csri hunspell lua51 contrib

* See r2749 for full description.

Originally committed to SVN as r2754.
2009-03-08 08:31:41 +00:00
Amar Takhar 0df92fa359 SVN Transition Step 4/7
1. svn mv auto3 aegisub/src/libauto3
   1. svn mv installer aegisub/packages/win_installer

* See r2749 for full description.

Originally committed to SVN as r2753.
2009-03-08 08:31:28 +00:00
Amar Takhar a067bd560d SVN Transition Step 3/7
1. cd aegisub/
  2. svn mv *cpp *h src/
  3. svn mv Makefile.am MatroskaParser.c auto4_perldata.inc bitmaps boost \
     changelog.txt config gl include libosxutil libresrc md5.c msvc mythes.cxx \
     mythes.hxx res.rc src/
  4. cd ..
  5. svn mv FFmpegSource2/ INSTALL Makefile.am README  acinclude.m4 \
     autogen.sh automation/ bin build configure.in desktop dummy.txt lib \
     libass/ m4macros/ packages/ po/ scripts/ universalchardet/ aegisub/
  6. mkdir -p docs/wiki_convert
  7. svn add docs/wiki_convert
  8. cd docs
  9. svn mv aegisub_convert_docs.pl convert.bat output wiki_convert/

* See r2749 for full description.

Originally committed to SVN as r2752.
2009-03-08 08:30:39 +00:00
Amar Takhar 563dc4689e SVN Transition Step 2/7
1. svn mv auto3/lua contrib/lua50

* See r2749 for full description.

Originally committed to SVN as r2751.
2009-03-08 08:20:07 +00:00
Niels Martin Hansen 5e476ca821 Updated cleantags script from ai-chan.
Originally committed to SVN as r2748.
2009-02-28 17:52:06 +00:00
Amar Takhar ae9a23d848 Move *all* AC_SUBST* out of any conditional blocks, also set them below
AM_CONDITIONAL where applicable.

Originally committed to SVN as r2747.
2009-02-22 22:04:21 +00:00
Amar Takhar 10a531b684 * Rework the debugging flags to set the variables conditionally on either being
enabled.
* Fix some cut-and-paste-o's (dunno how I managed these)
* Move AC_SUBST* outside of the conditionally enabled blocks
* Fix typo.

Originally committed to SVN as r2746.
2009-02-22 22:01:14 +00:00
Amar Takhar eac9424b2a Add --enable-gcov, --enable-efence and --enable-ccmalloc for gcov, Electric
Fence and ccmalloc support.  gcov support won't work without manual
intervention (for now) but some hooks will be added later to automate it.

Originally committed to SVN as r2745.
2009-02-22 05:38:46 +00:00
Amar Takhar 9df096a660 Updates from greg:
* Scale shadow displacement and blur size like border
  * Correctly re-initialize glyph_info_t.
  * When using pan-and-scan, use correct positions.
  * patch cleanups

Originally committed to SVN as r2744.
2009-02-22 05:17:47 +00:00
Amar Takhar 68a9d536cb Return NULL if n < 0 on line 886, for whatever reason on FreeBSD this falls
through exception handling and causes and abort().

Originally committed to SVN as r2743.
2009-02-19 23:58:06 +00:00
Niels Martin Hansen c2f3b95fa3 New Russian translation, thanks to z0rc.
Originally committed to SVN as r2742.
2009-02-18 20:05:29 +00:00
Amar Takhar c4d4e6db98 Use $DICT_DIR to find diciontary files for copying inside the bundle.
The default is ~/dict.

Originally committed to SVN as r2741.
2009-02-18 06:00:17 +00:00
Amar Takhar e7d5448885 Only enable -D_DEBUG if there is a debug version of wxWidgets installed.
Originally committed to SVN as r2740.
2009-02-17 09:08:27 +00:00
Amar Takhar ae6541cde4 Add audio_provider_dummy.cpp to the build which is required when _DEBUG is used.
Originally committed to SVN as r2739.
2009-02-17 08:12:19 +00:00
Amar Takhar 5be76ad6ac On OS X affix -debug to the bundle name when --enable-debug is used.
Originally committed to SVN as r2738.
2009-02-17 06:37:39 +00:00
Amar Takhar e792da082c Add -D_DEBUG when --enable-debug is used, this can't be turned off as
anyone making a debug build should use any features to help out with
debugging.

Originally committed to SVN as r2737.
2009-02-17 02:27:31 +00:00
Amar Takhar 8fab7c9ddc Substitute the FontConfig Cache dir in fonts.conf to use the proper (versioned)
path: ~/Library/Application Data/Aegisub-<AEGISUB_VERSION_DATA>

Originally committed to SVN as r2736.
2009-02-16 01:57:19 +00:00
Amar Takhar ea31698587 Add missing files from aegisub/libosxutil/, packages/, and scripts/.
All of the missing files were related to OS X.

Originally committed to SVN as r2735.
2009-02-16 00:27:52 +00:00
Amar Takhar 83bf4c7512 Apply a fix from greg:
* 'Correctly' handle font aspect ratio in the case of PlayRes(X|Y) not matching
   the video aspect ratio. (to match vsfilter)

Originally committed to SVN as r2734.
2009-02-15 05:44:06 +00:00
Amar Takhar cf936f5e12 Add changes from
http://greg.geekmind.org/mplayer/libass-snapshot-20090214.tar.gz

* \be filter with [1,2,1] kernel (like vsfilter)
* "decimal point" support, e.g. numbers with fractional parts are dealt with
  correctly
* shadow without border
* "compromise" fix for transparency + aa
* misc fixes: \be and \blur radius and a memory leak
* proper compositing of overlapping translucent outlines

Originally committed to SVN as r2733.
2009-02-14 19:19:35 +00:00
Amar Takhar b10f0503ba Add -pipe for C/C++.
Originally committed to SVN as r2732.
2009-02-14 19:08:44 +00:00
Amar Takhar ef269acdd3 Really disable -O2 when --enable-debug is used.
Originally committed to SVN as r2731.
2009-02-14 19:05:40 +00:00
Amar Takhar acea1a7e35 Add some more comments for clarity.
Originally committed to SVN as r2730.
2009-02-12 00:39:53 +00:00
Amar Takhar 93c073cbc6 Disable -O2 when --enable-debug is used, it can/does do odd things.
Originally committed to SVN as r2729.
2009-02-11 16:50:16 +00:00
Amar Takhar fa6831c1b0 Add a few comments for clarity.
Originally committed to SVN as r2728.
2009-02-10 21:25:32 +00:00
Amar Takhar fce6a3716a Add a new flag: --disable-compiler-flags which disables *all* default
compiler flags.

Originally committed to SVN as r2727.
2009-02-10 20:50:28 +00:00
Niels Martin Hansen 342ab23e88 Oops, had a C++-style line comment in a C source file
Originally committed to SVN as r2726.
2009-02-09 18:10:16 +00:00
Niels Martin Hansen fe2e4ba1e4 Updated version of stdint.h for MSVC
Originally committed to SVN as r2725.
2009-02-09 18:08:14 +00:00
http://greg.geekmind.org/mplayer/mplayer-libass-fixes.txt 8cb2492a02 Impliment changes from http://greg.geekmind.org/mplayer/mplayer-libass-fixes.patch
from: http://greg.geekmind.org/mplayer/mplayer-libass-fixes.txt
 * adds stubs for most features introduced in vsfilter 2.39
 * implements \blur and \be > 1
 * corrects fix_outline_and_shadow for transparency + aa
 * first-tag-wins for \pos and \move

Originally committed to SVN as r2724.
2009-02-06 05:58:22 +00:00
1987 changed files with 140269 additions and 88279 deletions

View File

@ -1,32 +0,0 @@
noinst_LIBRARIES = libffmpegsource2_aegisub.a
AM_CPPFLAGS = -I../aegisub -D__UNIX__ -DHAVE_STRLCPY @LIBAVFORMAT_CFLAGS@ @LIBAVCODEC_CFLAGS@ @LIBSWSCALE_CFLAGS@ @LIBAVUTIL_CFLAGS@ @LIBPOSTPROC_CFLAGS@
libffmpegsource2_aegisub_a_SOURCES = \
ffaudiosource.cpp \
ffms.cpp \
ffvideosource.cpp \
indexing.cpp \
MatroskaParser.c \
stdiostream.c \
utils.cpp \
wave64writer.cpp
libffmpegsource2_aegisub_a_SOURCES += \
MatroskaParser.h \
avisynth.h \
ffaudiosource.h \
ffavisynth.h \
ffms.h \
ffpp.h \
ffswscale.h \
ffvideosource.h \
indexing.h \
stdiostream.h \
utils.h \
wave64writer.h
EXTRA_DIST = \
ffms2.html

View File

@ -1,749 +0,0 @@
// Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al.
// http://www.avisynth.org
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
// http://www.gnu.org/copyleft/gpl.html .
//
// Linking Avisynth statically or dynamically with other modules is making a
// combined work based on Avisynth. Thus, the terms and conditions of the GNU
// General Public License cover the whole combination.
//
// As a special exception, the copyright holders of Avisynth give you
// permission to link Avisynth with independent modules that communicate with
// Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
// terms of these independent modules, and to copy and distribute the
// resulting combined work under terms of your choice, provided that
// every copy of the combined work is accompanied by a complete copy of
// the source code of Avisynth (the version of Avisynth used to produce the
// combined work), being distributed under the terms of the GNU General
// Public License plus this exception. An independent module is a module
// which is not derived from or based on Avisynth, such as 3rd-party filters,
// import and export plugins, or graphical user interfaces.
#ifndef __AVISYNTH_H__
#define __AVISYNTH_H__
enum { AVISYNTH_INTERFACE_VERSION = 3 };
/* Define all types necessary for interfacing with avisynth.dll
Moved from internal.h */
// Win32 API macros, notably the types BYTE, DWORD, ULONG, etc.
#include <windef.h>
// COM interface macros
#include <objbase.h>
// Raster types used by VirtualDub & Avisynth
#define in64 (__int64)(unsigned short)
typedef unsigned long Pixel; // this will break on 64-bit machines!
typedef unsigned long Pixel32;
typedef unsigned char Pixel8;
typedef long PixCoord;
typedef long PixDim;
typedef long PixOffset;
/* Compiler-specific crap */
// Tell MSVC to stop precompiling here
#ifdef _MSC_VER
#pragma hdrstop
#endif
// Set up debugging macros for MS compilers; for others, step down to the
// standard <assert.h> interface
#ifdef _MSC_VER
#include <crtdbg.h>
#else
#define _RPT0(a,b) ((void)0)
#define _RPT1(a,b,c) ((void)0)
#define _RPT2(a,b,c,d) ((void)0)
#define _RPT3(a,b,c,d,e) ((void)0)
#define _RPT4(a,b,c,d,e,f) ((void)0)
#define _ASSERTE(x) assert(x)
#include <assert.h>
#endif
// I had problems with Premiere wanting 1-byte alignment for its structures,
// so I now set the Avisynth struct alignment explicitly here.
#pragma pack(push,8)
#define FRAME_ALIGN 16
// Default frame alignment is 16 bytes, to help P4, when using SSE2
// The VideoInfo struct holds global information about a clip (i.e.
// information that does not depend on the frame number). The GetVideoInfo
// method in IClip returns this struct.
// Audio Sample information
typedef float SFLOAT;
enum {SAMPLE_INT8 = 1<<0,
SAMPLE_INT16 = 1<<1,
SAMPLE_INT24 = 1<<2, // Int24 is a very stupid thing to code, but it's supported by some hardware.
SAMPLE_INT32 = 1<<3,
SAMPLE_FLOAT = 1<<4};
enum {
PLANAR_Y=1<<0,
PLANAR_U=1<<1,
PLANAR_V=1<<2,
PLANAR_ALIGNED=1<<3,
PLANAR_Y_ALIGNED=PLANAR_Y|PLANAR_ALIGNED,
PLANAR_U_ALIGNED=PLANAR_U|PLANAR_ALIGNED,
PLANAR_V_ALIGNED=PLANAR_V|PLANAR_ALIGNED,
};
struct VideoInfo {
int width, height; // width=0 means no video
unsigned fps_numerator, fps_denominator;
int num_frames;
// This is more extensible than previous versions. More properties can be added seeminglesly.
// Colorspace properties.
enum {
CS_BGR = 1<<28,
CS_YUV = 1<<29,
CS_INTERLEAVED = 1<<30,
CS_PLANAR = 1<<31
};
// Specific colorformats
enum { CS_UNKNOWN = 0,
CS_BGR24 = 1<<0 | CS_BGR | CS_INTERLEAVED,
CS_BGR32 = 1<<1 | CS_BGR | CS_INTERLEAVED,
CS_YUY2 = 1<<2 | CS_YUV | CS_INTERLEAVED,
CS_YV12 = 1<<3 | CS_YUV | CS_PLANAR, // y-v-u, planar
CS_I420 = 1<<4 | CS_YUV | CS_PLANAR, // y-u-v, planar
CS_IYUV = 1<<4 | CS_YUV | CS_PLANAR // same as above
};
int pixel_type; // changed to int as of 2.5
int audio_samples_per_second; // 0 means no audio
int sample_type; // as of 2.5
__int64 num_audio_samples; // changed as of 2.5
int nchannels; // as of 2.5
// Imagetype properties
int image_type;
enum {
IT_BFF = 1<<0,
IT_TFF = 1<<1,
IT_FIELDBASED = 1<<2
};
// useful functions of the above
bool HasVideo() const { return (width!=0); }
bool HasAudio() const { return (audio_samples_per_second!=0); }
bool IsRGB() const { return !!(pixel_type&CS_BGR); }
bool IsRGB24() const { return (pixel_type&CS_BGR24)==CS_BGR24; } // Clear out additional properties
bool IsRGB32() const { return (pixel_type & CS_BGR32) == CS_BGR32 ; }
bool IsYUV() const { return !!(pixel_type&CS_YUV ); }
bool IsYUY2() const { return (pixel_type & CS_YUY2) == CS_YUY2; }
bool IsYV12() const { return ((pixel_type & CS_YV12) == CS_YV12)||((pixel_type & CS_I420) == CS_I420); }
bool IsColorSpace(int c_space) const { return ((pixel_type & c_space) == c_space); }
bool Is(int property) const { return ((pixel_type & property)==property ); }
bool IsPlanar() const { return !!(pixel_type & CS_PLANAR); }
bool IsFieldBased() const { return !!(image_type & IT_FIELDBASED); }
bool IsParityKnown() const { return ((image_type & IT_FIELDBASED)&&(image_type & (IT_BFF|IT_TFF))); }
bool IsBFF() const { return !!(image_type & IT_BFF); }
bool IsTFF() const { return !!(image_type & IT_TFF); }
bool IsVPlaneFirst() const {return ((pixel_type & CS_YV12) == CS_YV12); } // Don't use this
int BytesFromPixels(int pixels) const { return pixels * (BitsPerPixel()>>3); } // Will not work on planar images, but will return only luma planes
int RowSize() const { return BytesFromPixels(width); } // Also only returns first plane on planar images
int BMPSize() const { if (IsPlanar()) {int p = height * ((RowSize()+3) & ~3); p+=p>>1; return p; } return height * ((RowSize()+3) & ~3); }
__int64 AudioSamplesFromFrames(__int64 frames) const { return (fps_numerator && HasVideo()) ? ((__int64)(frames) * audio_samples_per_second * fps_denominator / fps_numerator) : 0; }
int FramesFromAudioSamples(__int64 samples) const { return (fps_denominator && HasAudio()) ? (int)((samples * (__int64)fps_numerator)/((__int64)fps_denominator * (__int64)audio_samples_per_second)) : 0; }
__int64 AudioSamplesFromBytes(__int64 bytes) const { return HasAudio() ? bytes / BytesPerAudioSample() : 0; }
__int64 BytesFromAudioSamples(__int64 samples) const { return samples * BytesPerAudioSample(); }
int AudioChannels() const { return HasAudio() ? nchannels : 0; }
int SampleType() const{ return sample_type;}
bool IsSampleType(int testtype) const{ return !!(sample_type&testtype);}
int SamplesPerSecond() const { return audio_samples_per_second; }
int BytesPerAudioSample() const { return nchannels*BytesPerChannelSample();}
void SetFieldBased(bool isfieldbased) { if (isfieldbased) image_type|=IT_FIELDBASED; else image_type&=~IT_FIELDBASED; }
void Set(int property) { image_type|=property; }
void Clear(int property) { image_type&=~property; }
int BitsPerPixel() const {
switch (pixel_type) {
case CS_BGR24:
return 24;
case CS_BGR32:
return 32;
case CS_YUY2:
return 16;
case CS_YV12:
case CS_I420:
return 12;
default:
return 0;
}
}
int BytesPerChannelSample() const {
switch (sample_type) {
case SAMPLE_INT8:
return sizeof(signed char);
case SAMPLE_INT16:
return sizeof(signed short);
case SAMPLE_INT24:
return 3;
case SAMPLE_INT32:
return sizeof(signed int);
case SAMPLE_FLOAT:
return sizeof(SFLOAT);
default:
_ASSERTE("Sample type not recognized!");
return 0;
}
}
// useful mutator
void SetFPS(unsigned numerator, unsigned denominator) {
if ((numerator == 0) || (denominator == 0)) {
fps_numerator = 0;
fps_denominator = 1;
}
else {
unsigned x=numerator, y=denominator;
while (y) { // find gcd
unsigned t = x%y; x = y; y = t;
}
fps_numerator = numerator/x;
fps_denominator = denominator/x;
}
}
// Range protected multiply-divide of FPS
void MulDivFPS(unsigned multiplier, unsigned divisor) {
unsigned __int64 numerator = UInt32x32To64(fps_numerator, multiplier);
unsigned __int64 denominator = UInt32x32To64(fps_denominator, divisor);
unsigned __int64 x=numerator, y=denominator;
while (y) { // find gcd
unsigned __int64 t = x%y; x = y; y = t;
}
numerator /= x; // normalize
denominator /= x;
unsigned __int64 temp = numerator | denominator; // Just looking top bit
unsigned u = 0;
while (temp & 0xffffffff80000000) { // or perhaps > 16777216*2
temp = Int64ShrlMod32(temp, 1);
u++;
}
if (u) { // Scale to fit
const unsigned round = 1 << (u-1);
SetFPS( (unsigned)Int64ShrlMod32(numerator + round, u),
(unsigned)Int64ShrlMod32(denominator + round, u) );
}
else {
fps_numerator = (unsigned)numerator;
fps_denominator = (unsigned)denominator;
}
}
// Test for same colorspace
bool IsSameColorspace(const VideoInfo& vi) const {
if (vi.pixel_type == pixel_type) return TRUE;
if (IsYV12() && vi.IsYV12()) return TRUE;
return FALSE;
}
};
// VideoFrameBuffer holds information about a memory block which is used
// for video data. For efficiency, instances of this class are not deleted
// when the refcount reaches zero; instead they're stored in a linked list
// to be reused. The instances are deleted when the corresponding AVS
// file is closed.
class VideoFrameBuffer {
BYTE* const data;
const int data_size;
// sequence_number is incremented every time the buffer is changed, so
// that stale views can tell they're no longer valid.
long sequence_number;
friend class VideoFrame;
friend class Cache;
friend class ScriptEnvironment;
long refcount;
public:
VideoFrameBuffer(int size);
VideoFrameBuffer();
~VideoFrameBuffer();
const BYTE* GetReadPtr() const { return data; }
BYTE* GetWritePtr() { ++sequence_number; return data; }
int GetDataSize() { return data_size; }
int GetSequenceNumber() { return sequence_number; }
int GetRefcount() { return refcount; }
};
class IClip;
class PClip;
class PVideoFrame;
class IScriptEnvironment;
class AVSValue;
// VideoFrame holds a "window" into a VideoFrameBuffer. Operator new
// is overloaded to recycle class instances.
class VideoFrame {
int refcount;
VideoFrameBuffer* const vfb;
const int offset, pitch, row_size, height, offsetU, offsetV, pitchUV; // U&V offsets are from top of picture.
friend class PVideoFrame;
void AddRef() { InterlockedIncrement((long *)&refcount); }
void Release() { if (refcount==1) InterlockedDecrement(&vfb->refcount); InterlockedDecrement((long *)&refcount); }
friend class ScriptEnvironment;
friend class Cache;
VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height);
VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height, int _offsetU, int _offsetV, int _pitchUV);
void* operator new(unsigned size);
// TESTME: OFFSET U/V may be switched to what could be expected from AVI standard!
public:
int GetPitch() const { return pitch; }
int GetPitch(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: return pitchUV;} return pitch; }
int GetRowSize() const { return row_size; }
int GetRowSize(int plane) const {
switch (plane) {
case PLANAR_U: case PLANAR_V: if (pitchUV) return row_size>>1; else return 0;
case PLANAR_U_ALIGNED: case PLANAR_V_ALIGNED:
if (pitchUV) {
int r = ((row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)) )>>1; // Aligned rowsize
if (r<=pitchUV)
return r;
return row_size>>1;
} else return 0;
case PLANAR_Y_ALIGNED:
int r = (row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)); // Aligned rowsize
if (r<=pitch)
return r;
return row_size;
}
return row_size; }
int GetHeight() const { return height; }
int GetHeight(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: if (pitchUV) return height>>1; return 0;} return height; }
// generally you shouldn't use these three
VideoFrameBuffer* GetFrameBuffer() const { return vfb; }
int GetOffset() const { return offset; }
int GetOffset(int plane) const { switch (plane) {case PLANAR_U: return offsetU;case PLANAR_V: return offsetV;default: return offset;}; }
// in plugins use env->SubFrame()
VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height) const;
VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int pitchUV) const;
const BYTE* GetReadPtr() const { return vfb->GetReadPtr() + offset; }
const BYTE* GetReadPtr(int plane) const { return vfb->GetReadPtr() + GetOffset(plane); }
bool IsWritable() const { return (refcount == 1 && vfb->refcount == 1); }
BYTE* GetWritePtr() const {
if (vfb->GetRefcount()>1) {
_ASSERT(FALSE);
//throw AvisynthError("Internal Error - refcount was more than one!");
}
return IsWritable() ? (vfb->GetWritePtr() + offset) : 0;
}
BYTE* GetWritePtr(int plane) const {
if (plane==PLANAR_Y) {
if (vfb->GetRefcount()>1) {
_ASSERT(FALSE);
// throw AvisynthError("Internal Error - refcount was more than one!");
}
return IsWritable() ? vfb->GetWritePtr() + GetOffset(plane) : 0;
}
return vfb->data + GetOffset(plane);
}
~VideoFrame() { InterlockedDecrement(&vfb->refcount); }
};
enum {
CACHE_NOTHING=0,
CACHE_RANGE=1,
CACHE_ALL=2,
CACHE_AUDIO=3,
CACHE_AUDIO_NONE=4
};
// Base class for all filters.
class IClip {
friend class PClip;
friend class AVSValue;
int refcnt;
void AddRef() { InterlockedIncrement((long *)&refcnt); }
void Release() { InterlockedDecrement((long *)&refcnt); if (!refcnt) delete this; }
public:
IClip() : refcnt(0) {}
virtual int __stdcall GetVersion() { return AVISYNTH_INTERFACE_VERSION; }
virtual PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) = 0;
virtual bool __stdcall GetParity(int n) = 0; // return field parity if field_based, else parity of first field in frame
virtual void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) = 0; // start and count are in samples
virtual void __stdcall SetCacheHints(int cachehints,int frame_range) = 0 ; // We do not pass cache requests upwards, only to the next filter.
virtual const VideoInfo& __stdcall GetVideoInfo() = 0;
virtual __stdcall ~IClip() {}
};
// smart pointer to IClip
class PClip {
IClip* p;
IClip* GetPointerWithAddRef() const { if (p) p->AddRef(); return p; }
friend class AVSValue;
friend class VideoFrame;
void Init(IClip* x) {
if (x) x->AddRef();
p=x;
}
void Set(IClip* x) {
if (x) x->AddRef();
if (p) p->Release();
p=x;
}
public:
PClip() { p = 0; }
PClip(const PClip& x) { Init(x.p); }
PClip(IClip* x) { Init(x); }
void operator=(IClip* x) { Set(x); }
void operator=(const PClip& x) { Set(x.p); }
IClip* operator->() const { return p; }
// useful in conditional expressions
operator void*() const { return p; }
bool operator!() const { return !p; }
~PClip() { if (p) p->Release(); }
};
// smart pointer to VideoFrame
class PVideoFrame {
VideoFrame* p;
void Init(VideoFrame* x) {
if (x) x->AddRef();
p=x;
}
void Set(VideoFrame* x) {
if (x) x->AddRef();
if (p) p->Release();
p=x;
}
public:
PVideoFrame() { p = 0; }
PVideoFrame(const PVideoFrame& x) { Init(x.p); }
PVideoFrame(VideoFrame* x) { Init(x); }
void operator=(VideoFrame* x) { Set(x); }
void operator=(const PVideoFrame& x) { Set(x.p); }
VideoFrame* operator->() const { return p; }
// for conditional expressions
operator void*() const { return p; }
bool operator!() const { return !p; }
~PVideoFrame() { if (p) p->Release();}
};
class AVSValue {
public:
AVSValue() { type = 'v'; }
AVSValue(IClip* c) { type = 'c'; clip = c; if (c) c->AddRef(); }
AVSValue(const PClip& c) { type = 'c'; clip = c.GetPointerWithAddRef(); }
AVSValue(bool b) { type = 'b'; boolean = b; }
AVSValue(int i) { type = 'i'; integer = i; }
// AVSValue(__int64 l) { type = 'l'; longlong = l; }
AVSValue(float f) { type = 'f'; floating_pt = f; }
AVSValue(double f) { type = 'f'; floating_pt = float(f); }
AVSValue(const char* s) { type = 's'; string = s; }
AVSValue(const AVSValue* a, int size) { type = 'a'; array = a; array_size = size; }
AVSValue(const AVSValue& v) { Assign(&v, true); }
~AVSValue() { if (IsClip() && clip) clip->Release(); }
AVSValue& operator=(const AVSValue& v) { Assign(&v, false); return *this; }
// Note that we transparently allow 'int' to be treated as 'float'.
// There are no int<->bool conversions, though.
bool Defined() const { return type != 'v'; }
bool IsClip() const { return type == 'c'; }
bool IsBool() const { return type == 'b'; }
bool IsInt() const { return type == 'i'; }
// bool IsLong() const { return (type == 'l'|| type == 'i'); }
bool IsFloat() const { return type == 'f' || type == 'i'; }
bool IsString() const { return type == 's'; }
bool IsArray() const { return type == 'a'; }
PClip AsClip() const { _ASSERTE(IsClip()); return IsClip()?clip:0; }
bool AsBool() const { _ASSERTE(IsBool()); return boolean; }
int AsInt() const { _ASSERTE(IsInt()); return integer; }
// int AsLong() const { _ASSERTE(IsLong()); return longlong; }
const char* AsString() const { _ASSERTE(IsString()); return IsString()?string:0; }
double AsFloat() const { _ASSERTE(IsFloat()); return IsInt()?integer:floating_pt; }
bool AsBool(bool def) const { _ASSERTE(IsBool()||!Defined()); return IsBool() ? boolean : def; }
int AsInt(int def) const { _ASSERTE(IsInt()||!Defined()); return IsInt() ? integer : def; }
double AsFloat(double def) const { _ASSERTE(IsFloat()||!Defined()); return IsInt() ? integer : type=='f' ? floating_pt : def; }
const char* AsString(const char* def) const { _ASSERTE(IsString()||!Defined()); return IsString() ? string : def; }
int ArraySize() const { _ASSERTE(IsArray()); return IsArray()?array_size:1; }
const AVSValue& operator[](int index) const {
_ASSERTE(IsArray() && index>=0 && index<array_size);
return (IsArray() && index>=0 && index<array_size) ? array[index] : *this;
}
private:
short type; // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, 'v'oid, or 'l'ong
short array_size;
union {
IClip* clip;
bool boolean;
int integer;
float floating_pt;
const char* string;
const AVSValue* array;
// __int64 longlong;
};
void Assign(const AVSValue* src, bool init) {
if (src->IsClip() && src->clip)
src->clip->AddRef();
if (!init && IsClip() && clip)
clip->Release();
// make sure this copies the whole struct!
((__int32*)this)[0] = ((__int32*)src)[0];
((__int32*)this)[1] = ((__int32*)src)[1];
}
};
// instantiable null filter
class GenericVideoFilter : public IClip {
protected:
PClip child;
VideoInfo vi;
public:
GenericVideoFilter(PClip _child) : child(_child) { vi = child->GetVideoInfo(); }
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) { return child->GetFrame(n, env); }
void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) { child->GetAudio(buf, start, count, env); }
const VideoInfo& __stdcall GetVideoInfo() { return vi; }
bool __stdcall GetParity(int n) { return child->GetParity(n); }
void __stdcall SetCacheHints(int cachehints,int frame_range) { } ; // We do not pass cache requests upwards, only to the next filter.
};
class AvisynthError /* exception */ {
public:
const char* const msg;
AvisynthError(const char* _msg) : msg(_msg) {}
};
/* Helper classes useful to plugin authors */
class AlignPlanar : public GenericVideoFilter
{
public:
AlignPlanar(PClip _clip);
static PClip Create(PClip clip);
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};
class FillBorder : public GenericVideoFilter
{
public:
FillBorder(PClip _clip);
static PClip Create(PClip clip);
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};
class ConvertAudio : public GenericVideoFilter
/**
* Helper class to convert audio to any format
**/
{
public:
ConvertAudio(PClip _clip, int prefered_format);
void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env);
void __stdcall SetCacheHints(int cachehints,int frame_range); // We do pass cache requests upwards, to the cache!
static PClip Create(PClip clip, int sample_type, int prefered_type);
static AVSValue __cdecl Create_float(AVSValue args, void*, IScriptEnvironment*);
static AVSValue __cdecl Create_32bit(AVSValue args, void*, IScriptEnvironment*);
static AVSValue __cdecl Create_24bit(AVSValue args, void*, IScriptEnvironment*);
static AVSValue __cdecl Create_16bit(AVSValue args, void*, IScriptEnvironment*);
static AVSValue __cdecl Create_8bit(AVSValue args, void*, IScriptEnvironment*);
virtual ~ConvertAudio();
private:
void convertToFloat(char* inbuf, float* outbuf, char sample_type, int count);
void convertToFloat_3DN(char* inbuf, float* outbuf, char sample_type, int count);
void convertToFloat_SSE(char* inbuf, float* outbuf, char sample_type, int count);
void convertToFloat_SSE2(char* inbuf, float* outbuf, char sample_type, int count);
void convertFromFloat(float* inbuf, void* outbuf, char sample_type, int count);
void convertFromFloat_3DN(float* inbuf, void* outbuf, char sample_type, int count);
void convertFromFloat_SSE(float* inbuf, void* outbuf, char sample_type, int count);
void convertFromFloat_SSE2(float* inbuf, void* outbuf, char sample_type, int count);
__inline int Saturate_int8(float n);
__inline short Saturate_int16(float n);
__inline int Saturate_int24(float n);
__inline int Saturate_int32(float n);
char src_format;
char dst_format;
int src_bps;
char *tempbuffer;
SFLOAT *floatbuffer;
int tempbuffer_size;
};
// For GetCPUFlags. These are backwards-compatible with those in VirtualDub.
enum {
/* slowest CPU to support extension */
CPUF_FORCE = 0x01, // N/A
CPUF_FPU = 0x02, // 386/486DX
CPUF_MMX = 0x04, // P55C, K6, PII
CPUF_INTEGER_SSE = 0x08, // PIII, Athlon
CPUF_SSE = 0x10, // PIII, Athlon XP/MP
CPUF_SSE2 = 0x20, // PIV, Hammer
CPUF_3DNOW = 0x40, // K6-2
CPUF_3DNOW_EXT = 0x80, // Athlon
CPUF_X86_64 = 0xA0, // Hammer (note: equiv. to 3DNow + SSE2, which only Hammer
// will have anyway)
CPUF_SSE3 = 0x100, // Some P4 & Athlon 64.
};
#define MAX_INT 0x7fffffff
#define MIN_INT -0x7fffffff
class IScriptEnvironment {
public:
virtual __stdcall ~IScriptEnvironment() {}
virtual /*static*/ long __stdcall GetCPUFlags() = 0;
virtual char* __stdcall SaveString(const char* s, int length = -1) = 0;
virtual char* __stdcall Sprintf(const char* fmt, ...) = 0;
// note: val is really a va_list; I hope everyone typedefs va_list to a pointer
virtual char* __stdcall VSprintf(const char* fmt, void* val) = 0;
__declspec(noreturn) virtual void __stdcall ThrowError(const char* fmt, ...) = 0;
class NotFound /*exception*/ {}; // thrown by Invoke and GetVar
typedef AVSValue (__cdecl *ApplyFunc)(AVSValue args, void* user_data, IScriptEnvironment* env);
virtual void __stdcall AddFunction(const char* name, const char* params, ApplyFunc apply, void* user_data) = 0;
virtual bool __stdcall FunctionExists(const char* name) = 0;
virtual AVSValue __stdcall Invoke(const char* name, const AVSValue args, const char** arg_names=0) = 0;
virtual AVSValue __stdcall GetVar(const char* name) = 0;
virtual bool __stdcall SetVar(const char* name, const AVSValue& val) = 0;
virtual bool __stdcall SetGlobalVar(const char* name, const AVSValue& val) = 0;
virtual void __stdcall PushContext(int level=0) = 0;
virtual void __stdcall PopContext() = 0;
// align should be 4 or 8
virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, int align=FRAME_ALIGN) = 0;
virtual bool __stdcall MakeWritable(PVideoFrame* pvf) = 0;
virtual /*static*/ void __stdcall BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height) = 0;
typedef void (__cdecl *ShutdownFunc)(void* user_data, IScriptEnvironment* env);
virtual void __stdcall AtExit(ShutdownFunc function, void* user_data) = 0;
virtual void __stdcall CheckVersion(int version = AVISYNTH_INTERFACE_VERSION) = 0;
virtual PVideoFrame __stdcall Subframe(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height) = 0;
virtual int __stdcall SetMemoryMax(int mem) = 0;
virtual int __stdcall SetWorkingDir(const char * newdir) = 0;
virtual void* __stdcall ManageCache(int key, void* data) = 0;
enum PlanarChromaAlignmentMode {
PlanarChromaAlignmentOff,
PlanarChromaAlignmentOn,
PlanarChromaAlignmentTest };
virtual bool __stdcall PlanarChromaAlignment(PlanarChromaAlignmentMode key) = 0;
virtual PVideoFrame __stdcall SubframePlanar(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV) = 0;
};
// avisynth.dll exports this; it's a way to use it as a library, without
// writing an AVS script or without going through AVIFile.
IScriptEnvironment* __stdcall CreateScriptEnvironment(int version = AVISYNTH_INTERFACE_VERSION);
#pragma pack(pop)
#endif //__AVISYNTH_H__

View File

@ -1,368 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "ffaudiosource.h"
#include <errno.h>
#ifdef __UNIX__
#define _snprintf snprintf
#endif
AudioBase::AudioBase() {
DecodingBuffer = new uint8_t[AVCODEC_MAX_AUDIO_FRAME_SIZE * 10];
};
AudioBase::~AudioBase() {
delete[] DecodingBuffer;
};
size_t AudioBase::FindClosestAudioKeyFrame(int64_t Sample) {
for (size_t i = 0; i < Frames.size(); i++) {
if (Frames[i].SampleStart == Sample && Frames[i].KeyFrame)
return i;
else if (Frames[i].SampleStart > Sample && Frames[i].KeyFrame)
return i - 1;
}
return Frames.size() - 1;
}
void FFAudioSource::Free(bool CloseCodec) {
if (CloseCodec)
avcodec_close(CodecContext);
av_close_input_file(FormatContext);
}
FFAudioSource::FFAudioSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize) {
FormatContext = NULL;
AVCodec *Codec = NULL;
AudioTrack = Track;
Frames = (*TrackIndices)[AudioTrack];
if (Frames.size() == 0) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Audio track contains no frames");
throw ErrorMsg;
}
if (av_open_input_file(&FormatContext, SourceFile, NULL, 0, NULL) != 0) {
_snprintf(ErrorMsg, MsgSize, "Couldn't open '%s'", SourceFile);
throw ErrorMsg;
}
if (av_find_stream_info(FormatContext) < 0) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Couldn't find stream information");
throw ErrorMsg;
}
CodecContext = FormatContext->streams[AudioTrack]->codec;
Codec = avcodec_find_decoder(CodecContext->codec_id);
if (Codec == NULL) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Audio codec not found");
throw ErrorMsg;
}
if (avcodec_open(CodecContext, Codec) < 0) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Could not open audio codec");
throw ErrorMsg;
}
// Always try to decode a frame to make sure all required parameters are known
uint8_t DummyBuf[512];
if (GetAudio(DummyBuf, 0, 1, ErrorMsg, MsgSize)) {
Free(true);
throw ErrorMsg;
}
AP.BitsPerSample = av_get_bits_per_sample_format(CodecContext->sample_fmt);
AP.Channels = CodecContext->channels;;
AP.Float = AudioFMTIsFloat(CodecContext->sample_fmt);
AP.SampleRate = CodecContext->sample_rate;
AP.NumSamples = (Frames.back()).SampleStart;
if (AP.SampleRate <= 0 || AP.BitsPerSample <= 0) {
Free(true);
_snprintf(ErrorMsg, MsgSize, "Codec returned zero size audio");
throw ErrorMsg;
}
}
int FFAudioSource::DecodeNextAudioBlock(uint8_t *Buf, int64_t *Count, char *ErrorMsg, unsigned MsgSize) {
const size_t SizeConst = (av_get_bits_per_sample_format(CodecContext->sample_fmt) * CodecContext->channels) / 8;
int Ret = -1;
*Count = 0;
AVPacket Packet;
while (av_read_frame(FormatContext, &Packet) >= 0) {
if (Packet.stream_index == AudioTrack) {
uint8_t *Data = Packet.data;
int Size = Packet.size;
while (Size > 0) {
int TempOutputBufSize = AVCODEC_MAX_AUDIO_FRAME_SIZE * 10;
Ret = avcodec_decode_audio2(CodecContext, (int16_t *)Buf, &TempOutputBufSize, Data, Size);
if (Ret < 0) {// throw error or something?
av_free_packet(&Packet);
goto Done;
}
if (Ret > 0) {
Size -= Ret;
Data += Ret;
Buf += TempOutputBufSize;
if (SizeConst)
*Count += TempOutputBufSize / SizeConst;
}
}
av_free_packet(&Packet);
goto Done;
}
av_free_packet(&Packet);
}
Done:
return Ret;
}
int FFAudioSource::GetAudio(void *Buf, int64_t Start, int64_t Count, char *ErrorMsg, unsigned MsgSize) {
const size_t SizeConst = (av_get_bits_per_sample_format(CodecContext->sample_fmt) * CodecContext->channels) / 8;
size_t CurrentAudioBlock = FFMAX((int64_t)FindClosestAudioKeyFrame(Start) - 50, (int64_t)0);
memset(Buf, 0, SizeConst * Count);
AVPacket Packet;
avcodec_flush_buffers(CodecContext);
av_seek_frame(FormatContext, AudioTrack, Frames[CurrentAudioBlock].DTS, AVSEEK_FLAG_BACKWARD);
// Establish where we actually are
// Trigger on packet dts difference since groups can otherwise be indistinguishable
int64_t LastDTS = - 1;
while (av_read_frame(FormatContext, &Packet) >= 0) {
if (Packet.stream_index == AudioTrack) {
if (LastDTS < 0) {
LastDTS = Packet.dts;
} else if (LastDTS != Packet.dts) {
for (size_t i = 0; i < Frames.size(); i++)
if (Frames[i].DTS == Packet.dts) {
// The current match was consumed
CurrentAudioBlock = i + 1;
break;
}
av_free_packet(&Packet);
break;
}
}
av_free_packet(&Packet);
}
uint8_t *DstBuf = (uint8_t *)Buf;
int64_t RemainingSamples = Count;
int64_t DecodeCount;
do {
int64_t DecodeStart = Frames[CurrentAudioBlock].SampleStart;
int Ret = DecodeNextAudioBlock(DecodingBuffer, &DecodeCount, ErrorMsg, MsgSize);
if (Ret < 0) {
// FIXME
//Env->ThrowError("Bleh, bad audio decoding");
}
CurrentAudioBlock++;
int64_t OffsetBytes = SizeConst * FFMAX(0, Start - DecodeStart);
int64_t CopyBytes = FFMAX(0, SizeConst * FFMIN(RemainingSamples, DecodeCount - FFMAX(0, Start - DecodeStart)));
memcpy(DstBuf, DecodingBuffer + OffsetBytes, CopyBytes);
DstBuf += CopyBytes;
if (SizeConst)
RemainingSamples -= CopyBytes / SizeConst;
} while (RemainingSamples > 0 && CurrentAudioBlock < Frames.size());
return 0;
}
FFAudioSource::~FFAudioSource() {
Free(true);
}
void MatroskaAudioSource::Free(bool CloseCodec) {
if (CS)
cs_Destroy(CS);
if (MC.ST.fp) {
mkv_Close(MF);
fclose(MC.ST.fp);
}
if (CloseCodec)
avcodec_close(CodecContext);
av_free(CodecContext);
}
MatroskaAudioSource::MatroskaAudioSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize) {
CodecContext = NULL;
AVCodec *Codec = NULL;
TrackInfo *TI = NULL;
CS = NULL;
Frames = (*TrackIndices)[Track];
if (Frames.size() == 0) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Audio track contains no frames");
throw ErrorMsg;
}
MC.ST.fp = fopen(SourceFile, "rb");
if (MC.ST.fp == NULL) {
_snprintf(ErrorMsg, MsgSize, "Can't open '%s': %s", SourceFile, strerror(errno));
throw ErrorMsg;
}
setvbuf(MC.ST.fp, NULL, _IOFBF, CACHESIZE);
MF = mkv_OpenEx(&MC.ST.base, 0, 0, ErrorMessage, sizeof(ErrorMessage));
if (MF == NULL) {
fclose(MC.ST.fp);
_snprintf(ErrorMsg, MsgSize, "Can't parse Matroska file: %s", ErrorMessage);
throw ErrorMsg;
}
mkv_SetTrackMask(MF, ~(1 << Track));
TI = mkv_GetTrackInfo(MF, Track);
if (TI->CompEnabled) {
CS = cs_Create(MF, Track, ErrorMessage, sizeof(ErrorMessage));
if (CS == NULL) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Can't create decompressor: %s", ErrorMessage);
throw ErrorMsg;
}
}
CodecContext = avcodec_alloc_context();
CodecContext->extradata = (uint8_t *)TI->CodecPrivate;
CodecContext->extradata_size = TI->CodecPrivateSize;
Codec = avcodec_find_decoder(MatroskaToFFCodecID(TI->CodecID, TI->CodecPrivate));
if (Codec == NULL) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Video codec not found");
throw ErrorMsg;
}
if (avcodec_open(CodecContext, Codec) < 0) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Could not open video codec");
throw ErrorMsg;
}
// Always try to decode a frame to make sure all required parameters are known
uint8_t DummyBuf[512];
if (GetAudio(DummyBuf, 0, 1, ErrorMsg, MsgSize)) {
Free(true);
throw ErrorMsg;
}
AP.BitsPerSample = av_get_bits_per_sample_format(CodecContext->sample_fmt);
AP.Channels = CodecContext->channels;;
AP.Float = AudioFMTIsFloat(CodecContext->sample_fmt);
AP.SampleRate = CodecContext->sample_rate;
AP.NumSamples = (Frames.back()).SampleStart;
if (AP.SampleRate <= 0 || AP.BitsPerSample <= 0) {
Free(true);
_snprintf(ErrorMsg, MsgSize, "Codec returned zero size audio");
throw ErrorMsg;
}
}
MatroskaAudioSource::~MatroskaAudioSource() {
Free(true);
}
int MatroskaAudioSource::GetAudio(void *Buf, int64_t Start, int64_t Count, char *ErrorMsg, unsigned MsgSize) {
const size_t SizeConst = (av_get_bits_per_sample_format(CodecContext->sample_fmt) * CodecContext->channels) / 8;
size_t CurrentAudioBlock = FFMAX((int64_t)FindClosestAudioKeyFrame(Start) - 10, (int64_t)0);
avcodec_flush_buffers(CodecContext);
memset(Buf, 0, SizeConst * Count);
uint8_t *DstBuf = (uint8_t *)Buf;
int64_t RemainingSamples = Count;
int64_t DecodeCount;
do {
int64_t DecodeStart = Frames[CurrentAudioBlock].SampleStart;
int Ret = DecodeNextAudioBlock(DecodingBuffer, &DecodeCount, Frames[CurrentAudioBlock].FilePos, Frames[CurrentAudioBlock].FrameSize, ErrorMsg, MsgSize);
if (Ret < 0) {
// FIXME
//Env->ThrowError("Bleh, bad audio decoding");
}
CurrentAudioBlock++;
int64_t OffsetBytes = SizeConst * FFMAX(0, Start - DecodeStart);
int64_t CopyBytes = FFMAX(0, SizeConst * FFMIN(RemainingSamples, DecodeCount - FFMAX(0, Start - DecodeStart)));
memcpy(DstBuf, DecodingBuffer + OffsetBytes, CopyBytes);
DstBuf += CopyBytes;
if (SizeConst)
RemainingSamples -= CopyBytes / SizeConst;
} while (RemainingSamples > 0 && CurrentAudioBlock < Frames.size());
return 0;
}
int MatroskaAudioSource::DecodeNextAudioBlock(uint8_t *Buf, int64_t *Count, uint64_t FilePos, unsigned int FrameSize, char *ErrorMsg, unsigned MsgSize) {
const size_t SizeConst = (av_get_bits_per_sample_format(CodecContext->sample_fmt) * CodecContext->channels) / 8;
int Ret = -1;
*Count = 0;
// FIXME check return
ReadFrame(FilePos, FrameSize, CS, MC, ErrorMsg, MsgSize);
int Size = FrameSize;
uint8_t *Data = MC.Buffer;
while (Size > 0) {
int TempOutputBufSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
Ret = avcodec_decode_audio2(CodecContext, (int16_t *)Buf, &TempOutputBufSize, Data, Size);
if (Ret < 0) // throw error or something?
goto Done;
if (Ret > 0) {
Size -= Ret;
Data += Ret;
Buf += TempOutputBufSize;
if (SizeConst)
*Count += TempOutputBufSize / SizeConst;
}
}
Done:
return Ret;
}

View File

@ -1,80 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFAUDIOSOURCE_H
#define FFAUDIOSOURCE_H
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
#include <vector>
#include "indexing.h"
#include "utils.h"
#include "ffms.h"
class AudioBase {
protected:
uint8_t *DecodingBuffer;
FrameInfoVector Frames;
AVCodecContext *CodecContext;
AudioProperties AP;
size_t FindClosestAudioKeyFrame(int64_t Sample);
public:
AudioBase();
~AudioBase();
const AudioProperties& GetAudioProperties() { return AP; }
virtual int GetAudio(void *Buf, int64_t Start, int64_t Count, char *ErrorMsg, unsigned MsgSize) = 0;
};
class FFAudioSource : public AudioBase {
private:
AVFormatContext *FormatContext;
int AudioTrack;
int DecodeNextAudioBlock(uint8_t *Buf, int64_t *Count, char *ErrorMsg, unsigned MsgSize);
void Free(bool CloseCodec);
public:
FFAudioSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize);
~FFAudioSource();
int GetAudio(void *Buf, int64_t Start, int64_t Count, char *ErrorMsg, unsigned MsgSize);
};
class MatroskaAudioSource : public AudioBase {
private:
MatroskaFile *MF;
MatroskaReaderContext MC;
CompressedStream *CS;
char ErrorMessage[256];
int DecodeNextAudioBlock(uint8_t *Buf, int64_t *Count, uint64_t FilePos, unsigned int FrameSize, char *ErrorMsg, unsigned MsgSize);
void Free(bool CloseCodec);
public:
MatroskaAudioSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize);
~MatroskaAudioSource();
int GetAudio(void *Buf, int64_t Start, int64_t Count, char *ErrorMsg, unsigned MsgSize);
};
#endif

View File

@ -1,190 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "ffavisynth.h"
#include "utils.h"
AvisynthVideoSource::AvisynthVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, int FPSNum, int FPSDen, const char *PP, int Threads, int SeekMode, IScriptEnvironment* Env, char *ErrorMsg, unsigned MsgSize) {
memset(&VI, 0, sizeof(VI));
SWS = NULL;
ConvertToFormat = PIX_FMT_NONE;
this->FPSNum = FPSNum;
this->FPSDen = FPSDen;
VS = FFMS_CreateVideoSource(SourceFile, Track, TrackIndices, PP, Threads, SeekMode, ErrorMsg, MsgSize);
if (!VS)
Env->ThrowError(ErrorMsg);
const VideoProperties VP = *FFMS_GetVideoProperties(VS);
VI.image_type = VideoInfo::IT_TFF;
VI.width = VP.Width;
VI.height = VP.Height;
if (FPSNum > 0 && FPSDen > 0) {
VI.fps_denominator = FPSDen;
VI.fps_numerator = FPSNum;
VI.num_frames = ceil(((VP.LastTime - VP.FirstTime) * FPSNum) / FPSDen);
} else {
VI.fps_denominator = VP.FPSDenominator;
VI.fps_numerator = VP.FPSNumerator;
VI.num_frames = VP.NumFrames;
}
try {
InitOutputFormat(VP.PixelFormat, Env);
} catch (AvisynthError &) {
FFMS_DestroyVideoSource(VS);
throw;
}
// Set AR variables
Env->SetVar("FFSAR_NUM", VP.SARNum);
Env->SetVar("FFSAR_DEN", VP.SARDen);
Env->SetVar("FFSAR", VP.SARNum / (double)VP.SARDen);
// Set crop variables
Env->SetVar("FFCROP_LEFT", VP.CropLeft);
Env->SetVar("FFCROP_RIGHT", VP.CropRight);
Env->SetVar("FFCROP_TOP", VP.CropTop);
Env->SetVar("FFCROP_BOTTOM", VP.CropBottom);
}
AvisynthVideoSource::~AvisynthVideoSource() {
if (SWS)
sws_freeContext(SWS);
FFMS_DestroyVideoSource(VS);
}
void AvisynthVideoSource::InitOutputFormat(int CurrentFormat, IScriptEnvironment *Env) {
int Loss;
int BestFormat = avcodec_find_best_pix_fmt((1 << PIX_FMT_YUVJ420P) | (1 << PIX_FMT_YUV420P) | (1 << PIX_FMT_YUYV422) | (1 << PIX_FMT_RGB32) | (1 << PIX_FMT_BGR24), CurrentFormat, 1 /* Required to prevent pointless RGB32 => RGB24 conversion */, &Loss);
switch (BestFormat) {
case PIX_FMT_YUVJ420P: // stupid yv12 distinctions, also inexplicably completely undeniably incompatible with all other supported output formats
case PIX_FMT_YUV420P: VI.pixel_type = VideoInfo::CS_I420; break;
case PIX_FMT_YUYV422: VI.pixel_type = VideoInfo::CS_YUY2; break;
case PIX_FMT_RGB32: VI.pixel_type = VideoInfo::CS_BGR32; break;
case PIX_FMT_BGR24: VI.pixel_type = VideoInfo::CS_BGR24; break;
default:
Env->ThrowError("FFVideoSource: No suitable output format found");
}
if (BestFormat != CurrentFormat) {
ConvertToFormat = BestFormat;
SWS = sws_getContext(VI.width, VI.height, CurrentFormat, VI.width, VI.height, ConvertToFormat, GetCPUFlags() | SWS_BICUBIC, NULL, NULL, NULL);
}
if (BestFormat == PIX_FMT_YUVJ420P || BestFormat == PIX_FMT_YUV420P) {
VI.height -= VI.height & 1;
VI.width -= VI.width & 1;
}
if (BestFormat == PIX_FMT_YUYV422) {
VI.width -= VI.width & 1;
}
}
PVideoFrame AvisynthVideoSource::OutputFrame(const AVFrameLite *Frame, IScriptEnvironment *Env) {
// Yes, this function is overly complex and could probably be simplified
AVPicture *SrcPicture = reinterpret_cast<AVPicture *>(const_cast<AVFrameLite *>(Frame));
PVideoFrame Dst = Env->NewVideoFrame(VI);
if (ConvertToFormat != PIX_FMT_NONE && VI.pixel_type == VideoInfo::CS_I420) {
uint8_t *DstData[3] = {Dst->GetWritePtr(PLANAR_Y), Dst->GetWritePtr(PLANAR_U), Dst->GetWritePtr(PLANAR_V)};
int DstStride[3] = {Dst->GetPitch(PLANAR_Y), Dst->GetPitch(PLANAR_U), Dst->GetPitch(PLANAR_V)};
sws_scale(SWS, SrcPicture->data, SrcPicture->linesize, 0, VI.height, DstData, DstStride);
} else if (ConvertToFormat != PIX_FMT_NONE) {
if (VI.IsRGB()) {
uint8_t *DstData[1] = {Dst->GetWritePtr() + Dst->GetPitch() * (Dst->GetHeight() - 1)};
int DstStride[1] = {-Dst->GetPitch()};
sws_scale(SWS, SrcPicture->data, SrcPicture->linesize, 0, VI.height, DstData, DstStride);
} else {
uint8_t *DstData[1] = {Dst->GetWritePtr()};
int DstStride[1] = {Dst->GetPitch()};
sws_scale(SWS, SrcPicture->data, SrcPicture->linesize, 0, VI.height, DstData, DstStride);
}
} else if (VI.pixel_type == VideoInfo::CS_I420) {
Env->BitBlt(Dst->GetWritePtr(PLANAR_Y), Dst->GetPitch(PLANAR_Y), SrcPicture->data[0], SrcPicture->linesize[0], Dst->GetRowSize(PLANAR_Y), Dst->GetHeight(PLANAR_Y));
Env->BitBlt(Dst->GetWritePtr(PLANAR_U), Dst->GetPitch(PLANAR_U), SrcPicture->data[1], SrcPicture->linesize[1], Dst->GetRowSize(PLANAR_U), Dst->GetHeight(PLANAR_U));
Env->BitBlt(Dst->GetWritePtr(PLANAR_V), Dst->GetPitch(PLANAR_V), SrcPicture->data[2], SrcPicture->linesize[2], Dst->GetRowSize(PLANAR_V), Dst->GetHeight(PLANAR_V));
} else {
if (VI.IsRGB())
Env->BitBlt(Dst->GetWritePtr() + Dst->GetPitch() * (Dst->GetHeight() - 1), -Dst->GetPitch(), SrcPicture->data[0], SrcPicture->linesize[0], Dst->GetRowSize(), Dst->GetHeight());
else
Env->BitBlt(Dst->GetWritePtr(), Dst->GetPitch(), SrcPicture->data[0], SrcPicture->linesize[0], Dst->GetRowSize(), Dst->GetHeight());
}
return Dst;
}
PVideoFrame AvisynthVideoSource::GetFrame(int n, IScriptEnvironment *Env) {
char ErrorMsg[1024];
unsigned MsgSize = sizeof(ErrorMsg);
const AVFrameLite *Frame;
if (FPSNum > 0 && FPSDen > 0)
Frame = FFMS_GetFrameByTime(VS, FFMS_GetVideoProperties(VS)->FirstTime + (double)(n * (int64_t)FPSDen) / FPSNum, ErrorMsg, MsgSize);
else
Frame = FFMS_GetFrame(VS, n, ErrorMsg, MsgSize);
if (Frame == NULL)
Env->ThrowError("FFVideoSource: %s", ErrorMsg);
Env->SetVar("FFPICT_TYPE", Frame->PictType);
return OutputFrame(Frame, Env);
}
AvisynthAudioSource::AvisynthAudioSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, IScriptEnvironment* Env, char *ErrorMsg, unsigned MsgSize) {
memset(&VI, 0, sizeof(VI));
AS = FFMS_CreateAudioSource(SourceFile, Track, TrackIndices, ErrorMsg, MsgSize);
if (!AS)
Env->ThrowError(ErrorMsg);
const AudioProperties AP = *FFMS_GetAudioProperties(AS);
VI.nchannels = AP.Channels;
VI.num_audio_samples = AP.NumSamples;
VI.audio_samples_per_second = AP.SampleRate;
if (AP.Float && AP.BitsPerSample == 32) {
VI.sample_type = SAMPLE_FLOAT;
} else {
switch (AP.BitsPerSample) {
case 8: VI.sample_type = SAMPLE_INT8; break;
case 16: VI.sample_type = SAMPLE_INT16; break;
case 24: VI.sample_type = SAMPLE_INT24; break;
case 32: VI.sample_type = SAMPLE_INT32; break;
default: Env->ThrowError("FFAudioSource: Bad audio format");
}
}
}
AvisynthAudioSource::~AvisynthAudioSource() {
FFMS_DestroyAudioSource(AS);
}
void AvisynthAudioSource::GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment *Env) {
char ErrorMsg[1024];
unsigned MsgSize = sizeof(ErrorMsg);
if (FFMS_GetAudio(AS, Buf, Start, Count, ErrorMsg, MsgSize))
Env->ThrowError(ErrorMsg);
}

View File

@ -1,70 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFAVISYNTH_H
#define FFAVISYNTH_H
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libpostproc/postprocess.h>
}
#include <windows.h>
#include "avisynth.h"
#include "ffms.h"
class AvisynthVideoSource : public IClip {
private:
VideoInfo VI;
VideoBase *VS;
SwsContext *SWS;
int ConvertToFormat;
int FPSNum;
int FPSDen;
void InitOutputFormat(int CurrentFormat, IScriptEnvironment *Env);
PVideoFrame OutputFrame(const AVFrameLite *SrcPicture, IScriptEnvironment *Env);
public:
AvisynthVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, int FPSNum, int FPSDen, const char *PP, int Threads, int SeekMode, IScriptEnvironment* Env, char *ErrorMsg, unsigned MsgSize);
~AvisynthVideoSource();
bool __stdcall GetParity(int n) { return false; }
void __stdcall SetCacheHints(int cachehints, int frame_range) { }
const VideoInfo& __stdcall GetVideoInfo() { return VI; }
void __stdcall GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment *Env) { }
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env);
};
class AvisynthAudioSource : public IClip {
private:
VideoInfo VI;
AudioBase *AS;
public:
AvisynthAudioSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, IScriptEnvironment* Env, char *ErrorMsg, unsigned MsgSize);
~AvisynthAudioSource();
bool __stdcall GetParity(int n) { return false; }
void __stdcall SetCacheHints(int cachehints, int frame_range) { }
const VideoInfo& __stdcall GetVideoInfo() { return VI; }
void __stdcall GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment *Env);
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env) { return NULL; };
};
#endif

View File

@ -1,236 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <string>
#include "ffms.h"
#include "ffavisynth.h"
#include "ffswscale.h"
#include "ffpp.h"
int GetNumberOfLogicalCPUs() {
SYSTEM_INFO SI;
GetSystemInfo(&SI);
return SI.dwNumberOfProcessors;
}
AVSValue __cdecl CreateFFIndex(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
FFMS_Init();
char ErrorMsg[1024];
unsigned MsgSize = sizeof(ErrorMsg);
if (!Args[0].Defined())
Env->ThrowError("FFIndex: No source specified");
const char *Source = Args[0].AsString();
const char *CacheFile = Args[1].AsString("");
int IndexMask = Args[2].AsInt(0);
int DumpMask = Args[3].AsInt(0);
const char *AudioFile = Args[4].AsString("");
bool OverWrite = Args[5].AsBool(false);
std::string DefaultCache(Source);
DefaultCache.append(".ffindex");
if (!strcmp(CacheFile, ""))
CacheFile = DefaultCache.c_str();
if (!strcmp(AudioFile, ""))
AudioFile = Source;
// Return values
// 0: Index already present
// 1: Index generated
// 2: Index forced to be overwritten
FrameIndex *Index = NULL;
if (OverWrite || !(Index = FFMS_ReadIndex(CacheFile, ErrorMsg, MsgSize))) {
if (!(Index = FFMS_MakeIndex(Source, IndexMask, DumpMask, AudioFile, true, NULL, NULL, ErrorMsg, MsgSize)))
Env->ThrowError("FFIndex: %s", ErrorMsg);
if (FFMS_WriteIndex(CacheFile, Index, ErrorMsg, MsgSize)) {
FFMS_DestroyFrameIndex(Index);
Env->ThrowError("FFIndex: %s", ErrorMsg);
}
FFMS_DestroyFrameIndex(Index);
if (!OverWrite)
return AVSValue(1);
else
return AVSValue(2);
} else {
FFMS_DestroyFrameIndex(Index);
return AVSValue(0);
}
}
AVSValue __cdecl CreateFFVideoSource(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
FFMS_Init();
char ErrorMsg[1024];
unsigned MsgSize = sizeof(ErrorMsg);
if (!Args[0].Defined())
Env->ThrowError("FFVideoSource: No source specified");
const char *Source = Args[0].AsString();
int Track = Args[1].AsInt(-1);
bool Cache = Args[2].AsBool(true);
const char *CacheFile = Args[3].AsString("");
int FPSNum = Args[4].AsInt(-1);
int FPSDen = Args[5].AsInt(1);
const char *PP = Args[6].AsString("");
int Threads = Args[7].AsInt(-1);
const char *Timecodes = Args[8].AsString("");
int SeekMode = Args[9].AsInt(1);
if (Track <= -2)
Env->ThrowError("FFVideoSource: No video track selected");
if (SeekMode < -1 || SeekMode > 3)
Env->ThrowError("FFVideoSource: Invalid seekmode selected");
if (Threads <= 0)
Threads = GetNumberOfLogicalCPUs();
if (Threads < 1)
Env->ThrowError("FFVideoSource: Invalid thread count");
if (!_stricmp(Source, Timecodes))
Env->ThrowError("FFVideoSource: Timecodes will overwrite the source");
std::string DefaultCache(Source);
DefaultCache.append(".ffindex");
if (!strcmp(CacheFile, ""))
CacheFile = DefaultCache.c_str();
FrameIndex *Index = NULL;
if (Cache)
Index = FFMS_ReadIndex(CacheFile, ErrorMsg, MsgSize);
if (!Index) {
if (!(Index = FFMS_MakeIndex(Source, 0, 0, NULL, true, NULL, NULL, ErrorMsg, MsgSize)))
Env->ThrowError("FFVideoSource: %s", ErrorMsg);
if (Cache)
if (FFMS_WriteIndex(CacheFile, Index, ErrorMsg, MsgSize)) {
FFMS_DestroyFrameIndex(Index);
Env->ThrowError("FFVideoSource: %s", ErrorMsg);
}
}
if (Track == -1)
Track = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_VIDEO, ErrorMsg, MsgSize);
if (Track < 0)
Env->ThrowError("FFVideoSource: No video track found");
if (strcmp(Timecodes, "")) {
if (FFMS_WriteTimecodes(FFMS_GetTITrackIndex(Index, Track, ErrorMsg, MsgSize), Timecodes, ErrorMsg, MsgSize)) {
FFMS_DestroyFrameIndex(Index);
Env->ThrowError("FFVideoSource: %s", ErrorMsg);
}
}
AvisynthVideoSource *Filter;
try {
Filter = new AvisynthVideoSource(Source, Track, Index, FPSNum, FPSDen, PP, Threads, SeekMode, Env, ErrorMsg, MsgSize);
} catch (...) {
FFMS_DestroyFrameIndex(Index);
throw;
}
FFMS_DestroyFrameIndex(Index);
return Filter;
}
AVSValue __cdecl CreateFFAudioSource(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
FFMS_Init();
char ErrorMsg[1024];
unsigned MsgSize = sizeof(ErrorMsg);
if (!Args[0].Defined())
Env->ThrowError("FFAudioSource: No source specified");
const char *Source = Args[0].AsString();
int Track = Args[1].AsInt(-1);
bool Cache = Args[2].AsBool(true);
const char *CacheFile = Args[3].AsString("");
if (Track <= -2)
Env->ThrowError("FFAudioSource: No audio track selected");
std::string DefaultCache(Source);
DefaultCache.append(".ffindex");
if (!strcmp(CacheFile, ""))
CacheFile = DefaultCache.c_str();
FrameIndex *Index = NULL;
if (Cache)
Index = FFMS_ReadIndex(CacheFile, ErrorMsg, MsgSize);
if (!Index) {
if (!(Index = FFMS_MakeIndex(Source, -1, 0, CacheFile, true, NULL, NULL, ErrorMsg, MsgSize)))
Env->ThrowError("FFAudioSource: %s", ErrorMsg);
if (Cache)
if (FFMS_WriteIndex(CacheFile, Index, ErrorMsg, MsgSize)) {
FFMS_DestroyFrameIndex(Index);
Env->ThrowError("FFAudioSource: %s", ErrorMsg);
}
}
if (Track == -1)
Track = FFMS_GetFirstTrackOfType(Index, FFMS_TYPE_AUDIO, ErrorMsg, MsgSize);
if (Track < 0)
Env->ThrowError("FFAudioSource: No audio track found");
AvisynthAudioSource *Filter;
try {
Filter = new AvisynthAudioSource(Source, Track, Index, Env, ErrorMsg, MsgSize);
} catch (...) {
FFMS_DestroyFrameIndex(Index);
throw;
}
FFMS_DestroyFrameIndex(Index);
return Filter;
}
AVSValue __cdecl CreateFFPP(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
return new FFPP(Args[0].AsClip(), Args[1].AsString(""), Env);
}
AVSValue __cdecl CreateSWScale(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
return new SWScale(Args[0].AsClip(), Args[1].AsInt(0), Args[2].AsInt(0), Args[3].AsString("BICUBIC"), Args[4].AsString(""), Env);
}
AVSValue __cdecl FFNoLog(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
FFMS_NoLog();
return 0;
}
extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* Env) {
Env->AddFunction("FFIndex", "[source]s[cachefile]s[indexmask]i[dumpmask]i[audiofile]s[overwrite]b", CreateFFIndex, 0);
Env->AddFunction("FFVideoSource", "[source]s[track]i[cache]b[cachefile]s[fpsnum]i[fpsden]i[pp]s[threads]i[timecodes]s[seekmode]i", CreateFFVideoSource, 0);
Env->AddFunction("FFAudioSource", "[source]s[track]i[cache]b[cachefile]s", CreateFFAudioSource, 0);
Env->AddFunction("FFPP", "c[pp]s", CreateFFPP, 0);
Env->AddFunction("SWScale", "c[width]i[height]i[resizer]s[colorspace]s", CreateSWScale, 0);
Env->AddFunction("FFNoLog", "", FFNoLog, 0);
return "FFmpegSource - The Second Coming";
}

View File

@ -1,214 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "ffms.h"
#include "ffvideosource.h"
#include "ffaudiosource.h"
#include "indexing.h"
#ifdef __UNIX__
#define _snprintf snprintf
#endif
FrameInfo::FrameInfo(int64_t DTS, bool KeyFrame) {
this->DTS = DTS;
this->SampleStart = 0;
this->FilePos = 0;
this->FrameSize = 0;
this->KeyFrame = KeyFrame;
}
FrameInfo::FrameInfo(int64_t DTS, int64_t SampleStart, bool KeyFrame) {
this->DTS = DTS;
this->SampleStart = SampleStart;
this->FilePos = 0;
this->FrameSize = 0;
this->KeyFrame = KeyFrame;
}
FrameInfo::FrameInfo(int64_t SampleStart, int64_t FilePos, unsigned int FrameSize, bool KeyFrame) {
this->DTS = 0;
this->SampleStart = SampleStart;
this->FilePos = FilePos;
this->FrameSize = FrameSize;
this->KeyFrame = KeyFrame;
}
FFMS_API(void) FFMS_Init() {
static bool InitDone = false;
if (!InitDone)
av_register_all();
InitDone = true;
}
FFMS_API(void) FFMS_NoLog() {
av_log_set_level(AV_LOG_QUIET);
}
FFMS_API(VideoBase *) FFMS_CreateVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, const char *PP, int Threads, int SeekMode, char *ErrorMsg, unsigned MsgSize) {
try {
switch (TrackIndices->Decoder) {
case 0: return new FFVideoSource(SourceFile, Track, TrackIndices, PP, Threads, SeekMode, ErrorMsg, MsgSize);
case 1: return new MatroskaVideoSource(SourceFile, Track, TrackIndices, PP, Threads, ErrorMsg, MsgSize);
#ifdef HAALITS
case 2: return new HaaliTSVideoSource(SourceFile, Track, TrackIndices, PP, Threads, ErrorMsg, MsgSize);
#endif
default:
_snprintf(ErrorMsg, MsgSize, "Unsupported format");
return NULL;
}
} catch (...) {
return NULL;
}
}
FFMS_API(AudioBase *) FFMS_CreateAudioSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize) {
try {
switch (TrackIndices->Decoder) {
case 0: return new FFAudioSource(SourceFile, Track, TrackIndices, ErrorMsg, MsgSize);
case 1: return new MatroskaAudioSource(SourceFile, Track, TrackIndices, ErrorMsg, MsgSize);
default:
_snprintf(ErrorMsg, MsgSize, "Unsupported format");
return NULL;
}
} catch (...) {
return NULL;
}
}
FFMS_API(void) FFMS_DestroyVideoSource(VideoBase *VB) {
delete VB;
}
FFMS_API(void) FFMS_DestroyAudioSource(AudioBase *AB) {
delete AB;
}
FFMS_API(const VideoProperties *) FFMS_GetVideoProperties(VideoBase *VB) {
return &VB->GetVideoProperties();
}
FFMS_API(const AudioProperties *) FFMS_GetAudioProperties(AudioBase *AB) {
return &AB->GetAudioProperties();
}
FFMS_API(const AVFrameLite *) FFMS_GetFrame(VideoBase *VB, int n, char *ErrorMsg, unsigned MsgSize) {
return (AVFrameLite *)VB->GetFrame(n, ErrorMsg, MsgSize);
}
FFMS_API(const AVFrameLite *) FFMS_GetFrameByTime(VideoBase *VB, double Time, char *ErrorMsg, unsigned MsgSize) {
return (AVFrameLite *)VB->GetFrameByTime(Time, ErrorMsg, MsgSize);
}
FFMS_API(int) FFMS_GetAudio(AudioBase *AB, void *Buf, int64_t Start, int64_t Count, char *ErrorMsg, unsigned MsgSize) {
return AB->GetAudio(Buf, Start, Count, ErrorMsg, MsgSize);
}
FFMS_API(int) FFMS_SetOutputFormat(VideoBase *VB, int TargetFormat, int Width, int Height, char *ErrorMsg, unsigned MsgSize) {
return VB->SetOutputFormat(TargetFormat, Width, Height, ErrorMsg, MsgSize);
}
FFMS_API(void) FFMS_ResetOutputFormat(VideoBase *VB) {
VB->ResetOutputFormat();
}
FFMS_API(void) FFMS_DestroyFrameIndex(FrameIndex *FI) {
delete FI;
}
FFMS_API(int) FFMS_GetFirstTrackOfType(FrameIndex *TrackIndices, int TrackType, char *ErrorMsg, unsigned MsgSize) {
for (int i = 0; i < TrackIndices->size(); i++)
if ((*TrackIndices)[i].TT == TrackType)
return i;
_snprintf(ErrorMsg, MsgSize, "No suitable track found");
return -1;
}
FFMS_API(int) FFMS_GetNumTracks(FrameIndex *TrackIndices) {
return TrackIndices->size();
}
FFMS_API(int) FFMS_GetTrackType(FrameInfoVector *FIV) {
return FIV->TT;
}
FFMS_API(int) FFMS_GetNumFrames(FrameInfoVector *FIV) {
return FIV->size();
}
FFMS_API(const FrameInfo *) FFMS_GetFrameInfo(FrameInfoVector *FIV, int Frame, char *ErrorMsg, unsigned MsgSize) {
if (Frame < 0 || Frame >= FIV->size()) {
_snprintf(ErrorMsg, MsgSize, "Invalid frame specified");
return NULL;
} else {
return &(*FIV)[Frame];
}
}
FFMS_API(FrameInfoVector *) FFMS_GetTITrackIndex(FrameIndex *TrackIndices, int Track, char *ErrorMsg, unsigned MsgSize) {
if (Track < 0 || Track >= TrackIndices->size()) {
_snprintf(ErrorMsg, MsgSize, "Invalid track specified");
return NULL;
} else {
return &(*TrackIndices)[Track];
}
}
FFMS_API(FrameInfoVector *) FFMS_GetVSTrackIndex(VideoBase *VB) {
return VB->GetFrameInfoVector();
}
FFMS_API(int) FFMS_FindClosestKeyFrame(FrameInfoVector *FIV, int Frame, char *ErrorMsg, unsigned MsgSize) {
if (Frame < 0 || Frame >= FIV->size()) {
_snprintf(ErrorMsg, MsgSize, "Out of range frame specified");
return -1;
} else {
return FIV->FindClosestKeyFrame(Frame);
}
}
FFMS_API(int) FFMS_FrameFromDTS(FrameInfoVector *FIV, int64_t DTS) {
return FIV->FrameFromDTS(DTS);
}
FFMS_API(int) FFMS_ClosestFrameFromDTS(FrameInfoVector *FIV, int64_t DTS) {
return FIV->ClosestFrameFromDTS(DTS);
}
FFMS_API(const TrackTimeBase *) FFMS_GetTimeBase(FrameInfoVector *FIV) {
return &FIV->TB;
}
FFMS_API(int) FFMS_WriteTimecodes(FrameInfoVector *FIV, const char *TimecodeFile, char *ErrorMsg, unsigned MsgSize) {
return FIV->WriteTimecodes(TimecodeFile, ErrorMsg, MsgSize);
}
FFMS_API(FrameIndex *) FFMS_MakeIndex(const char *SourceFile, int IndexMask, int DumpMask, const char *AudioFile, bool IgnoreDecodeErrors, IndexCallback IP, void *Private, char *ErrorMsg, unsigned MsgSize) {
return MakeIndex(SourceFile, IndexMask, DumpMask, AudioFile, IgnoreDecodeErrors, IP, Private, ErrorMsg, MsgSize);
}
FFMS_API(FrameIndex *) FFMS_ReadIndex(const char *IndexFile, char *ErrorMsg, unsigned MsgSize) {
return ReadIndex(IndexFile, ErrorMsg, MsgSize);
}
FFMS_API(int) FFMS_WriteIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize) {
return WriteIndex(IndexFile, TrackIndices, ErrorMsg, MsgSize);
}

View File

@ -1,193 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFMS_H
#define FFMS_H
#include <stdint.h>
#define FFMS_EXPORTS
#ifdef __cplusplus
# define EXTERN_C extern "C"
#else
# define EXTERN_C
#endif
#ifdef _WIN32
# define FFMS_CC __stdcall
# ifdef FFMS_EXPORTS
# define FFMS_API(ret) EXTERN_C __declspec(dllexport) ret FFMS_CC
# else
# define FFMS_API(ret) EXTERN_C __declspec(dllimport) ret FFMS_CC
# endif
#else
# define FFMS_CC
# define FFMS_API(ret) EXTERN_C ret FFMS_CC
#endif
class VideoBase;
class AudioBase;
class FrameIndex;
class FrameInfoVector;
typedef int (FFMS_CC *IndexCallback)(int State, int64_t Current, int64_t Total, void *Private);
enum TrackType {
FFMS_TYPE_VIDEO = 0,
FFMS_TYPE_AUDIO = 1,
};
// PixelFormat declarations from avutil.h so external libraries don't necessarily have to include ffmpeg headers
enum FFMS_PixelFormat {
FFMS_PIX_FMT_NONE= -1,
FFMS_PIX_FMT_YUV420P, ///< Planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
FFMS_PIX_FMT_YUYV422, ///< Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
FFMS_PIX_FMT_RGB24, ///< Packed RGB 8:8:8, 24bpp, RGBRGB...
FFMS_PIX_FMT_BGR24, ///< Packed RGB 8:8:8, 24bpp, BGRBGR...
FFMS_PIX_FMT_YUV422P, ///< Planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
FFMS_PIX_FMT_YUV444P, ///< Planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
FFMS_PIX_FMT_RGB32, ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8R 8G 8B(lsb), in cpu endianness
FFMS_PIX_FMT_YUV410P, ///< Planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
FFMS_PIX_FMT_YUV411P, ///< Planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
FFMS_PIX_FMT_RGB565, ///< Packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), in cpu endianness
FFMS_PIX_FMT_RGB555, ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), in cpu endianness most significant bit to 0
FFMS_PIX_FMT_GRAY8, ///< Y , 8bpp
FFMS_PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black
FFMS_PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white
FFMS_PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette
FFMS_PIX_FMT_YUVJ420P, ///< Planar YUV 4:2:0, 12bpp, full scale (jpeg)
FFMS_PIX_FMT_YUVJ422P, ///< Planar YUV 4:2:2, 16bpp, full scale (jpeg)
FFMS_PIX_FMT_YUVJ444P, ///< Planar YUV 4:4:4, 24bpp, full scale (jpeg)
FFMS_PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h)
FFMS_PIX_FMT_XVMC_MPEG2_IDCT,
FFMS_PIX_FMT_UYVY422, ///< Packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
FFMS_PIX_FMT_UYYVYY411, ///< Packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
FFMS_PIX_FMT_BGR32, ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8B 8G 8R(lsb), in cpu endianness
FFMS_PIX_FMT_BGR565, ///< Packed RGB 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), in cpu endianness
FFMS_PIX_FMT_BGR555, ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), in cpu endianness most significant bit to 1
FFMS_PIX_FMT_BGR8, ///< Packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
FFMS_PIX_FMT_BGR4, ///< Packed RGB 1:2:1, 4bpp, (msb)1B 2G 1R(lsb)
FFMS_PIX_FMT_BGR4_BYTE, ///< Packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb)
FFMS_PIX_FMT_RGB8, ///< Packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
FFMS_PIX_FMT_RGB4, ///< Packed RGB 1:2:1, 4bpp, (msb)2R 3G 3B(lsb)
FFMS_PIX_FMT_RGB4_BYTE, ///< Packed RGB 1:2:1, 8bpp, (msb)2R 3G 3B(lsb)
FFMS_PIX_FMT_NV12, ///< Planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV
FFMS_PIX_FMT_NV21, ///< as above, but U and V bytes are swapped
FFMS_PIX_FMT_RGB32_1, ///< Packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in cpu endianness
FFMS_PIX_FMT_BGR32_1, ///< Packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in cpu endianness
FFMS_PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian
FFMS_PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian
FFMS_PIX_FMT_YUV440P, ///< Planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
FFMS_PIX_FMT_YUVJ440P, ///< Planar YUV 4:4:0 full scale (jpeg)
FFMS_PIX_FMT_YUVA420P, ///< Planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
};
// This is a subset of the original AVFrame only containing the most used parts.
// Even if it might seem like a good idea to cast it back to a full AVFrame to
// access a few more values you really shouldn't do that. Only the values present
// in AVFrameLite are actually updated when postprocessing is used.
struct AVFrameLite {
uint8_t *Data[4];
int Linesize[4];
uint8_t *Base[4];
int KeyFrame;
int PictType;
};
struct TrackTimeBase {
int Num;
int Den;
};
class FrameInfo {
public:
int64_t DTS;
int64_t SampleStart;
int64_t FilePos;
unsigned int FrameSize;
bool KeyFrame;
FrameInfo(int64_t DTS, bool KeyFrame);
FrameInfo(int64_t DTS, int64_t SampleStart, bool KeyFrame);
FrameInfo(int64_t SampleStart, int64_t FilePos, unsigned int FrameSize, bool KeyFrame);
};
struct VideoProperties {
int Width;
int Height;
int FPSDenominator;
int FPSNumerator;
int NumFrames;
int PixelFormat;
int SARNum;
int SARDen;
int CropTop;
int CropBottom;
int CropLeft;
int CropRight;
double FirstTime;
double LastTime;
};
struct AudioProperties {
int SampleRate;
int Channels;
int BitsPerSample;
bool Float;
int64_t NumSamples;
};
// Most functions return 0 on success
// Functions without error message output can be assumed to never fail
FFMS_API(void) FFMS_Init();
FFMS_API(void) FFMS_NoLog();
FFMS_API(VideoBase *) FFMS_CreateVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, const char *PP, int Threads, int SeekMode, char *ErrorMsg, unsigned MsgSize);
FFMS_API(AudioBase *) FFMS_CreateAudioSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize);
FFMS_API(void) FFMS_DestroyVideoSource(VideoBase *VB);
FFMS_API(void) FFMS_DestroyAudioSource(AudioBase *AB);
FFMS_API(const VideoProperties *) FFMS_GetVideoProperties(VideoBase *VB);
FFMS_API(const AudioProperties *) FFMS_GetAudioProperties(AudioBase *AB);
FFMS_API(const AVFrameLite *) FFMS_GetFrame(VideoBase *VB, int n, char *ErrorMsg, unsigned MsgSize);
FFMS_API(const AVFrameLite *) FFMS_GetFrameByTime(VideoBase *VB, double Time, char *ErrorMsg, unsigned MsgSize);
FFMS_API(int) FFMS_GetAudio(AudioBase *AB, void *Buf, int64_t Start, int64_t Count, char *ErrorMsg, unsigned MsgSize);
FFMS_API(int) FFMS_SetOutputFormat(VideoBase *VB, int TargetFormat, int Width, int Height, char *ErrorMsg, unsigned MsgSize);
FFMS_API(void) FFMS_ResetOutputFormat(VideoBase *VB);
FFMS_API(void) FFMS_DestroyFrameIndex(FrameIndex *FI);
FFMS_API(int) FFMS_GetFirstTrackOfType(FrameIndex *TrackIndices, int TrackType, char *ErrorMsg, unsigned MsgSize);
FFMS_API(int) FFMS_GetNumTracks(FrameIndex *TrackIndices);
FFMS_API(int) FFMS_GetTrackType(FrameInfoVector *FIV);
FFMS_API(int) FFMS_GetNumFrames(FrameInfoVector *FIV);
FFMS_API(const FrameInfo *) FFMS_GetFrameInfo(FrameInfoVector *FIV, int Frame, char *ErrorMsg, unsigned MsgSize);
FFMS_API(FrameInfoVector *) FFMS_GetTITrackIndex(FrameIndex *TrackIndices, int Track, char *ErrorMsg, unsigned MsgSize);
FFMS_API(FrameInfoVector *) FFMS_GetVSTrackIndex(VideoBase *VB);
FFMS_API(FrameInfoVector *) FFMS_GetASTrackIndex(AudioBase *AB);
FFMS_API(int) FFMS_FindClosestKeyFrame(FrameInfoVector *FIV, int Frame, char *ErrorMsg, unsigned MsgSize);
FFMS_API(int) FFMS_FrameFromDTS(FrameInfoVector *FIV, int64_t DTS);
FFMS_API(int) FFMS_ClosestFrameFromDTS(FrameInfoVector *FIV, int64_t DTS);
FFMS_API(const TrackTimeBase *) FFMS_GetTimeBase(FrameInfoVector *FIV);
FFMS_API(int) FFMS_WriteTimecodes(FrameInfoVector *FIV, const char *TimecodeFile, char *ErrorMsg, unsigned MsgSize);
FFMS_API(FrameIndex *) FFMS_MakeIndex(const char *SourceFile, int IndexMask, int DumpMask, const char *AudioFile, bool IgnoreDecodeErrors, IndexCallback IP, void *Private, char *ErrorMsg, unsigned MsgSize);
FFMS_API(FrameIndex *) FFMS_ReadIndex(const char *IndexFile, char *ErrorMsg, unsigned MsgSize);
FFMS_API(int) FFMS_WriteIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize);
#endif

View File

@ -1,238 +0,0 @@
<html>
<head>
<title>
FFmpegSource2 Documentation
</title>
</head>
<body>
<h1>FFmpegSource2 Documentation</h1>
<p>
Opens files using ffmpeg and nothing else. May be frame accurate on good days. The source is MIT licensed and can be obtained from https://spaceboyz.net/svn/aegisub/trunk/FFmpegSource2. The precompiled binary is GPL licensed. If you are religious you may consider this the second coming.
</p>
<h2>Compatibility - Video</h2>
<ul>
<li>AVI, MKV, MP4, FLV: Frame accurate</li>
<li>WMV: Frame accurate(?) but avformat seems to pick keyframes relatively far away</li>
<li>OGM: Messed up first frame and seeking produces smearing with seekmode=3, incredibly slow seeking without, remux to mkv or avi</li>
<li>VOB: No rff flags applied, frame accurate?</li>
<li>MPG: Seeking seems to be off by one or two frames now and then</li>
<li>M2TS, TS: Linear access only (seekmode=-1)</li>
<li>Image files: Most formats can be opened if seekmode=-1 is set</li>
</ul>
<h2>Compatibility - Audio</h2>
<ul>
<li>All formats are written to separate wave64 files</li>
<li>No wave64 reader is provided</li>
</ul>
<h2>Usage</h2>
<p>
<b>FFIndex(string source, string cachefile = source + ".ffindex", int indexmask = 0, int dumpmask = 0, string audiofile = source, bool overwrite = false)</b><br />
Used to invoke indexing separately and to write audio tracks to disk as wave64 files
</p>
<p>
<b>FFVideoSource(string source, int track, bool cache = true, string cachefile = source + ".ffindex", int fpsnum = -1, int fpsden = 1, string pp, int threads = -1, string timecodes, int seekmode = 1)</b><br />
Opens video, will invoke indexing with the defaults if no preexisting index is found
</p>
<p>
<b>FFAudioSource(string source, int track, bool cache = true, string cachefile = source + ".ffindex")</b><br />
Opens audio, <b>if an index already exists it needs to contain a suitable audio index or empty audio will be returned</b>, will invoke indexing with the defaults if no preexisting index is found
</p>
<p>
<b>FFPP(clip, string pp)</b><br />
Separate postprocessing which also seems to include a few simple deinterlacers
</p>
<p>
<b>SWScale(clip, width = -1, height = -1, resizer = "BICUBIC", colorspace = "")</b><br />
Separate postprocessing which also seems to include a few simple deinterlacers
</p>
<b>FFNoLog()</b><br />
Disable all logging output from FFmpeg
</p>
<p>
<b>source:</b>
Source file.
</p>
<p>
<b>indexmask &amp; dumpmask:</b>
Which audio tracks to index/write to disk. Dumping a track also implies indexing since the same work has to be done anyway. It is a binary mask meaning that 7 corresponds to writing tracks 1-3. Non-audio tracks are ignored. -1 writes all tracks.
</p>
<p>
<b>audiofile:</b>
The base name to use for the decoded audio. Track number and delay is appended.
</p>
<p>
<b>overwrite:</b>
Forces reindexing even if a valid index already exists. May be useful for trackmask changes or testing.
</p>
<p>
<b>track:</b>
Track number as seen by the relevant demuxer, starts from 0, -1 means it will pick the first suitable track.
</p>
<p>
<b>fpsnum &amp; fpsden:</b>
For VFR -> CFR conversion. Setting fpsnum <= 0 means a 1:1 relation with the encoded frames.
</p>
<p>
<b>timecodes:</b>
File to output timecodes to, if the file exists it will be overwritten.
</p>
<p>
<b>cache:</b>
Write indexing information to a file for later use. This setting does not control if The video index is loaded which it always is if it exists.
</p>
<p>
<b>cachefile</b>
Where to write the cache information.
</p>
<p>
<b>pp:</b>
See the table below for a full description, an empty string means no processing. It is recommended to avoid the autoq option since it's currently unknown what effect it will have on the processing.
</p>
<p>
<b>threads:</b>
Sets the number of decoder threads used. Defaults to the number of cpus reported by windows. Ignored by lavc if the used decoder doesn't implement it.
</p>
<p>
<b>seekmode:</b>
Force how seeking is handled, has no effect on matroska files which always use the equivalent of seekmode=1<br />
<b>-1:</b> linear access without rewind, will throw an error if each successive requested frame number isn't bigger than the last one, only intended for opening images but might work on well with some obscure video format<br />
<b>0:</b> linear access, the definition of slow but should make some formats "usable"<br />
<b>1:</b> safe normal, bases seeking decisions on the reported keyframe positions<br />
<b>2:</b> unsafe normal, same as 1 but no error will be thrown if the exact destination has to be guessed<br />
<b>3:</b> aggressive, seek in the forward direction even if no closer keyframe is known to exist, only useful for testing and containers where avformat doesn't report keyframes properly
</p>
<p>
<b>width &amp; height:</b>
Width and height to resize to. Value below or equal to 0 is the same as specifying the input dimensions.
</p>
<p>
<b>resizer:</b>
Selects the resizer used for resampling the chroma planes and normal resizing. The available methods are: FAST_BILINEAR, BILINEAR, BICUBIC, X, POINT, AREA, BICUBLIN, GAUSS, SINC, LANCZOS and SPLINE.
</p>
<p>
<b>colorspace:</b>
The colorspace to convert to. The names are YV12, YUY2, RGB24, RGB32 and the empty string for same as input.
</p>
<h2>PP string format</h2>
<pre>
Available postprocessing filters:
Filters Options
short long name short long option Description
* * a autoq CPU power dependent enabler
c chrom chrominance filtering enabled
y nochrom chrominance filtering disabled
n noluma luma filtering disabled
hb hdeblock (2 threshold) horizontal deblocking filter
1. difference factor: default=32, higher -> more deblocking
2. flatness threshold: default=39, lower -> more deblocking
the h & v deblocking filters share these
so you can't set different thresholds for h / v
vb vdeblock (2 threshold) vertical deblocking filter
ha hadeblock (2 threshold) horizontal deblocking filter
va vadeblock (2 threshold) vertical deblocking filter
h1 x1hdeblock experimental h deblock filter 1
v1 x1vdeblock experimental v deblock filter 1
dr dering deringing filter
al autolevels automatic brightness / contrast
f fullyrange stretch luminance to (0..255)
lb linblenddeint linear blend deinterlacer
li linipoldeint linear interpolating deinterlace
ci cubicipoldeint cubic interpolating deinterlacer
md mediandeint median deinterlacer
fd ffmpegdeint ffmpeg deinterlacer
l5 lowpass5 FIR lowpass deinterlacer
de default hb:a,vb:a,dr:a
fa fast h1:a,v1:a,dr:a
ac ha:a:128:7,va:a,dr:a
tn tmpnoise (3 threshold) temporal noise reducer
1. <= 2. <= 3. larger -> stronger filtering
fq forceQuant <quantizer> force quantizer
Usage:
<filterName>[:<option>[:<option>...]][[,|/][-]<filterName>[:<option>...]]...
long form example:
vdeblock:autoq/hdeblock:autoq/linblenddeint default,-vdeblock
short form example:
vb:a/hb:a/lb de,-vb
more examples:
tn:64:128:256
</pre>
<h2>Compiling</h2>
<p><b>zlib</b> from http://www.zlib.net/</p>
<p><b>FFmpeg svn</b> from http://ffmpeg.mplayerhq.hu/</p>
<p><b>Required FFmpeg Configuration:</b>
./configure --enable-memalign-hack --enable-gpl --enable-swscale --enable-postproc
<p><b>Suggested Additional Options:</b>
--enable-w32threads --disable-encoders --disable-muxers --disable-debug</p>
<p>
Note that --enable-w32threads is required for multithreaded decoding to work.
</p>
<h2>Changes</h2>
<ul>
<li>2.00 beta 4<ul>
<li>Added the function FFNoLog which suppresses all messages from ffmpeg</li>
<li>Experimental new TS parsing using Haali's splitter (with bugs)</li>
<li>Everything is now compiled with VS2008 and GCC 4.3.2</li>
<li>Updated FFmpeg to rev 16383 (no libfaad2 this time)</li>
</ul></li>
<li>2.00 beta 3<ul>
<li>Compiled with libfaad2 again (has anyone seen a single aac file lavc can open right now?)</li>
<li>More API changes (and even more are likely to come)</li>
<li>Several access violations and memory leaks on opening and indexing files fixed</li>
<li>Added a VFR to CFR mode</li>
<li>Readded FFAudioSource support for other containers (glitches still present now and then but no separate raw cache is required and possibly less buggy)</li>
<li>Renamed the dll to FFMS2.dll, FFMS2 is now the official short name of the project</li>
<li>Updated FFmpeg to rev 15522</li>
</ul></li>
<li>2.00 beta 2<ul>
<li>More API changes (and more are likely to come)</li>
<li>Includes a simple CLI indexing application</li>
<li>FFIndex now takes a few more arguments</li>
<li>Readded FFAudioSource (only matroska supported for now)</li>
<li>Updated FFmpeg to rev 15396</li>
</ul></li>
<li>2.00 beta 1<ul>
<li>Can now be used as a stand alone library for making indices and retrieving frames</li>
<li>Rewrote most things</li>
<li>Updated FFmpeg to rev 15301</li>
</ul></li>
</ul>
</body>
</html>

View File

@ -1,201 +0,0 @@
// Copyright (c) 2008 Karl Blomster
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <iostream>
#include <string>
#include <stdlib.h>
#include "ffms.h"
int TrackMask;
int DumpMask;
bool Overwrite;
bool IgnoreErrors;
std::string InputFile;
std::string CacheFile;
std::string AudioFile;
FrameIndex *Index;
void PrintUsage () {
using namespace std;
cout << "FFmpegSource2 indexing app" << endl
<< "Usage: ffmsindex [options] inputfile [outputfile]" << endl
<< "If no output filename is specified, inputfile.ffindex will be used." << endl << endl
<< "Options:" << endl
<< "-f Force overwriting of existing index file, if any (default: no)" << endl
<< "-s Silently skip indexing of audio tracks that cannot be read (default: no)" << endl
<< "-t N Set the audio indexing mask to N (-1 means index all tracks, 0 means index none, default: 0)" << endl
<< "-d N Set the audio decoding mask to N (mask syntax same as -t, default: 0)" << endl
<< "-a NAME Set the audio output base filename to NAME (default: input filename)";
}
void ParseCMDLine (int argc, char *argv[]) {
if (argc <= 1) {
PrintUsage();
throw "";
}
// defaults
InputFile = "";
CacheFile = "";
AudioFile = "";
TrackMask = 0;
DumpMask = 0;
Overwrite = false;
IgnoreErrors = false;
// argv[0] = name of program
int i = 1;
while (i < argc) {
std::string Option = argv[i];
std::string OptionArg = "";
if (i+1 < argc)
OptionArg = argv[i+1];
if (!Option.compare("-f")) {
Overwrite = true;
} else if (!Option.compare("-s")) {
IgnoreErrors = true;
} else if (!Option.compare("-t")) {
TrackMask = atoi(OptionArg.c_str());
i++;
} else if (!Option.compare("-d")) {
DumpMask = atoi(OptionArg.c_str());
i++;
} else if (!Option.compare("-a")) {
AudioFile = OptionArg;
i++;
} else if (InputFile.empty()) {
InputFile = argv[i];
} else if (CacheFile.empty()) {
CacheFile = argv[i];
} else {
std::cout << "Warning: ignoring unknown option " << argv[i] << std::endl;
}
i++;
}
if (InputFile.empty()) {
throw "Error: no input file specified";
}
if (CacheFile.empty()) {
CacheFile = InputFile;
CacheFile.append(".ffindex");
}
if (AudioFile.empty()) {
AudioFile = InputFile;
}
}
static int FFMS_CC UpdateProgress(int State, int64_t Current, int64_t Total, void *Private) {
using namespace std;
int *LastPercentage = (int *)Private;
int Percentage = int((double(Current)/double(Total)) * 100);
if (Percentage <= *LastPercentage)
return 0;
*LastPercentage = Percentage;
/*if (Percentage < 10)
cout << "\b\b";
else
cout << "\b\b\b"; */
cout << "Indexing, please wait... " << Percentage << "% \r";
return 0;
}
void DoIndexing () {
char FFMSErrMsg[1024];
int MsgSize = sizeof(FFMSErrMsg);
int Progress = 0;
Index = FFMS_ReadIndex(CacheFile.c_str(), FFMSErrMsg, MsgSize);
if (Overwrite || Index == NULL) {
std::cout << "Indexing, please wait... 0% \r";
Index = FFMS_MakeIndex(InputFile.c_str(), TrackMask, DumpMask, AudioFile.c_str(), IgnoreErrors, UpdateProgress, &Progress, FFMSErrMsg, MsgSize);
if (Index == NULL) {
std::string Err = "\nIndexing error: ";
Err.append(FFMSErrMsg);
throw Err;
}
if (Progress != 100)
std::cout << "Indexing, please wait... 100% \r";
std::cout << std::endl << "Writing index... ";
if (FFMS_WriteIndex(CacheFile.c_str(), Index, FFMSErrMsg, MsgSize)) {
std::string Err = "Error writing index: ";
Err.append(FFMSErrMsg);
throw Err;
}
std::cout << "done." << std::endl;
} else {
throw "Error: index file already exists, use -f if you are sure you want to overwrite it.";
}
}
int main(int argc, char *argv[]) {
try {
ParseCMDLine(argc, argv);
} catch (const char *Error) {
std::cout << std::endl << Error << std::endl;
return 1;
} catch (std::string Error) {
std::cout << std::endl << Error << std::endl;
return 1;
} catch (...) {
std::cout << std::endl << "Unknown error" << std::endl;
return 1;
}
FFMS_Init();
try {
DoIndexing();
} catch (const char *Error) {
std::cout << Error << std::endl;
FFMS_DestroyFrameIndex(Index);
return 1;
} catch (std::string Error) {
std::cout << std::endl << Error << std::endl;
FFMS_DestroyFrameIndex(Index);
return 1;
} catch (...) {
std::cout << std::endl << "Unknown error" << std::endl;
FFMS_DestroyFrameIndex(Index);
return 1;
}
FFMS_DestroyFrameIndex(Index);
return 0;
}

View File

@ -1,96 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "ffpp.h"
#include "utils.h"
FFPP::FFPP(PClip AChild, const char *PP, IScriptEnvironment *Env) : GenericVideoFilter(AChild) {
if (!strcmp(PP, ""))
Env->ThrowError("FFPP: PP argument is empty");
PPContext = NULL;
PPMode = NULL;
SWSTo422P = NULL;
SWSFrom422P = NULL;
memset(&InputPicture, 0, sizeof(InputPicture));
memset(&OutputPicture, 0, sizeof(OutputPicture));
PPMode = pp_get_mode_by_name_and_quality((char *)PP, PP_QUALITY_MAX);
if (!PPMode)
Env->ThrowError("FFPP: Invalid postprocesing settings");
int Flags = GetCPUFlags();
if (vi.IsYV12()) {
Flags |= PP_FORMAT_420;
} else if (vi.IsYUY2()) {
Flags |= PP_FORMAT_422;
SWSTo422P = sws_getContext(vi.width, vi.height, PIX_FMT_YUV422, vi.width, vi.height, PIX_FMT_YUV422P, GetCPUFlags() | SWS_BICUBIC, NULL, NULL, NULL);
SWSFrom422P = sws_getContext(vi.width, vi.height, PIX_FMT_YUV422P, vi.width, vi.height, PIX_FMT_YUV422, GetCPUFlags() | SWS_BICUBIC, NULL, NULL, NULL);
avpicture_alloc(&InputPicture, PIX_FMT_YUV422P, vi.width, vi.height);
avpicture_alloc(&OutputPicture, PIX_FMT_YUV422P, vi.width, vi.height);
} else {
Env->ThrowError("FFPP: Only YV12 and YUY2 video supported");
}
PPContext = pp_get_context(vi.width, vi.height, Flags);
if (!PPContext)
Env->ThrowError("FFPP: Failed to create context");
}
FFPP::~FFPP() {
if (PPMode)
pp_free_mode(PPMode);
if (PPContext)
pp_free_context(PPContext);
if (SWSTo422P)
sws_freeContext(SWSTo422P);
if (SWSFrom422P)
sws_freeContext(SWSFrom422P);
avpicture_free(&InputPicture);
avpicture_free(&OutputPicture);
}
PVideoFrame FFPP::GetFrame(int n, IScriptEnvironment* Env) {
PVideoFrame Src = child->GetFrame(n, Env);
PVideoFrame Dst = Env->NewVideoFrame(vi);
if (vi.IsYV12()) {
const uint8_t *SrcData[3] = {(uint8_t *)Src->GetReadPtr(PLANAR_Y), (uint8_t *)Src->GetReadPtr(PLANAR_U), (uint8_t *)Src->GetReadPtr(PLANAR_V)};
int SrcStride[3] = {Src->GetPitch(PLANAR_Y), Src->GetPitch(PLANAR_U), Src->GetPitch(PLANAR_V)};
uint8_t *DstData[3] = {Dst->GetWritePtr(PLANAR_Y), Dst->GetWritePtr(PLANAR_U), Dst->GetWritePtr(PLANAR_V)};
int DstStride[3] = {Dst->GetPitch(PLANAR_Y), Dst->GetPitch(PLANAR_U), Dst->GetPitch(PLANAR_V)};
pp_postprocess(SrcData, SrcStride, DstData, DstStride, vi.width, vi.height, NULL, 0, PPMode, PPContext, 0);
} else if (vi.IsYUY2()) {
uint8_t *SrcData[1] = {(uint8_t *)Src->GetReadPtr()};
int SrcStride[1] = {Src->GetPitch()};
sws_scale(SWSTo422P, SrcData, SrcStride, 0, vi.height, InputPicture.data, InputPicture.linesize);
pp_postprocess(const_cast<const uint8_t **>(InputPicture.data), InputPicture.linesize, OutputPicture.data, OutputPicture.linesize, vi.width, vi.height, NULL, 0, PPMode, PPContext, 0);
uint8_t *DstData[1] = {Dst->GetWritePtr()};
int DstStride[1] = {Dst->GetPitch()};
sws_scale(SWSFrom422P, OutputPicture.data, OutputPicture.linesize, 0, vi.height, DstData, DstStride);
}
return Dst;
}

View File

@ -1,142 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "ffswscale.h"
#include "utils.h"
int CSNameToPIXFMT(const char * ACSName, int ADefault) {
if (!_stricmp(ACSName, ""))
return ADefault;
if (!_stricmp(ACSName, "YV12"))
return PIX_FMT_YUV420P;
if (!_stricmp(ACSName, "YUY2"))
return PIX_FMT_YUYV422;
if (!_stricmp(ACSName, "RGB24"))
return PIX_FMT_BGR24;
if (!_stricmp(ACSName, "RGB32"))
return PIX_FMT_RGB32;
return PIX_FMT_NONE;
}
int ResizerNameToSWSResizer(const char *AResizerName) {
if (!_stricmp(AResizerName, "FAST_BILINEAR"))
return SWS_FAST_BILINEAR;
if (!_stricmp(AResizerName, "BILINEAR"))
return SWS_BILINEAR;
if (!_stricmp(AResizerName, "BICUBIC"))
return SWS_BICUBIC;
if (!_stricmp(AResizerName, "X"))
return SWS_X;
if (!_stricmp(AResizerName, "POINT"))
return SWS_POINT;
if (!_stricmp(AResizerName, "AREA"))
return SWS_AREA;
if (!_stricmp(AResizerName, "BICUBLIN"))
return SWS_BICUBLIN;
if (!_stricmp(AResizerName, "GAUSS"))
return SWS_GAUSS;
if (!_stricmp(AResizerName, "SINC"))
return SWS_SINC;
if (!_stricmp(AResizerName, "LANCZOS"))
return SWS_LANCZOS;
if (!_stricmp(AResizerName, "SPLINE"))
return SWS_SPLINE;
return 0;
}
SWScale::SWScale(PClip Child, int ResizeToWidth, int ResizeToHeight, const char *ResizerName, const char *ConvertToFormatName, IScriptEnvironment *Env) : GenericVideoFilter(Child) {
Context = NULL;
OrigWidth = vi.width;
OrigHeight = vi.height;
FlipOutput = vi.IsYUV();
int ConvertFromFormat = PIX_FMT_NONE;
if (vi.IsYV12())
ConvertFromFormat = PIX_FMT_YUV420P;
if (vi.IsYUY2())
ConvertFromFormat = PIX_FMT_YUYV422;
if (vi.IsRGB24())
ConvertFromFormat = PIX_FMT_BGR24;
if (vi.IsRGB32())
ConvertFromFormat = PIX_FMT_RGB32;
if (ResizeToHeight <= 0)
ResizeToHeight = OrigHeight;
else
vi.height = ResizeToHeight;
if (ResizeToWidth <= 0)
ResizeToWidth = OrigWidth;
else
vi.width = ResizeToWidth;
int ConvertToFormat = CSNameToPIXFMT(ConvertToFormatName, ConvertFromFormat);
if (ConvertToFormat == PIX_FMT_NONE)
Env->ThrowError("SWScale: Invalid colorspace specified (%s)", ConvertToFormatName);
switch (ConvertToFormat) {
case PIX_FMT_YUV420P: vi.pixel_type = VideoInfo::CS_I420; break;
case PIX_FMT_YUYV422: vi.pixel_type = VideoInfo::CS_YUY2; break;
case PIX_FMT_BGR24: vi.pixel_type = VideoInfo::CS_BGR24; break;
case PIX_FMT_RGB32: vi.pixel_type = VideoInfo::CS_BGR32; break;
}
FlipOutput ^= vi.IsYUV();
int Resizer = ResizerNameToSWSResizer(ResizerName);
if (Resizer == 0)
Env->ThrowError("SWScale: Invalid resizer specified (%s)", ResizerName);
if (ConvertToFormat == PIX_FMT_YUV420P && vi.height & 1)
Env->ThrowError("SWScale: mod 2 output height required");
if ((ConvertToFormat == PIX_FMT_YUV420P || ConvertToFormat == PIX_FMT_YUYV422) && vi.width & 1)
Env->ThrowError("SWScale: mod 2 output width required");
// may one day need a SWS_CS_DEFAULT in flags
Context = sws_getContext(OrigWidth, OrigHeight, ConvertFromFormat, vi.width, vi.height, ConvertToFormat, GetCPUFlags() | Resizer, NULL, NULL, NULL);
if (Context == NULL)
Env->ThrowError("SWScale: Context creation failed");
}
SWScale::~SWScale() {
if (Context)
sws_freeContext(Context);
}
PVideoFrame SWScale::GetFrame(int n, IScriptEnvironment *Env) {
PVideoFrame Src = child->GetFrame(n, Env);
PVideoFrame Dst = Env->NewVideoFrame(vi);
uint8_t *SrcData[3] = {(uint8_t *)Src->GetReadPtr(PLANAR_Y), (uint8_t *)Src->GetReadPtr(PLANAR_U), (uint8_t *)Src->GetReadPtr(PLANAR_V)};
int SrcStride[3] = {Src->GetPitch(PLANAR_Y), Src->GetPitch(PLANAR_U), Src->GetPitch(PLANAR_V)};
if (FlipOutput) {
uint8_t *DstData[3] = {Dst->GetWritePtr(PLANAR_Y) + Dst->GetPitch(PLANAR_Y) * (Dst->GetHeight(PLANAR_Y) - 1), Dst->GetWritePtr(PLANAR_U) + Dst->GetPitch(PLANAR_U) * (Dst->GetHeight(PLANAR_U) - 1), Dst->GetWritePtr(PLANAR_V) + Dst->GetPitch(PLANAR_V) * (Dst->GetHeight(PLANAR_V) - 1)};
int DstStride[3] = {-Dst->GetPitch(PLANAR_Y), -Dst->GetPitch(PLANAR_U), -Dst->GetPitch(PLANAR_V)};
sws_scale(Context, SrcData, SrcStride, 0, OrigHeight, DstData, DstStride);
} else {
uint8_t *DstData[3] = {Dst->GetWritePtr(PLANAR_Y), Dst->GetWritePtr(PLANAR_U), Dst->GetWritePtr(PLANAR_V)};
int DstStride[3] = {Dst->GetPitch(PLANAR_Y), Dst->GetPitch(PLANAR_U), Dst->GetPitch(PLANAR_V)};
sws_scale(Context, SrcData, SrcStride, 0, OrigHeight, DstData, DstStride);
}
return Dst;
}

View File

@ -1,43 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFSWSCALE_H
#define FFSWSCALE_H
extern "C" {
#include <libswscale/swscale.h>
}
#include <windows.h>
#include "avisynth.h"
class SWScale : public GenericVideoFilter {
private:
SwsContext *Context;
int OrigWidth;
int OrigHeight;
bool FlipOutput;
public:
SWScale(PClip Child, int ResizeToWidth, int ResizeToHeight, const char *ResizerName, const char *ConvertToFormatName, IScriptEnvironment *Env);
~SWScale();
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env);
};
#endif

View File

@ -1,799 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "ffvideosource.h"
#include <errno.h>
#ifdef __UNIX__
#define _snprintf snprintf
#endif
int VideoBase::InitPP(const char *PP, int PixelFormat, char *ErrorMsg, unsigned MsgSize) {
if (PP == NULL || !strcmp(PP, ""))
return 0;
PPMode = pp_get_mode_by_name_and_quality(PP, PP_QUALITY_MAX);
if (!PPMode) {
_snprintf(ErrorMsg, MsgSize, "Invalid postprocesing settings");
return 1;
}
int Flags = GetCPUFlags();
switch (PixelFormat) {
case PIX_FMT_YUV420P: Flags |= PP_FORMAT_420; break;
case PIX_FMT_YUV422P: Flags |= PP_FORMAT_422; break;
case PIX_FMT_YUV411P: Flags |= PP_FORMAT_411; break;
case PIX_FMT_YUV444P: Flags |= PP_FORMAT_444; break;
default:
_snprintf(ErrorMsg, MsgSize, "Input format is not supported for postprocessing");
return 2;
}
PPContext = pp_get_context(VP.Width, VP.Height, Flags);
if (!(PPFrame = avcodec_alloc_frame())) {
_snprintf(ErrorMsg, MsgSize, "Failed to allocate temporary frame");
return 3;
}
if (avpicture_alloc((AVPicture *)PPFrame, PixelFormat, VP.Width, VP.Height) < 0) {
av_free(PPFrame);
PPFrame = NULL;
_snprintf(ErrorMsg, MsgSize, "Failed to allocate picture");
return 4;
}
FinalFrame = PPFrame;
return 0;
}
AVFrameLite *VideoBase::OutputFrame(AVFrame *Frame) {
if (PPContext) {
pp_postprocess(const_cast<const uint8_t **>(Frame->data), Frame->linesize, PPFrame->data, PPFrame->linesize, VP.Width, VP.Height, Frame->qscale_table, Frame->qstride, PPMode, PPContext, Frame->pict_type | (Frame->qscale_type ? PP_PICT_TYPE_QP2 : 0));
PPFrame->key_frame = Frame->key_frame;
PPFrame->pict_type = Frame->pict_type;
}
if (SWS) {
sws_scale(SWS, PPFrame->data, PPFrame->linesize, 0, VP.Height, FinalFrame->data, FinalFrame->linesize);
FinalFrame->key_frame = PPFrame->key_frame;
FinalFrame->pict_type = PPFrame->pict_type;
}
return reinterpret_cast<AVFrameLite *>(FinalFrame);
}
VideoBase::VideoBase() {
memset(&VP, 0, sizeof(VP));
PPContext = NULL;
PPMode = NULL;
SWS = NULL;
LastFrameNum = -1;
CurrentFrame = 0;
CodecContext = NULL;
DecodeFrame = avcodec_alloc_frame();
PPFrame = DecodeFrame;
FinalFrame = PPFrame;
}
VideoBase::~VideoBase() {
if (PPMode)
pp_free_mode(PPMode);
if (PPContext)
pp_free_context(PPContext);
if (SWS)
sws_freeContext(SWS);
if (FinalFrame != PPFrame) {
avpicture_free((AVPicture *)FinalFrame);
av_free(FinalFrame);
}
if (PPFrame != DecodeFrame) {
avpicture_free((AVPicture *)PPFrame);
av_free(PPFrame);
}
av_free(DecodeFrame);
}
AVFrameLite *VideoBase::GetFrameByTime(double Time, char *ErrorMsg, unsigned MsgSize) {
int Frame = Frames.ClosestFrameFromDTS((Time * 1000 * Frames.TB.Den) / Frames.TB.Num);
return GetFrame(Frame, ErrorMsg, MsgSize);
}
int VideoBase::SetOutputFormat(int TargetFormats, int Width, int Height, char *ErrorMsg, unsigned MsgSize) {
// FIXME: investigate the possible bug in avcodec_find_best_pix_fmt
// int Loss;
// int OutputFormat = avcodec_find_best_pix_fmt(TargetFormats,
// CodecContext->pix_fmt, 1 /* Required to prevent pointless RGB32 => RGB24 conversion */, &Loss);
// if (OutputFormat == -1)
// return -1;
int OutputFormat = TargetFormats;
SwsContext *NewSWS = NULL;
if (CodecContext->pix_fmt != OutputFormat || Width != CodecContext->width || Height != CodecContext->height) {
NewSWS = sws_getContext(CodecContext->width, CodecContext->height, CodecContext->pix_fmt, Width, Height,
OutputFormat, GetCPUFlags() | SWS_BICUBIC, NULL, NULL, NULL);
if (NewSWS == NULL) {
_snprintf(ErrorMsg, MsgSize, "Failed to allocate SWScale context");
return 1;
}
}
if (SWS)
sws_freeContext(SWS);
SWS = NewSWS;
VP.Height = Height;
VP.Width = Width;
VP.PixelFormat = OutputFormat;
// FIXME: In theory the allocations in this part could fail just like in InitPP but whatever
if (FinalFrame != PPFrame) {
avpicture_free((AVPicture *)FinalFrame);
av_free(FinalFrame);
}
if (SWS) {
FinalFrame = avcodec_alloc_frame();
avpicture_alloc((AVPicture *)FinalFrame, VP.PixelFormat, VP.Width, VP.Height);
} else {
FinalFrame = PPFrame;
}
return 0;
}
void VideoBase::ResetOutputFormat() {
if (SWS)
sws_freeContext(SWS);
SWS = NULL;
VP.Height = CodecContext->height;
VP.Width = CodecContext->width;
VP.PixelFormat = CodecContext->pix_fmt;
}
void FFVideoSource::Free(bool CloseCodec) {
if (CloseCodec)
avcodec_close(CodecContext);
av_close_input_file(FormatContext);
// how was it allocated? how was it deallocate? nobody knows
//av_free(FormatContext);
}
FFVideoSource::FFVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices,
const char *PP, int Threads, int SeekMode, char *ErrorMsg, unsigned MsgSize) {
FormatContext = NULL;
AVCodec *Codec = NULL;
this->SeekMode = SeekMode;
VideoTrack = Track;
Frames = (*TrackIndices)[VideoTrack];
if (Frames.size() == 0) {
_snprintf(ErrorMsg, MsgSize, "Video track contains no frames");
throw ErrorMsg;
}
if (av_open_input_file(&FormatContext, SourceFile, NULL, 0, NULL) != 0) {
_snprintf(ErrorMsg, MsgSize, "Couldn't open '%s'", SourceFile);
throw ErrorMsg;
}
if (av_find_stream_info(FormatContext) < 0) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Couldn't find stream information");
throw ErrorMsg;
}
if (SeekMode >= 0 && av_seek_frame(FormatContext, VideoTrack, Frames[0].DTS, AVSEEK_FLAG_BACKWARD) < 0) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Video track is unseekable");
throw ErrorMsg;
}
CodecContext = FormatContext->streams[VideoTrack]->codec;
CodecContext->thread_count = Threads;
Codec = avcodec_find_decoder(CodecContext->codec_id);
if (Codec == NULL) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Video codec not found");
throw ErrorMsg;
}
if (avcodec_open(CodecContext, Codec) < 0) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Could not open video codec");
throw ErrorMsg;
}
// Always try to decode a frame to make sure all required parameters are known
int64_t Dummy;
if (DecodeNextFrame(DecodeFrame, &Dummy, ErrorMsg, MsgSize)) {
Free(true);
throw ErrorMsg;
}
//VP.image_type = VideoInfo::IT_TFF;
VP.Width = CodecContext->width;
VP.Height = CodecContext->height;
VP.FPSDenominator = FormatContext->streams[VideoTrack]->time_base.num;
VP.FPSNumerator = FormatContext->streams[VideoTrack]->time_base.den;
VP.NumFrames = Frames.size();
VP.PixelFormat = CodecContext->pix_fmt;
VP.FirstTime = ((Frames.front().DTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000;
VP.LastTime = ((Frames.back().DTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000;
if (VP.Width <= 0 || VP.Height <= 0) {
Free(true);
_snprintf(ErrorMsg, MsgSize, "Codec returned zero size video");
throw ErrorMsg;
}
// sanity check framerate
if (VP.FPSDenominator > VP.FPSNumerator || VP.FPSDenominator <= 0 || VP.FPSNumerator <= 0) {
VP.FPSDenominator = 1;
VP.FPSNumerator = 30;
}
if (InitPP(PP, CodecContext->pix_fmt, ErrorMsg, MsgSize)) {
Free(true);
throw ErrorMsg;
}
// Adjust framerate to match the duration of the first frame
if (Frames.size() >= 2) {
unsigned int DTSDiff = (unsigned int)FFMAX(Frames[1].DTS - Frames[0].DTS, 1);
VP.FPSDenominator *= DTSDiff;
}
// Cannot "output" to PPFrame without doing all other initialization
// This is the additional mess required for seekmode=-1 to work in a reasonable way
OutputFrame(DecodeFrame);
LastFrameNum = 0;
// Set AR variables
VP.SARNum = CodecContext->sample_aspect_ratio.num;
VP.SARDen = CodecContext->sample_aspect_ratio.den;
}
FFVideoSource::~FFVideoSource() {
Free(true);
}
int FFVideoSource::DecodeNextFrame(AVFrame *AFrame, int64_t *AStartTime, char *ErrorMsg, unsigned MsgSize) {
AVPacket Packet;
int FrameFinished = 0;
*AStartTime = -1;
while (av_read_frame(FormatContext, &Packet) >= 0) {
if (Packet.stream_index == VideoTrack) {
if (*AStartTime < 0)
*AStartTime = Packet.dts;
avcodec_decode_video(CodecContext, AFrame, &FrameFinished, Packet.data, Packet.size);
}
av_free_packet(&Packet);
if (FrameFinished)
goto Done;
}
// Flush the last frames
if (CodecContext->has_b_frames)
avcodec_decode_video(CodecContext, AFrame, &FrameFinished, NULL, 0);
if (!FrameFinished)
goto Error;
// Ignore errors for now
Error:
Done:
return 0;
}
AVFrameLite *FFVideoSource::GetFrame(int n, char *ErrorMsg, unsigned MsgSize) {
// PPFrame always holds frame LastFrameNum even if no PP is applied
if (LastFrameNum == n)
return OutputFrame(DecodeFrame);
bool HasSeeked = false;
if (SeekMode >= 0) {
int ClosestKF = Frames.FindClosestKeyFrame(n);
if (SeekMode == 0) {
if (n < CurrentFrame) {
av_seek_frame(FormatContext, VideoTrack, Frames[0].DTS, AVSEEK_FLAG_BACKWARD);
avcodec_flush_buffers(CodecContext);
CurrentFrame = 0;
}
} else {
// 10 frames is used as a margin to prevent excessive seeking since the predicted best keyframe isn't always selected by avformat
if (n < CurrentFrame || ClosestKF > CurrentFrame + 10 || (SeekMode == 3 && n > CurrentFrame + 10)) {
av_seek_frame(FormatContext, VideoTrack, (SeekMode == 3) ? Frames[n].DTS : Frames[ClosestKF].DTS, AVSEEK_FLAG_BACKWARD);
avcodec_flush_buffers(CodecContext);
HasSeeked = true;
}
}
} else if (n < CurrentFrame) {
_snprintf(ErrorMsg, MsgSize, "Non-linear access attempted");
return NULL;
}
do {
int64_t StartTime;
if (DecodeNextFrame(DecodeFrame, &StartTime, ErrorMsg, MsgSize))
return NULL;
if (HasSeeked) {
HasSeeked = false;
// Is the seek destination time known? Does it belong to a frame?
if (StartTime < 0 || (CurrentFrame = Frames.FrameFromDTS(StartTime)) < 0) {
switch (SeekMode) {
case 1:
_snprintf(ErrorMsg, MsgSize, "Frame accurate seeking is not possible in this file");
return NULL;
case 2:
case 3:
CurrentFrame = Frames.ClosestFrameFromDTS(StartTime);
break;
default:
_snprintf(ErrorMsg, MsgSize, "Failed assertion");
return NULL;
}
}
}
CurrentFrame++;
} while (CurrentFrame <= n);
LastFrameNum = n;
return OutputFrame(DecodeFrame);
}
void MatroskaVideoSource::Free(bool CloseCodec) {
if (CS)
cs_Destroy(CS);
if (MC.ST.fp) {
mkv_Close(MF);
fclose(MC.ST.fp);
}
if (CloseCodec)
avcodec_close(CodecContext);
av_free(CodecContext);
}
MatroskaVideoSource::MatroskaVideoSource(const char *SourceFile, int Track,
FrameIndex *TrackIndices, const char *PP,
int Threads, char *ErrorMsg, unsigned MsgSize) {
AVCodec *Codec = NULL;
CodecContext = NULL;
TrackInfo *TI = NULL;
CS = NULL;
VideoTrack = Track;
Frames = (*TrackIndices)[VideoTrack];
if (Frames.size() == 0) {
_snprintf(ErrorMsg, MsgSize, "Video track contains no frames");
throw ErrorMsg;
}
MC.ST.fp = fopen(SourceFile, "rb");
if (MC.ST.fp == NULL) {
_snprintf(ErrorMsg, MsgSize, "Can't open '%s': %s", SourceFile, strerror(errno));
throw ErrorMsg;
}
setvbuf(MC.ST.fp, NULL, _IOFBF, CACHESIZE);
MF = mkv_OpenEx(&MC.ST.base, 0, 0, ErrorMessage, sizeof(ErrorMessage));
if (MF == NULL) {
fclose(MC.ST.fp);
_snprintf(ErrorMsg, MsgSize, "Can't parse Matroska file: %s", ErrorMessage);
throw ErrorMsg;
}
mkv_SetTrackMask(MF, ~(1 << VideoTrack));
TI = mkv_GetTrackInfo(MF, VideoTrack);
if (TI->CompEnabled) {
CS = cs_Create(MF, VideoTrack, ErrorMessage, sizeof(ErrorMessage));
if (CS == NULL) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Can't create decompressor: %s", ErrorMessage);
throw ErrorMsg;
}
}
CodecContext = avcodec_alloc_context();
CodecContext->extradata = (uint8_t *)TI->CodecPrivate;
CodecContext->extradata_size = TI->CodecPrivateSize;
CodecContext->thread_count = Threads;
Codec = avcodec_find_decoder(MatroskaToFFCodecID(TI->CodecID, TI->CodecPrivate));
if (Codec == NULL) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Video codec not found");
throw ErrorMsg;
}
if (avcodec_open(CodecContext, Codec) < 0) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Could not open video codec");
throw ErrorMsg;
}
// Always try to decode a frame to make sure all required parameters are known
int64_t Dummy;
if (DecodeNextFrame(DecodeFrame, &Dummy, ErrorMsg, MsgSize)) {
Free(true);
throw ErrorMsg;
}
VP.Width = CodecContext->width;
VP.Height = CodecContext->height;;
VP.FPSDenominator = 1;
VP.FPSNumerator = 30;
VP.NumFrames = Frames.size();
VP.PixelFormat = CodecContext->pix_fmt;
VP.FirstTime = ((Frames.front().DTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000;
VP.LastTime = ((Frames.back().DTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000;
if (VP.Width <= 0 || VP.Height <= 0) {
Free(true);
_snprintf(ErrorMsg, MsgSize, "Codec returned zero size video");
throw ErrorMsg;
}
if (InitPP(PP, CodecContext->pix_fmt, ErrorMsg, MsgSize)) {
Free(true);
throw ErrorMsg;
}
// Calculate the average framerate
if (Frames.size() >= 2) {
double DTSDiff = (double)(Frames.back().DTS - Frames.front().DTS);
VP.FPSDenominator = (unsigned int)(DTSDiff * mkv_TruncFloat(TI->TimecodeScale) / (double)1000 / (double)(VP.NumFrames - 1) + 0.5);
VP.FPSNumerator = 1000000;
}
// Output the already decoded frame so it isn't wasted
OutputFrame(DecodeFrame);
LastFrameNum = 0;
// Set AR variables
VP.SARNum = TI->AV.Video.DisplayWidth * TI->AV.Video.PixelHeight;
VP.SARDen = TI->AV.Video.DisplayHeight * TI->AV.Video.PixelWidth;
// Set crop variables
VP.CropLeft = TI->AV.Video.CropL;
VP.CropRight = TI->AV.Video.CropR;
VP.CropTop = TI->AV.Video.CropT;
VP.CropBottom = TI->AV.Video.CropB;
}
MatroskaVideoSource::~MatroskaVideoSource() {
Free(true);
}
int MatroskaVideoSource::DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime, char *ErrorMsg, unsigned MsgSize) {
int FrameFinished = 0;
*AFirstStartTime = -1;
ulonglong StartTime, EndTime, FilePos;
unsigned int Track, FrameFlags, FrameSize;
while (mkv_ReadFrame(MF, 0, &Track, &StartTime, &EndTime, &FilePos, &FrameSize, &FrameFlags) == 0) {
if (*AFirstStartTime < 0)
*AFirstStartTime = StartTime;
if (ReadFrame(FilePos, FrameSize, CS, MC, ErrorMsg, MsgSize))
return 1;
avcodec_decode_video(CodecContext, AFrame, &FrameFinished, MC.Buffer, FrameSize);
if (FrameFinished)
goto Done;
}
// Flush the last frames
if (CodecContext->has_b_frames)
avcodec_decode_video(CodecContext, AFrame, &FrameFinished, NULL, 0);
if (!FrameFinished)
goto Error;
Error:
Done:
return 0;
}
AVFrameLite *MatroskaVideoSource::GetFrame(int n, char *ErrorMsg, unsigned MsgSize) {
// PPFrame always holds frame LastFrameNum even if no PP is applied
if (LastFrameNum == n)
return OutputFrame(DecodeFrame);
bool HasSeeked = false;
if (n < CurrentFrame || Frames.FindClosestKeyFrame(n) > CurrentFrame) {
mkv_Seek(MF, Frames[n].DTS, MKVF_SEEK_TO_PREV_KEYFRAME);
avcodec_flush_buffers(CodecContext);
HasSeeked = true;
}
do {
int64_t StartTime;
if (DecodeNextFrame(DecodeFrame, &StartTime, ErrorMsg, MsgSize))
return NULL;
if (HasSeeked) {
HasSeeked = false;
if (StartTime < 0 || (CurrentFrame = Frames.FrameFromDTS(StartTime)) < 0) {
_snprintf(ErrorMsg, MsgSize, "Frame accurate seeking is not possible in this file");
return NULL;
}
}
CurrentFrame++;
} while (CurrentFrame <= n);
LastFrameNum = n;
return OutputFrame(DecodeFrame);
}
#ifdef HAALITS
void HaaliTSVideoSource::Free(bool CloseCodec) {
if (CloseCodec)
avcodec_close(CodecContext);
av_free(CodecContext);
}
HaaliTSVideoSource::HaaliTSVideoSource(const char *SourceFile, int Track,
FrameIndex *TrackIndices, const char *PP,
int Threads, char *ErrorMsg, unsigned MsgSize) {
AVCodec *Codec = NULL;
CodecContext = NULL;
VideoTrack = Track;
Frames = (*TrackIndices)[VideoTrack];
if (Frames.size() == 0) {
_snprintf(ErrorMsg, MsgSize, "Video track contains no frames");
throw ErrorMsg;
}
::CoInitializeEx(NULL, COINIT_MULTITHREADED);
CLSID clsid = Haali_TS_Parser;
if (FAILED(pMMC.CoCreateInstance(clsid))) {
_snprintf(ErrorMsg, MsgSize, "Can't create parser");
throw ErrorMsg;
}
CComPtr<IMemAlloc> pMA;
if (FAILED(pMA.CoCreateInstance(CLSID_MemAlloc))) {
_snprintf(ErrorMsg, MsgSize, "Can't create memory allocator");
throw ErrorMsg;
}
CComPtr<IMMStream> pMS;
if (FAILED(pMS.CoCreateInstance(CLSID_DiskFile))) {
_snprintf(ErrorMsg, MsgSize, "Can't create disk file reader");
throw ErrorMsg;
}
WCHAR WSourceFile[2048];
mbstowcs(WSourceFile, SourceFile, 2000);
CComQIPtr<IMMStreamOpen> pMSO(pMS);
if (FAILED(pMSO->Open(WSourceFile))) {
_snprintf(ErrorMsg, MsgSize, "Can't open file");
throw ErrorMsg;
}
if (FAILED(pMMC->Open(pMS, 0, NULL, pMA))) {
_snprintf(ErrorMsg, MsgSize, "Can't parse file");
throw ErrorMsg;
}
BSTR CodecID = NULL;
uint8_t * CodecPrivate = NULL;
int CodecPrivateSize = 0;
int CurrentTrack = 0;
CComPtr<IEnumUnknown> pEU;
if (SUCCEEDED(pMMC->EnumTracks(&pEU))) {
CComPtr<IUnknown> pU;
while (pEU->Next(1, &pU, NULL) == S_OK) {
if (CurrentTrack++ == Track) {
CComQIPtr<IPropertyBag> pBag = pU;
if (pBag) {
VARIANT pV;
pV.vt = VT_EMPTY;
if (pBag->Read(L"CodecID", &pV, NULL) == S_OK)
CodecID = pV.bstrVal;
pV.vt = VT_EMPTY;
if (pBag->Read(L"CodecPrivate", &pV, NULL) == S_OK) {
CodecPrivate = (uint8_t *)pV.parray->pvData;
CodecPrivateSize = pV.parray->cbElements;
}
}
}
pU = NULL;
}
}
CodecContext = avcodec_alloc_context();
CodecContext->extradata = CodecPrivate;
CodecContext->extradata_size = CodecPrivateSize;
CodecContext->thread_count = Threads;
char ACodecID[2048];
wcstombs(ACodecID, CodecID, 2000);
Codec = avcodec_find_decoder(MatroskaToFFCodecID(ACodecID, CodecPrivate));
if (Codec == NULL) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Video codec not found");
throw ErrorMsg;
}
if (avcodec_open(CodecContext, Codec) < 0) {
Free(false);
_snprintf(ErrorMsg, MsgSize, "Could not open video codec");
throw ErrorMsg;
}
// Always try to decode a frame to make sure all required parameters are known
int64_t Dummy;
if (DecodeNextFrame(DecodeFrame, &Dummy, ErrorMsg, MsgSize)) {
Free(true);
throw ErrorMsg;
}
VP.Width = CodecContext->width;
VP.Height = CodecContext->height;;
VP.FPSDenominator = 1;
VP.FPSNumerator = 30;
VP.NumFrames = Frames.size();
VP.PixelFormat = CodecContext->pix_fmt;
VP.FirstTime = ((Frames.front().DTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000;
VP.LastTime = ((Frames.back().DTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000;
if (VP.Width <= 0 || VP.Height <= 0) {
Free(true);
_snprintf(ErrorMsg, MsgSize, "Codec returned zero size video");
throw ErrorMsg;
}
if (InitPP(PP, CodecContext->pix_fmt, ErrorMsg, MsgSize)) {
Free(true);
throw ErrorMsg;
}
// Calculate the average framerate
if (Frames.size() >= 2) {
double DTSDiff = (double)(Frames.back().DTS - Frames.front().DTS);
// FIXME
VP.FPSDenominator = (unsigned int)((DTSDiff * 1000000000) / (double)1000 / (double)(VP.NumFrames - 1) + 0.5);
VP.FPSNumerator = 1000000;
}
// Output the already decoded frame so it isn't wasted
OutputFrame(DecodeFrame);
LastFrameNum = 0;
// Set AR variables
// VP.SARNum = TI->AV.Video.DisplayWidth * TI->AV.Video.PixelHeight;
// VP.SARDen = TI->AV.Video.DisplayHeight * TI->AV.Video.PixelWidth;
// Set crop variables
// VP.CropLeft = TI->AV.Video.CropL;
// VP.CropRight = TI->AV.Video.CropR;
// VP.CropTop = TI->AV.Video.CropT;
// VP.CropBottom = TI->AV.Video.CropB;
}
HaaliTSVideoSource::~HaaliTSVideoSource() {
Free(true);
}
int HaaliTSVideoSource::DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime, char *ErrorMsg, unsigned MsgSize) {
int FrameFinished = 0;
*AFirstStartTime = -1;
for (;;) {
CComPtr<IMMFrame> pMMF;
if (pMMC->ReadFrame(NULL, &pMMF) != S_OK)
break;
REFERENCE_TIME Ts, Te;
if (*AFirstStartTime < 0 && SUCCEEDED(pMMF->GetTime(&Ts, &Te)))
*AFirstStartTime = Ts;
if (pMMF->GetTrack() == VideoTrack) {
BYTE *Data = NULL;
if (FAILED(pMMF->GetPointer(&Data)))
goto Error;
avcodec_decode_video(CodecContext, AFrame, &FrameFinished, Data, pMMF->GetActualDataLength());
if (FrameFinished)
goto Done;
}
}
// Flush the last frames
if (CodecContext->has_b_frames)
avcodec_decode_video(CodecContext, AFrame, &FrameFinished, NULL, 0);
if (!FrameFinished)
goto Error;
Error:
Done:
return 0;
}
AVFrameLite *HaaliTSVideoSource::GetFrame(int n, char *ErrorMsg, unsigned MsgSize) {
// PPFrame always holds frame LastFrameNum even if no PP is applied
if (LastFrameNum == n)
return OutputFrame(DecodeFrame);
bool HasSeeked = false;
if (n < CurrentFrame || Frames.FindClosestKeyFrame(n) > CurrentFrame) {
int64_t dtsp = Frames[n].DTS;
pMMC->Seek(Frames[n].DTS, MMSF_PREV_KF);
// FIXME for some reason required to make it seek properly
//avcodec_flush_buffers(CodecContext);
HasSeeked = true;
}
do {
int64_t StartTime;
if (DecodeNextFrame(DecodeFrame, &StartTime, ErrorMsg, MsgSize))
return NULL;
if (HasSeeked) {
HasSeeked = false;
if (StartTime < 0 || (CurrentFrame = Frames.FrameFromDTS(StartTime)) < 0) {
_snprintf(ErrorMsg, MsgSize, "Frame accurate seeking is not possible in this file\n");
return NULL;
}
}
CurrentFrame++;
} while (CurrentFrame <= n);
LastFrameNum = n;
return OutputFrame(DecodeFrame);
}
#endif // HAALITS

View File

@ -1,120 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFVIDEOSOURCE_H
#define FFVIDEOSOURCE_H
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libpostproc/postprocess.h>
}
#include <vector>
#include "indexing.h"
#include "utils.h"
#include "ffms.h"
#ifdef HAALITS
# define _WIN32_DCOM
# include <windows.h>
# include <tchar.h>
# include <atlbase.h>
# include <dshow.h>
# include "CoParser.h"
# include <initguid.h>
# include "guids.h"
#endif
class VideoBase {
private:
pp_context_t *PPContext;
pp_mode_t *PPMode;
SwsContext *SWS;
protected:
VideoProperties VP;
AVFrame *DecodeFrame;
AVFrame *PPFrame;
AVFrame *FinalFrame;
int LastFrameNum;
FrameInfoVector Frames;
int VideoTrack;
int CurrentFrame;
AVCodecContext *CodecContext;
VideoBase();
int InitPP(const char *PP, int PixelFormat, char *ErrorMsg, unsigned MsgSize);
AVFrameLite *OutputFrame(AVFrame *Frame);
public:
virtual ~VideoBase();
const VideoProperties& GetVideoProperties() { return VP; }
FrameInfoVector *GetFrameInfoVector() { return &Frames; }
virtual AVFrameLite *GetFrame(int n, char *ErrorMsg, unsigned MsgSize) = 0;
AVFrameLite *GetFrameByTime(double Time, char *ErrorMsg, unsigned MsgSize);
int SetOutputFormat(int TargetFormats, int Width, int Height, char *ErrorMsg, unsigned MsgSize);
void ResetOutputFormat();
};
class FFVideoSource : public VideoBase {
private:
AVFormatContext *FormatContext;
int SeekMode;
void Free(bool CloseCodec);
int DecodeNextFrame(AVFrame *Frame, int64_t *DTS, char *ErrorMsg, unsigned MsgSize);
public:
FFVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, const char *PP, int Threads, int SeekMode, char *ErrorMsg, unsigned MsgSize);
~FFVideoSource();
AVFrameLite *GetFrame(int n, char *ErrorMsg, unsigned MsgSize);
};
class MatroskaVideoSource : public VideoBase {
private:
MatroskaFile *MF;
MatroskaReaderContext MC;
CompressedStream *CS;
char ErrorMessage[256];
void Free(bool CloseCodec);
int DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime, char *ErrorMsg, unsigned MsgSize);
public:
MatroskaVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, const char *PP, int Threads, char *ErrorMsg, unsigned MsgSize);
~MatroskaVideoSource();
AVFrameLite *GetFrame(int n, char *ErrorMsg, unsigned MsgSize);
};
#ifdef HAALITS
class HaaliTSVideoSource : public VideoBase {
private:
CComPtr<IMMContainer> pMMC;
void Free(bool CloseCodec);
int DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime, char *ErrorMsg, unsigned MsgSize);
public:
HaaliTSVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, const char *PP, int Threads, char *ErrorMsg, unsigned MsgSize);
~HaaliTSVideoSource();
AVFrameLite *GetFrame(int n, char *ErrorMsg, unsigned MsgSize);
};
#endif // HAALITS
#endif

View File

@ -1,798 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include <iostream>
#include <fstream>
#include <set>
#include <algorithm>
#include <memory>
#include <errno.h>
#include "indexing.h"
#include "wave64writer.h"
#ifdef __UNIX__
#define _fseeki64 fseeko
#define _ftelli64 ftello
#define _snprintf snprintf
#endif
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include "MatroskaParser.h"
#include "stdiostream.h"
}
#ifdef _WIN32
# define _WIN32_DCOM
# include <windows.h>
# include <tchar.h>
# include <atlbase.h>
# include <dshow.h>
# include "CoParser.h"
# include <initguid.h>
# include "guids.h"
#endif
class MatroskaAudioContext {
public:
Wave64Writer *W64W;
AVCodecContext *CTX;
CompressedStream *CS;
int64_t CurrentSample;
MatroskaAudioContext() {
W64W = NULL;
CTX = NULL;
CS = NULL;
CurrentSample = 0;
}
~MatroskaAudioContext() {
delete W64W;
if (CTX) {
avcodec_close(CTX);
av_free(CTX);
}
if (CS)
cs_Destroy(CS);
}
};
class FFAudioContext {
public:
Wave64Writer *W64W;
AVCodecContext *CTX;
int64_t CurrentSample;
FFAudioContext() {
W64W = NULL;
CTX = NULL;
CurrentSample = 0;
}
~FFAudioContext() {
delete W64W;
if (CTX)
avcodec_close(CTX);
}
};
#ifdef HAALITS
class HaaliTSIndexMemory {
private:
int16_t *DecodingBuffer;
MatroskaAudioContext *AudioContexts;
public:
HaaliTSIndexMemory(int Tracks, int16_t *&DecodingBuffer, MatroskaAudioContext *&AudioContexts) {
DecodingBuffer = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE*10];
AudioContexts = new MatroskaAudioContext[Tracks];
this->DecodingBuffer = DecodingBuffer;
this->AudioContexts = AudioContexts;
}
~HaaliTSIndexMemory() {
delete [] DecodingBuffer;
delete [] AudioContexts;
}
};
#endif
class MatroskaIndexMemory {
private:
int16_t *DecodingBuffer;
MatroskaAudioContext *AudioContexts;
MatroskaFile *MF;
MatroskaReaderContext *MC;
public:
MatroskaIndexMemory(int Tracks, int16_t *&DecodingBuffer, MatroskaAudioContext *&AudioContexts, MatroskaFile *MF, MatroskaReaderContext *MC) {
DecodingBuffer = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE*10];
AudioContexts = new MatroskaAudioContext[Tracks];
this->DecodingBuffer = DecodingBuffer;
this->AudioContexts = AudioContexts;
this->MF = MF;
this->MC = MC;
}
~MatroskaIndexMemory() {
delete [] DecodingBuffer;
delete [] AudioContexts;
mkv_Close(MF);
fclose(MC->ST.fp);
}
};
class FFIndexMemory {
private:
int16_t *DecodingBuffer;
FFAudioContext *AudioContexts;
AVFormatContext *FormatContext;
public:
FFIndexMemory(int Tracks, int16_t *&DecodingBuffer, FFAudioContext *&AudioContexts, AVFormatContext *&FormatContext) {
DecodingBuffer = new int16_t[AVCODEC_MAX_AUDIO_FRAME_SIZE*10];
AudioContexts = new FFAudioContext[Tracks];
this->DecodingBuffer = DecodingBuffer;
this->AudioContexts = AudioContexts;
this->FormatContext = FormatContext;
}
~FFIndexMemory() {
delete [] DecodingBuffer;
delete [] AudioContexts;
av_close_input_file(FormatContext);
}
};
static bool DTSComparison(FrameInfo FI1, FrameInfo FI2) {
return FI1.DTS < FI2.DTS;
}
static void SortTrackIndices(FrameIndex *TrackIndices) {
for (FrameIndex::iterator Cur=TrackIndices->begin(); Cur!=TrackIndices->end(); Cur++)
std::sort(Cur->begin(), Cur->end(), DTSComparison);
}
int WriteIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize) {
std::ofstream Index(IndexFile, std::ios::out | std::ios::binary | std::ios::trunc);
if (!Index.is_open()) {
_snprintf(ErrorMsg, MsgSize, "Failed to open '%s' for writing", IndexFile);
return 1;
}
// Write the index file header
IndexHeader IH;
IH.Id = INDEXID;
IH.Version = INDEXVERSION;
IH.Tracks = TrackIndices->size();
IH.Decoder = TrackIndices->Decoder;
Index.write(reinterpret_cast<char *>(&IH), sizeof(IH));
for (unsigned int i = 0; i < IH.Tracks; i++) {
int TT = (*TrackIndices)[i].TT;
Index.write(reinterpret_cast<char *>(&TT), sizeof(TT));
int Num = (*TrackIndices)[i].TB.Num;
Index.write(reinterpret_cast<char *>(&Num), sizeof(Num));
int Den = (*TrackIndices)[i].TB.Den;
Index.write(reinterpret_cast<char *>(&Den), sizeof(Den));
size_t Frames = (*TrackIndices)[i].size();
Index.write(reinterpret_cast<char *>(&Frames), sizeof(Frames));
for (size_t j = 0; j < Frames; j++)
Index.write(reinterpret_cast<char *>(&(TrackIndices->at(i)[j])), sizeof(FrameInfo));
}
return 0;
}
#ifdef HAALITS
static FrameIndex *MakeHaaliTSIndex(const char *SourceFile, int IndexMask, int DumpMask, const char *AudioFile, bool IgnoreDecodeErrors, IndexCallback IP, void *Private, char *ErrorMsg, unsigned MsgSize) {
::CoInitializeEx(NULL, COINIT_MULTITHREADED);
CLSID clsid = Haali_TS_Parser;
CComPtr<IMMContainer> pMMC;
if (FAILED(pMMC.CoCreateInstance(clsid))) {
_snprintf(ErrorMsg, MsgSize, "Can't create parser");
return NULL;
}
CComPtr<IMemAlloc> pMA;
if (FAILED(pMA.CoCreateInstance(CLSID_MemAlloc))) {
_snprintf(ErrorMsg, MsgSize, "Can't create memory allocator");
return NULL;
}
CComPtr<IMMStream> pMS;
if (FAILED(pMS.CoCreateInstance(CLSID_DiskFile))) {
_snprintf(ErrorMsg, MsgSize, "Can't create disk file reader");
return NULL;
}
WCHAR WSourceFile[2048];
mbstowcs(WSourceFile, SourceFile, 2000);
CComQIPtr<IMMStreamOpen> pMSO(pMS);
if (FAILED(pMSO->Open(WSourceFile))) {
_snprintf(ErrorMsg, MsgSize, "Can't open file");
return NULL;
}
if (FAILED(pMMC->Open(pMS, 0, NULL, pMA))) {
_snprintf(ErrorMsg, MsgSize, "Can't parse file");
return NULL;
}
int NumTracks = 0;
CComPtr<IEnumUnknown> pEU;
if (SUCCEEDED(pMMC->EnumTracks(&pEU))) {
CComPtr<IUnknown> pU;
while (pEU->Next(1, &pU, NULL) == S_OK) {
NumTracks++;
pU = NULL;
}
}
// Audio stuff
int16_t *db;
MatroskaAudioContext *AudioContexts;
HaaliTSIndexMemory IM = HaaliTSIndexMemory(NumTracks, db, AudioContexts);
FrameIndex *TrackIndices = new FrameIndex();
TrackIndices->Decoder = 2;
int TrackTypes[32];
int CurrentTrack = 0;
pEU = NULL;
if (SUCCEEDED(pMMC->EnumTracks(&pEU))) {
CComPtr<IUnknown> pU;
while (pEU->Next(1, &pU, NULL) == S_OK) {
CComQIPtr<IPropertyBag> pBag = pU;
BSTR CodecID = NULL;
TrackTypes[CurrentTrack] = -200;
uint8_t * CodecPrivate = NULL;
int CodecPrivateSize = 0;
if (pBag) {
VARIANT pV;
pV.vt = VT_EMPTY;
if (pBag->Read(L"CodecID", &pV, NULL) == S_OK)
CodecID = pV.bstrVal;
pV.vt = VT_EMPTY;
if (pBag->Read(L"Type", &pV, NULL) == S_OK)
TrackTypes[CurrentTrack] = pV.uintVal;
pV.vt = VT_EMPTY;
if (pBag->Read(L"CodecPrivate", &pV, NULL) == S_OK) {
CodecPrivate = (uint8_t *)pV.parray->pvData;
CodecPrivateSize = pV.parray->cbElements;
}
}
TrackIndices->push_back(FrameInfoVector(1, 1000000000, TrackTypes[CurrentTrack] - 1));
if (IndexMask & (1 << CurrentTrack) && TrackTypes[CurrentTrack] == TT_AUDIO) {
AVCodecContext *AudioCodecContext = avcodec_alloc_context();
AudioCodecContext->extradata = CodecPrivate;
AudioCodecContext->extradata_size = CodecPrivateSize;
AudioContexts[CurrentTrack].CTX = AudioCodecContext;
char ACodecID[2048];
wcstombs(ACodecID, CodecID, 2000);
AVCodec *AudioCodec = avcodec_find_decoder(MatroskaToFFCodecID(ACodecID, NULL));
if (AudioCodec == NULL) {
av_free(AudioCodecContext);
AudioContexts[CurrentTrack].CTX = NULL;
_snprintf(ErrorMsg, MsgSize, "Audio codec not found");
return NULL;
}
if (avcodec_open(AudioCodecContext, AudioCodec) < 0) {
av_free(AudioCodecContext);
AudioContexts[CurrentTrack].CTX = NULL;
_snprintf(ErrorMsg, MsgSize, "Could not open audio codec");
return NULL;
}
} else {
IndexMask &= ~(1 << CurrentTrack);
}
pU = NULL;
CurrentTrack++;
}
}
//
for (;;) {
if (IP) {
if ((*IP)(0, 0, 1, Private)) {
_snprintf(ErrorMsg, MsgSize, "Cancelled by user");
delete TrackIndices;
return NULL;
}
}
CComPtr<IMMFrame> pMMF;
if (pMMC->ReadFrame(NULL, &pMMF) != S_OK)
break;
REFERENCE_TIME Ts, Te;
HRESULT hr = pMMF->GetTime(&Ts, &Te);
unsigned int CurrentTrack = pMMF->GetTrack();
// Only create index entries for video for now to save space
if (TrackTypes[CurrentTrack] == TT_VIDEO) {
(*TrackIndices)[CurrentTrack].push_back(FrameInfo(Ts, pMMF->IsSyncPoint() == S_OK));
} else if (TrackTypes[CurrentTrack] == TT_AUDIO && (IndexMask & (1 << CurrentTrack))) {
/* (*TrackIndices)[Track].push_back(FrameInfo(AudioContexts[Track].CurrentSample, FilePos, FrameSize, (FrameFlags & FRAME_KF) != 0));
ReadFrame(FilePos, FrameSize, AudioContexts[Track].CS, MC, ErrorMsg, MsgSize);
int Size = FrameSize;
uint8_t *Data = MC.Buffer;
AVCodecContext *AudioCodecContext = AudioContexts[Track].CTX;
while (Size > 0) {
int dbsize = AVCODEC_MAX_AUDIO_FRAME_SIZE*10;
int Ret = avcodec_decode_audio2(AudioCodecContext, db, &dbsize, Data, Size);
if (Ret < 0) {
if (IgnoreDecodeErrors) {
(*TrackIndices)[Track].clear();
IndexMask &= ~(1 << Track);
break;
} else {
_snprintf(ErrorMsg, MsgSize, "Audio decoding error");
delete TrackIndices;
return NULL;
}
}
if (Ret > 0) {
Size -= Ret;
Data += Ret;
}
if (dbsize > 0)
AudioContexts[Track].CurrentSample += (dbsize * 8) / (av_get_bits_per_sample_format(AudioCodecContext->sample_fmt) * AudioCodecContext->channels);
if (dbsize > 0 && (DumpMask & (1 << Track))) {
// Delay writer creation until after an audio frame has been decoded. This ensures that all parameters are known when writing the headers.
if (!AudioContexts[Track].W64W) {
char ABuf[50];
std::string WN(AudioFile);
int Offset = StartTime * mkv_TruncFloat(mkv_GetTrackInfo(MF, Track)->TimecodeScale) / (double)1000000;
_snprintf(ABuf, sizeof(ABuf), ".%02d.delay.%d.w64", Track, Offset);
WN += ABuf;
AudioContexts[Track].W64W = new Wave64Writer(WN.c_str(), av_get_bits_per_sample_format(AudioCodecContext->sample_fmt),
AudioCodecContext->channels, AudioCodecContext->sample_rate, AudioFMTIsFloat(AudioCodecContext->sample_fmt));
}
AudioContexts[Track].W64W->WriteData(db, dbsize);
}
}
*/
}
}
SortTrackIndices(TrackIndices);
return TrackIndices;
}
#endif
static FrameIndex *MakeMatroskaIndex(const char *SourceFile, int IndexMask, int DumpMask, const char *AudioFile, bool IgnoreDecodeErrors, IndexCallback IP, void *Private, char *ErrorMsg, unsigned MsgSize) {
MatroskaFile *MF;
char ErrorMessage[256];
MatroskaReaderContext MC;
MC.Buffer = NULL;
MC.BufferSize = 0;
InitStdIoStream(&MC.ST);
MC.ST.fp = fopen(SourceFile, "rb");
if (MC.ST.fp == NULL) {
_snprintf(ErrorMsg, MsgSize, "Can't open '%s': %s", SourceFile, strerror(errno));
return NULL;
}
setvbuf(MC.ST.fp, NULL, _IOFBF, CACHESIZE);
MF = mkv_OpenEx(&MC.ST.base, 0, 0, ErrorMessage, sizeof(ErrorMessage));
if (MF == NULL) {
fclose(MC.ST.fp);
_snprintf(ErrorMsg, MsgSize, "Can't parse Matroska file: %s", ErrorMessage);
return NULL;
}
// Audio stuff
int16_t *db;
MatroskaAudioContext *AudioContexts;
MatroskaIndexMemory IM = MatroskaIndexMemory(mkv_GetNumTracks(MF), db, AudioContexts, MF, &MC);
for (unsigned int i = 0; i < mkv_GetNumTracks(MF); i++) {
TrackInfo *TI = mkv_GetTrackInfo(MF, i);
if (IndexMask & (1 << i) && TI->Type == TT_AUDIO) {
AVCodecContext *AudioCodecContext = avcodec_alloc_context();
AudioCodecContext->extradata = (uint8_t *)TI->CodecPrivate;
AudioCodecContext->extradata_size = TI->CodecPrivateSize;
AudioContexts[i].CTX = AudioCodecContext;
if (TI->CompEnabled) {
AudioContexts[i].CS = cs_Create(MF, i, ErrorMessage, sizeof(ErrorMessage));
if (AudioContexts[i].CS == NULL) {
av_free(AudioCodecContext);
AudioContexts[i].CTX = NULL;
_snprintf(ErrorMsg, MsgSize, "Can't create decompressor: %s", ErrorMessage);
return NULL;
}
}
AVCodec *AudioCodec = avcodec_find_decoder(MatroskaToFFCodecID(TI->CodecID, TI->CodecPrivate));
if (AudioCodec == NULL) {
av_free(AudioCodecContext);
AudioContexts[i].CTX = NULL;
_snprintf(ErrorMsg, MsgSize, "Audio codec not found");
return NULL;
}
if (avcodec_open(AudioCodecContext, AudioCodec) < 0) {
av_free(AudioCodecContext);
AudioContexts[i].CTX = NULL;
_snprintf(ErrorMsg, MsgSize, "Could not open audio codec");
return NULL;
}
} else {
IndexMask &= ~(1 << i);
}
}
//
int64_t CurrentPos = _ftelli64(MC.ST.fp);
_fseeki64(MC.ST.fp, 0, SEEK_END);
int64_t SourceSize = _ftelli64(MC.ST.fp);
_fseeki64(MC.ST.fp, CurrentPos, SEEK_SET);
FrameIndex *TrackIndices = new FrameIndex();
TrackIndices->Decoder = 1;
for (unsigned int i = 0; i < mkv_GetNumTracks(MF); i++)
TrackIndices->push_back(FrameInfoVector(mkv_TruncFloat(mkv_GetTrackInfo(MF, i)->TimecodeScale), 1000000, mkv_GetTrackInfo(MF, i)->Type - 1));
ulonglong StartTime, EndTime, FilePos;
unsigned int Track, FrameFlags, FrameSize;
while (mkv_ReadFrame(MF, 0, &Track, &StartTime, &EndTime, &FilePos, &FrameSize, &FrameFlags) == 0) {
// Update progress
if (IP) {
if ((*IP)(0, _ftelli64(MC.ST.fp), SourceSize, Private)) {
_snprintf(ErrorMsg, MsgSize, "Cancelled by user");
delete TrackIndices;
return NULL;
}
}
// Only create index entries for video for now to save space
if (mkv_GetTrackInfo(MF, Track)->Type == TT_VIDEO) {
(*TrackIndices)[Track].push_back(FrameInfo(StartTime, (FrameFlags & FRAME_KF) != 0));
} else if (mkv_GetTrackInfo(MF, Track)->Type == TT_AUDIO && (IndexMask & (1 << Track))) {
(*TrackIndices)[Track].push_back(FrameInfo(AudioContexts[Track].CurrentSample, FilePos, FrameSize, (FrameFlags & FRAME_KF) != 0));
ReadFrame(FilePos, FrameSize, AudioContexts[Track].CS, MC, ErrorMsg, MsgSize);
int Size = FrameSize;
uint8_t *Data = MC.Buffer;
AVCodecContext *AudioCodecContext = AudioContexts[Track].CTX;
while (Size > 0) {
int dbsize = AVCODEC_MAX_AUDIO_FRAME_SIZE*10;
int Ret = avcodec_decode_audio2(AudioCodecContext, db, &dbsize, Data, Size);
if (Ret < 0) {
if (IgnoreDecodeErrors) {
(*TrackIndices)[Track].clear();
IndexMask &= ~(1 << Track);
break;
} else {
_snprintf(ErrorMsg, MsgSize, "Audio decoding error");
delete TrackIndices;
return NULL;
}
}
if (Ret > 0) {
Size -= Ret;
Data += Ret;
}
if (dbsize > 0)
AudioContexts[Track].CurrentSample += (dbsize * 8) / (av_get_bits_per_sample_format(AudioCodecContext->sample_fmt) * AudioCodecContext->channels);
if (dbsize > 0 && (DumpMask & (1 << Track))) {
// Delay writer creation until after an audio frame has been decoded. This ensures that all parameters are known when writing the headers.
if (!AudioContexts[Track].W64W) {
char ABuf[50];
std::string WN(AudioFile);
int Offset = StartTime * mkv_TruncFloat(mkv_GetTrackInfo(MF, Track)->TimecodeScale) / (double)1000000;
_snprintf(ABuf, sizeof(ABuf), ".%02d.delay.%d.w64", Track, Offset);
WN += ABuf;
AudioContexts[Track].W64W = new Wave64Writer(WN.c_str(), av_get_bits_per_sample_format(AudioCodecContext->sample_fmt),
AudioCodecContext->channels, AudioCodecContext->sample_rate, AudioFMTIsFloat(AudioCodecContext->sample_fmt));
}
AudioContexts[Track].W64W->WriteData(db, dbsize);
}
}
}
}
SortTrackIndices(TrackIndices);
return TrackIndices;
}
FrameIndex *MakeIndex(const char *SourceFile, int IndexMask, int DumpMask, const char *AudioFile, bool IgnoreDecodeErrors, IndexCallback IP, void *Private, char *ErrorMsg, unsigned MsgSize) {
AVFormatContext *FormatContext = NULL;
IndexMask |= DumpMask;
if (av_open_input_file(&FormatContext, SourceFile, NULL, 0, NULL) != 0) {
_snprintf(ErrorMsg, MsgSize, "Can't open '%s'", SourceFile);
return NULL;
}
// Do matroska indexing instead?
if (!strcmp(FormatContext->iformat->name, "matroska")) {
av_close_input_file(FormatContext);
return MakeMatroskaIndex(SourceFile, IndexMask, DumpMask, AudioFile, IgnoreDecodeErrors, IP, Private, ErrorMsg, MsgSize);
}
#ifdef HAALITS
// Do haali ts indexing instead?
if (!strcmp(FormatContext->iformat->name, "mpegts")) {
av_close_input_file(FormatContext);
return MakeHaaliTSIndex(SourceFile, IndexMask, DumpMask, AudioFile, IgnoreDecodeErrors, IP, Private, ErrorMsg, MsgSize);
}
#endif
if (av_find_stream_info(FormatContext) < 0) {
av_close_input_file(FormatContext);
_snprintf(ErrorMsg, MsgSize, "Couldn't find stream information");
return NULL;
}
// Audio stuff
int16_t *db;
FFAudioContext *AudioContexts;
FFIndexMemory IM = FFIndexMemory(FormatContext->nb_streams, db, AudioContexts, FormatContext);
for (unsigned int i = 0; i < FormatContext->nb_streams; i++) {
if (IndexMask & (1 << i) && FormatContext->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) {
AVCodecContext *AudioCodecContext = FormatContext->streams[i]->codec;
AVCodec *AudioCodec = avcodec_find_decoder(AudioCodecContext->codec_id);
if (AudioCodec == NULL) {
_snprintf(ErrorMsg, MsgSize, "Audio codec not found");
return NULL;
}
if (avcodec_open(AudioCodecContext, AudioCodec) < 0) {
_snprintf(ErrorMsg, MsgSize, "Could not open audio codec");
return NULL;
}
AudioContexts[i].CTX = AudioCodecContext;
} else {
IndexMask &= ~(1 << i);
}
}
//
FrameIndex *TrackIndices = new FrameIndex();
TrackIndices->Decoder = 0;
for (unsigned int i = 0; i < FormatContext->nb_streams; i++)
TrackIndices->push_back(FrameInfoVector(FormatContext->streams[i]->time_base.num * 1000,
FormatContext->streams[i]->time_base.den,
FormatContext->streams[i]->codec->codec_type));
AVPacket Packet;
while (av_read_frame(FormatContext, &Packet) >= 0) {
// Update progress
if (IP) {
if ((*IP)(0, FormatContext->pb->pos, FormatContext->file_size, Private)) {
_snprintf(ErrorMsg, MsgSize, "Cancelled by user");
delete TrackIndices;
return NULL;
}
}
// Only create index entries for video for now to save space
if (FormatContext->streams[Packet.stream_index]->codec->codec_type == CODEC_TYPE_VIDEO) {
(*TrackIndices)[Packet.stream_index].push_back(FrameInfo(Packet.dts, (Packet.flags & PKT_FLAG_KEY) ? 1 : 0));
} else if (FormatContext->streams[Packet.stream_index]->codec->codec_type == CODEC_TYPE_AUDIO && (IndexMask & (1 << Packet.stream_index))) {
(*TrackIndices)[Packet.stream_index].push_back(FrameInfo(Packet.dts, AudioContexts[Packet.stream_index].CurrentSample, (Packet.flags & PKT_FLAG_KEY) ? 1 : 0));
AVCodecContext *AudioCodecContext = FormatContext->streams[Packet.stream_index]->codec;
int Size = Packet.size;
uint8_t *Data = Packet.data;
while (Size > 0) {
int dbsize = AVCODEC_MAX_AUDIO_FRAME_SIZE*10;
int Ret = avcodec_decode_audio2(AudioCodecContext, db, &dbsize, Data, Size);
if (Ret < 0) {
if (IgnoreDecodeErrors) {
(*TrackIndices)[Packet.stream_index].clear();
IndexMask &= ~(1 << Packet.stream_index);
break;
} else {
_snprintf(ErrorMsg, MsgSize, "Audio decoding error");
delete TrackIndices;
return NULL;
}
}
if (Ret > 0) {
Size -= Ret;
Data += Ret;
}
if (dbsize > 0)
AudioContexts[Packet.stream_index].CurrentSample += (dbsize * 8) / (av_get_bits_per_sample_format(AudioCodecContext->sample_fmt) * AudioCodecContext->channels);
if (dbsize > 0 && (DumpMask & (1 << Packet.stream_index))) {
// Delay writer creation until after an audio frame has been decoded. This ensures that all parameters are known when writing the headers.
if (!AudioContexts[Packet.stream_index].W64W) {
char ABuf[50];
std::string WN(AudioFile);
int Offset = (Packet.dts * FormatContext->streams[Packet.stream_index]->time_base.num)
/ (double)(FormatContext->streams[Packet.stream_index]->time_base.den * 1000);
_snprintf(ABuf, sizeof(ABuf), ".%02d.delay.%d.w64", Packet.stream_index, Offset);
WN += ABuf;
AudioContexts[Packet.stream_index].W64W = new Wave64Writer(WN.c_str(), av_get_bits_per_sample_format(AudioCodecContext->sample_fmt),
AudioCodecContext->channels, AudioCodecContext->sample_rate, AudioFMTIsFloat(AudioCodecContext->sample_fmt));
}
AudioContexts[Packet.stream_index].W64W->WriteData(db, dbsize);
}
}
}
av_free_packet(&Packet);
}
SortTrackIndices(TrackIndices);
return TrackIndices;
}
FrameIndex *ReadIndex(const char *IndexFile, char *ErrorMsg, unsigned MsgSize) {
std::ifstream Index(IndexFile, std::ios::in | std::ios::binary);
if (!Index.is_open()) {
_snprintf(ErrorMsg, MsgSize, "Failed to open '%s' for reading", IndexFile);
return NULL;
}
// Read the index file header
IndexHeader IH;
Index.read(reinterpret_cast<char *>(&IH), sizeof(IH));
if (IH.Id != INDEXID) {
_snprintf(ErrorMsg, MsgSize, "'%s' is not a valid index file", IndexFile);
return NULL;
}
if (IH.Version != INDEXVERSION) {
_snprintf(ErrorMsg, MsgSize, "'%s' is not the expected index version", IndexFile);
return NULL;
}
FrameIndex *TrackIndices = new FrameIndex();
try {
TrackIndices->Decoder = IH.Decoder;
for (unsigned int i = 0; i < IH.Tracks; i++) {
// Read how many records belong to the current stream
int TT;
Index.read(reinterpret_cast<char *>(&TT), sizeof(TT));
int Num;
Index.read(reinterpret_cast<char *>(&Num), sizeof(Num));
int Den;
Index.read(reinterpret_cast<char *>(&Den), sizeof(Den));
size_t Frames;
Index.read(reinterpret_cast<char *>(&Frames), sizeof(Frames));
TrackIndices->push_back(FrameInfoVector(Num, Den, TT));
FrameInfo FI(0, false);
for (size_t j = 0; j < Frames; j++) {
Index.read(reinterpret_cast<char *>(&FI), sizeof(FrameInfo));
TrackIndices->at(i).push_back(FI);
}
}
} catch (...) {
delete TrackIndices;
_snprintf(ErrorMsg, MsgSize, "Unknown error while reading index information in '%s'", IndexFile);
return NULL;
}
return TrackIndices;
}
int FrameInfoVector::WriteTimecodes(const char *TimecodeFile, char *ErrorMsg, unsigned MsgSize) {
std::ofstream Timecodes(TimecodeFile, std::ios::out | std::ios::trunc);
if (!Timecodes.is_open()) {
_snprintf(ErrorMsg, MsgSize, "Failed to open '%s' for writing", TimecodeFile);
return 1;
}
Timecodes << "# timecode format v2\n";
for (iterator Cur=begin(); Cur!=end(); Cur++)
Timecodes << (int64_t)((Cur->DTS * TB.Num) / (double)TB.Den) << "\n";
return 0;
}
int FrameInfoVector::FrameFromDTS(int64_t DTS) {
for (int i = 0; i < static_cast<int>(size()); i++)
if (at(i).DTS == DTS)
return i;
return -1;
}
int FrameInfoVector::ClosestFrameFromDTS(int64_t DTS) {
int Frame = 0;
int64_t BestDiff = 0xFFFFFFFFFFFFFFLL; // big number
for (int i = 0; i < static_cast<int>(size()); i++) {
int64_t CurrentDiff = FFABS(at(i).DTS - DTS);
if (CurrentDiff < BestDiff) {
BestDiff = CurrentDiff;
Frame = i;
}
}
//int64_t tmp = at(2).DTS - at(1).DTS;
//ATLASSERT(BestDiff == 0);
return Frame;
}
int FrameInfoVector::FindClosestKeyFrame(int Frame) {
Frame = FFMIN(FFMAX(Frame, 0), size() - 1);
for (int i = Frame; i > 0; i--)
if (at(i).KeyFrame)
return i;
return 0;
}
FrameInfoVector::FrameInfoVector() {
this->TT = 0;
this->TB.Num = 0;
this->TB.Den = 0;
}
FrameInfoVector::FrameInfoVector(int Num, int Den, int TT) {
this->TT = TT;
this->TB.Num = Num;
this->TB.Den = Den;
}

View File

@ -1,61 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef INDEXING_H
#define INDEXING_H
#include <vector>
#include "utils.h"
#include "ffms.h"
#define INDEXVERSION 11
#define INDEXID 0x53920873
struct IndexHeader {
uint32_t Id;
uint32_t Version;
uint32_t Tracks;
uint32_t Decoder;
};
class FrameInfoVector : public std::vector<FrameInfo> {
public:
int TT;
TrackTimeBase TB;
int FindClosestKeyFrame(int Frame);
int FrameFromDTS(int64_t DTS);
int ClosestFrameFromDTS(int64_t DTS);
int WriteTimecodes(const char *TimecodeFile, char *ErrorMsg, unsigned MsgSize);
FrameInfoVector();
FrameInfoVector(int Num, int Den, int TT);
};
class FrameIndex : public std::vector<FrameInfoVector> {
public:
int Decoder;
};
FrameIndex *MakeIndex(const char *SourceFile, int IndexMask, int DumpMask, const char *AudioFile, bool IgnoreDecodeErrors, IndexCallback IP, void *Private, char *ErrorMsg, unsigned MsgSize);
FrameIndex *ReadIndex(const char *IndexFile, char *ErrorMsg, unsigned MsgSize);
int WriteIndex(const char *IndexFile, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize);
#endif

View File

@ -1,444 +0,0 @@
// Copyright (c) 2007-2008 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "utils.h"
#include <string.h>
#include <errno.h>
#ifdef _MSC_VER
# include <intrin.h>
#endif
#ifdef __UNIX__
#define _fseeki64 fseeko
#define _ftelli64 ftello
#define _snprintf snprintf
#endif
int GetCPUFlags() {
// FIXME Add proper feature detection when msvc isn't used
int Flags = PP_CPU_CAPS_MMX | PP_CPU_CAPS_MMX2;
#ifdef _MSC_VER
Flags = 0;
int CPUInfo[4];
__cpuid(CPUInfo, 0);
// PP and SWS defines have the same values for their defines so this actually works
if (CPUInfo[3] & (1 << 23))
Flags |= PP_CPU_CAPS_MMX;
if (CPUInfo[3] & (1 << 25))
Flags |= PP_CPU_CAPS_MMX2;
#endif
return Flags;
}
int ReadFrame(uint64_t FilePos, unsigned int &FrameSize, CompressedStream *CS, MatroskaReaderContext &Context, char *ErrorMsg, unsigned MsgSize) {
if (CS) {
char CSBuffer[4096];
unsigned int DecompressedFrameSize = 0;
cs_NextFrame(CS, FilePos, FrameSize);
for (;;) {
int ReadBytes = cs_ReadData(CS, CSBuffer, sizeof(CSBuffer));
if (ReadBytes < 0) {
_snprintf(ErrorMsg, MsgSize, "Error decompressing data: %s", cs_GetLastError(CS));
return 1;
}
if (ReadBytes == 0) {
FrameSize = DecompressedFrameSize;
return 0;
}
if (Context.BufferSize < DecompressedFrameSize + ReadBytes) {
Context.BufferSize = FrameSize;
Context.Buffer = (uint8_t *)realloc(Context.Buffer, Context.BufferSize + 16);
if (Context.Buffer == NULL) {
_snprintf(ErrorMsg, MsgSize, "Out of memory");
return 2;
}
}
memcpy(Context.Buffer + DecompressedFrameSize, CSBuffer, ReadBytes);
DecompressedFrameSize += ReadBytes;
}
} else {
if (_fseeki64(Context.ST.fp, FilePos, SEEK_SET)) {
_snprintf(ErrorMsg, MsgSize, "fseek(): %s", strerror(errno));
return 3;
}
if (Context.BufferSize < FrameSize) {
Context.BufferSize = FrameSize;
Context.Buffer = (uint8_t *)realloc(Context.Buffer, Context.BufferSize + 16);
if (Context.Buffer == NULL) {
_snprintf(ErrorMsg, MsgSize, "Out of memory");
return 4;
}
}
size_t ReadBytes = fread(Context.Buffer, 1, FrameSize, Context.ST.fp);
if (ReadBytes != FrameSize) {
if (ReadBytes == 0) {
if (feof(Context.ST.fp)) {
_snprintf(ErrorMsg, MsgSize, "Unexpected EOF while reading frame");
return 5;
} else {
_snprintf(ErrorMsg, MsgSize, "Error reading frame: %s", strerror(errno));
return 6;
}
} else {
_snprintf(ErrorMsg, MsgSize, "Short read while reading frame");
return 7;
}
_snprintf(ErrorMsg, MsgSize, "Unknown read error");
return 8;
}
return 0;
}
FrameSize = 0;
return 0;
}
bool AudioFMTIsFloat(SampleFormat FMT){
switch (FMT) {
case SAMPLE_FMT_FLT:
case SAMPLE_FMT_DBL:
return true;
default:
return false;
}
}
// used for matroska<->ffmpeg codec ID mapping to avoid Win32 dependency
typedef struct BITMAPINFOHEADER {
uint32_t biSize;
int32_t biWidth;
int32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
} BITMAPINFOHEADER;
#define MAKEFOURCC(ch0, ch1, ch2, ch3)\
((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) |\
((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 ))
CodecID MatroskaToFFCodecID(char *Codec, void *CodecPrivate) {
/* Video Codecs */
if (!strcmp(Codec, "V_MS/VFW/FOURCC")) {
// fourcc list from ffdshow
switch (((BITMAPINFOHEADER *)CodecPrivate)->biCompression) {
case MAKEFOURCC('F', 'F', 'D', 'S'):
case MAKEFOURCC('F', 'V', 'F', 'W'):
case MAKEFOURCC('X', 'V', 'I', 'D'):
case MAKEFOURCC('D', 'I', 'V', 'X'):
case MAKEFOURCC('D', 'X', '5', '0'):
case MAKEFOURCC('M', 'P', '4', 'V'):
case MAKEFOURCC('m', 'p', '4', 'v'): // This one may be my fault
case MAKEFOURCC('3', 'I', 'V', 'X'):
case MAKEFOURCC('W', 'V', '1', 'F'):
case MAKEFOURCC('F', 'M', 'P', '4'):
case MAKEFOURCC('S', 'M', 'P', '4'):
return CODEC_ID_MPEG4;
case MAKEFOURCC('D', 'I', 'V', '3'):
case MAKEFOURCC('D', 'V', 'X', '3'):
case MAKEFOURCC('M', 'P', '4', '3'):
return CODEC_ID_MSMPEG4V3;
case MAKEFOURCC('M', 'P', '4', '2'):
return CODEC_ID_MSMPEG4V2;
case MAKEFOURCC('M', 'P', '4', '1'):
return CODEC_ID_MSMPEG4V1;
case MAKEFOURCC('W', 'M', 'V', '1'):
return CODEC_ID_WMV1;
case MAKEFOURCC('W', 'M', 'V', '2'):
return CODEC_ID_WMV2;
case MAKEFOURCC('W', 'M', 'V', '3'):
return CODEC_ID_WMV3;
/*
case MAKEFOURCC('M', 'S', 'S', '1'):
case MAKEFOURCC('M', 'S', 'S', '2'):
case MAKEFOURCC('W', 'V', 'P', '2'):
case MAKEFOURCC('W', 'M', 'V', 'P'):
return CODEC_ID_WMV9_LIB;
*/
case MAKEFOURCC('W', 'V', 'C', '1'):
return CODEC_ID_VC1;
case MAKEFOURCC('V', 'P', '5', '0'):
return CODEC_ID_VP5;
case MAKEFOURCC('V', 'P', '6', '0'):
case MAKEFOURCC('V', 'P', '6', '1'):
case MAKEFOURCC('V', 'P', '6', '2'):
return CODEC_ID_VP6;
case MAKEFOURCC('V', 'P', '6', 'F'):
case MAKEFOURCC('F', 'L', 'V', '4'):
return CODEC_ID_VP6F;
case MAKEFOURCC('C', 'A', 'V', 'S'):
return CODEC_ID_CAVS;
case MAKEFOURCC('M', 'P', 'G', '1'):
case MAKEFOURCC('M', 'P', 'E', 'G'):
return CODEC_ID_MPEG2VIDEO; // not a typo
case MAKEFOURCC('M', 'P', 'G', '2'):
case MAKEFOURCC('E', 'M', '2', 'V'):
case MAKEFOURCC('M', 'M', 'E', 'S'):
return CODEC_ID_MPEG2VIDEO;
case MAKEFOURCC('H', '2', '6', '3'):
case MAKEFOURCC('S', '2', '6', '3'):
case MAKEFOURCC('L', '2', '6', '3'):
case MAKEFOURCC('M', '2', '6', '3'):
case MAKEFOURCC('U', '2', '6', '3'):
case MAKEFOURCC('X', '2', '6', '3'):
return CODEC_ID_H263;
case MAKEFOURCC('H', '2', '6', '4'):
case MAKEFOURCC('X', '2', '6', '4'):
case MAKEFOURCC('V', 'S', 'S', 'H'):
case MAKEFOURCC('D', 'A', 'V', 'C'):
case MAKEFOURCC('P', 'A', 'V', 'C'):
case MAKEFOURCC('A', 'V', 'C', '1'):
return CODEC_ID_H264;
case MAKEFOURCC('M', 'J', 'P', 'G'):
case MAKEFOURCC('L', 'J', 'P', 'G'):
case MAKEFOURCC('M', 'J', 'L', 'S'):
case MAKEFOURCC('J', 'P', 'E', 'G'): // questionable fourcc?
case MAKEFOURCC('A', 'V', 'R', 'N'):
case MAKEFOURCC('M', 'J', 'P', 'A'):
return CODEC_ID_MJPEG;
case MAKEFOURCC('D', 'V', 'S', 'D'):
case MAKEFOURCC('D', 'V', '2', '5'):
case MAKEFOURCC('D', 'V', '5', '0'):
case MAKEFOURCC('C', 'D', 'V', 'C'):
case MAKEFOURCC('C', 'D', 'V', '5'):
case MAKEFOURCC('D', 'V', 'I', 'S'):
case MAKEFOURCC('P', 'D', 'V', 'C'):
return CODEC_ID_DVVIDEO;
case MAKEFOURCC('H', 'F', 'Y', 'U'):
return CODEC_ID_HUFFYUV;
case MAKEFOURCC('F', 'F', 'V', 'H'):
return CODEC_ID_FFVHUFF;
case MAKEFOURCC('C', 'Y', 'U', 'V'):
return CODEC_ID_CYUV;
case MAKEFOURCC('A', 'S', 'V', '1'):
return CODEC_ID_ASV1;
case MAKEFOURCC('A', 'S', 'V', '2'):
return CODEC_ID_ASV2;
case MAKEFOURCC('V', 'C', 'R', '1'):
return CODEC_ID_VCR1;
case MAKEFOURCC('T', 'H', 'E', 'O'):
return CODEC_ID_THEORA;
case MAKEFOURCC('S', 'V', 'Q', '1'):
return CODEC_ID_SVQ1;
case MAKEFOURCC('S', 'V', 'Q', '3'):
return CODEC_ID_SVQ3;
case MAKEFOURCC('R', 'P', 'Z', 'A'):
return CODEC_ID_RPZA;
case MAKEFOURCC('F', 'F', 'V', '1'):
return CODEC_ID_FFV1;
case MAKEFOURCC('V', 'P', '3', '1'):
return CODEC_ID_VP3;
case MAKEFOURCC('R', 'L', 'E', '8'):
return CODEC_ID_MSRLE;
case MAKEFOURCC('M', 'S', 'Z', 'H'):
return CODEC_ID_MSZH;
case MAKEFOURCC('Z', 'L', 'I', 'B'):
return CODEC_ID_ZLIB;
case MAKEFOURCC('F', 'L', 'V', '1'):
return CODEC_ID_FLV1;
/*
case MAKEFOURCC('P', 'N', 'G', '1'):
return CODEC_ID_COREPNG;
*/
case MAKEFOURCC('M', 'P', 'N', 'G'):
return CODEC_ID_PNG;
/*
case MAKEFOURCC('A', 'V', 'I', 'S'):
return CODEC_ID_AVISYNTH;
*/
case MAKEFOURCC('C', 'R', 'A', 'M'):
return CODEC_ID_MSVIDEO1;
case MAKEFOURCC('R', 'T', '2', '1'):
return CODEC_ID_INDEO2;
case MAKEFOURCC('I', 'V', '3', '2'):
case MAKEFOURCC('I', 'V', '3', '1'):
return CODEC_ID_INDEO3;
case MAKEFOURCC('C', 'V', 'I', 'D'):
return CODEC_ID_CINEPAK;
case MAKEFOURCC('R', 'V', '1', '0'):
return CODEC_ID_RV10;
case MAKEFOURCC('R', 'V', '2', '0'):
return CODEC_ID_RV20;
case MAKEFOURCC('8', 'B', 'P', 'S'):
return CODEC_ID_8BPS;
case MAKEFOURCC('Q', 'R', 'L', 'E'):
return CODEC_ID_QTRLE;
case MAKEFOURCC('D', 'U', 'C', 'K'):
return CODEC_ID_TRUEMOTION1;
case MAKEFOURCC('T', 'M', '2', '0'):
return CODEC_ID_TRUEMOTION2;
case MAKEFOURCC('T', 'S', 'C', 'C'):
return CODEC_ID_TSCC;
case MAKEFOURCC('S', 'N', 'O', 'W'):
return CODEC_ID_SNOW;
case MAKEFOURCC('Q', 'P', 'E', 'G'):
case MAKEFOURCC('Q', '1', '_', '0'):
case MAKEFOURCC('Q', '1', '_', '1'):
return CODEC_ID_QPEG;
case MAKEFOURCC('H', '2', '6', '1'):
case MAKEFOURCC('M', '2', '6', '1'):
return CODEC_ID_H261;
case MAKEFOURCC('L', 'O', 'C', 'O'):
return CODEC_ID_LOCO;
case MAKEFOURCC('W', 'N', 'V', '1'):
return CODEC_ID_WNV1;
case MAKEFOURCC('C', 'S', 'C', 'D'):
return CODEC_ID_CSCD;
case MAKEFOURCC('Z', 'M', 'B', 'V'):
return CODEC_ID_ZMBV;
case MAKEFOURCC('U', 'L', 'T', 'I'):
return CODEC_ID_ULTI;
case MAKEFOURCC('V', 'I', 'X', 'L'):
return CODEC_ID_VIXL;
case MAKEFOURCC('A', 'A', 'S', 'C'):
return CODEC_ID_AASC;
case MAKEFOURCC('F', 'P', 'S', '1'):
return CODEC_ID_FRAPS;
default:
return CODEC_ID_NONE;
}
} else if (!strcmp(Codec, "V_MPEG4/ISO/AVC"))
return CODEC_ID_H264;
else if (!strcmp(Codec, "V_MPEG4/ISO/AP"))
return CODEC_ID_MPEG4;
else if (!strcmp(Codec, "V_MPEG4/ISO/ASP"))
return CODEC_ID_MPEG4;
else if (!strcmp(Codec, "V_MPEG4/ISO/SP"))
return CODEC_ID_MPEG4;
else if (!strcmp(Codec, "V_MPEG4/MS/V3"))
return CODEC_ID_MSMPEG4V3;
else if (!strcmp(Codec, "V_MPEG2"))
return CODEC_ID_MPEG2VIDEO;
else if (!strcmp(Codec, "V_MPEG1"))
return CODEC_ID_MPEG2VIDEO; // still not a typo
else if (!strcmp(Codec, "V_VC1"))
return CODEC_ID_VC1;
else if (!strcmp(Codec, "V_SNOW"))
return CODEC_ID_SNOW;
else if (!strcmp(Codec, "V_THEORA"))
return CODEC_ID_THEORA;
else if (!strcmp(Codec, "V_UNCOMPRESSED"))
return CODEC_ID_NONE; // bleh
else if (!strcmp(Codec, "V_QUICKTIME"))
return CODEC_ID_SVQ3; // no idea if this is right
else if (!strcmp(Codec, "V_CIPC"))
return CODEC_ID_NONE; // don't know, don't care
else if (!strncmp(Codec, "V_REAL/RV", 9)) {
switch (Codec[9]) {
case '1':
return CODEC_ID_RV10;
case '2':
return CODEC_ID_RV20;
case '3':
return CODEC_ID_RV30;
case '4':
return CODEC_ID_RV40;
default:
return CODEC_ID_NONE;
}
/* Audio Codecs */
} else if (!strcmp(Codec, "A_AC3"))
return CODEC_ID_AC3;
else if (!strcmp(Codec, "A_EAC3"))
return CODEC_ID_AC3;
else if (!strcmp(Codec, "A_MPEG/L3"))
return CODEC_ID_MP3;
else if (!strcmp(Codec, "A_MPEG/L2"))
return CODEC_ID_MP2;
else if (!strcmp(Codec, "A_MPEG/L1"))
return CODEC_ID_MP2; // correct?
else if (!strcmp(Codec, "A_DTS"))
return CODEC_ID_DTS;
else if (!strcmp(Codec, "A_PCM/INT/LIT")) {
/* FIXME
switch (TI->AV.Audio.BitDepth) {
case 8: return CODEC_ID_PCM_S8;
case 16: return CODEC_ID_PCM_S16LE;
case 24: return CODEC_ID_PCM_S24LE;
case 32: return CODEC_ID_PCM_S32LE;
default: return CODEC_ID_NONE;
}
*/
return CODEC_ID_NONE;
} else if (!strcmp(Codec, "A_PCM/INT/BIG")) {
/* FIXME
switch (TI->AV.Audio.BitDepth) {
case 8: return CODEC_ID_PCM_S8;
case 16: return CODEC_ID_PCM_S16BE;
case 24: return CODEC_ID_PCM_S24BE;
case 32: return CODEC_ID_PCM_S32BE;
default: return CODEC_ID_NONE;
}
*/
return CODEC_ID_NONE;
} else if (!strcmp(Codec, "A_PCM/FLOAT/IEEE"))
return CODEC_ID_PCM_F32LE; // only a most likely guess, may do bad things
else if (!strcmp(Codec, "A_FLAC"))
return CODEC_ID_FLAC;
else if (!strcmp(Codec, "A_MPC"))
return CODEC_ID_MUSEPACK8; // or is it CODEC_ID_MUSEPACK7? both?
else if (!strcmp(Codec, "A_TTA1"))
return CODEC_ID_TTA;
else if (!strcmp(Codec, "A_WAVPACK4"))
return CODEC_ID_WAVPACK;
else if (!strcmp(Codec, "A_VORBIS"))
return CODEC_ID_VORBIS;
else if (!strcmp(Codec, "A_REAL/14_4"))
return CODEC_ID_RA_144;
else if (!strcmp(Codec, "A_REAL/28_8"))
return CODEC_ID_RA_288;
else if (!strcmp(Codec, "A_REAL/COOK"))
return CODEC_ID_COOK;
else if (!strcmp(Codec, "A_REAL/SIPR"))
return CODEC_ID_NONE; // no sipr codec id?
else if (!strcmp(Codec, "A_REAL/ATRC"))
return CODEC_ID_ATRAC3;
else if (!strncmp(Codec, "A_AAC", 5))
return CODEC_ID_AAC;
else if (!strcmp(Codec, "A_SPEEX"))
return CODEC_ID_SPEEX;
else if (!strcmp(Codec, "A_QUICKTIME"))
return CODEC_ID_NONE; // no
else if (!strcmp(Codec, "A_MS/ACM")) {
// nothing useful here anyway?
//#include "Mmreg.h"
//((WAVEFORMATEX *)TI->CodecPrivate)->wFormatTag
return CODEC_ID_NONE;
} else {
return CODEC_ID_NONE;
}
}

View File

@ -1,63 +0,0 @@
AUTOMAKE_OPTIONS = foreign
if HAVE_UNIVCHARDET
univchardet = universalchardet
endif
if HAVE_AUTO3_LUA
auto3 = auto3
endif
if WITH_LIBASS
libass = libass
endif
if HAVE_PROVIDER_FFMPEGSOURCE
ffmpegsource = FFmpegSource2
endif
SUBDIRS = \
$(univchardet) \
$(auto3) \
$(libass) \
$(ffmpegsource) \
aegisub \
automation \
po \
desktop
osx-bundle:
@SHELL@ scripts/osx-bundle.sh @PACKAGE_TARNAME@-@PACKAGE_VERSION@ @AEGISUB_VERSION_DATA@
osx-dmg:
@SHELL@ scripts/osx-dmg.sh @PACKAGE_TARNAME@-@PACKAGE_VERSION@ "@PACKAGE_TARNAME@ @PACKAGE_VERSION@"
EXTRA_DIST = \
intltool-extract.in \
intltool-merge.in \
intltool-update.in \
config.guess \
config.sub \
depcomp \
install-sh \
missing \
INSTALL \
README \
svn_revision
# m4macros/
EXTRA_DIST += \
m4macros/check_gnu_make.m4 \
m4macros/acx_pthread.m4 \
m4macros/ac_agi.m4 \
m4macros/ax_lang_compiler_ms.m4 \
m4macros/ac_agi_mdcpucfg.m4 \
m4macros/ax_openmp.m4 \
m4macros/ax_check_gl.m4 \
m4macros/ac_flag.m4
CLEANFILES= \
intltool-extract \
intltool-merge \
intltool-update

View File

@ -1,355 +1,90 @@
AUTOMAKE_OPTIONS = foreign
SUFFIXES = .c .cpp .rc
noinst_LIBRARIES=
if BUILD_DARWIN
libosxutil_subdir = libosxutil
libosxutil_lib = libosxutil/libosxutil.a
libosxutil_ldflags = -framework CoreFoundation
if HAVE_UNIVCHARDET
univchardet = universalchardet
endif
SUBDIRS = bitmaps libresrc $(libosxutil_subdir)
AM_CXXFLAGS = -DAEGISUB -Iinclude @WX_CPPFLAGS@ @OPENMP_CXXFLAGS@ @LIBAVFORMAT_CFLAGS@ @LIBAVCODEC_CFLAGS@ @LIBSWSCALE_CFLAGS@ @LIBAVUTIL_CFLAGS@
bin_PROGRAMS = aegisub-2.1
aegisub_2_1_LDADD = libresrc/libresrc.a $(libosxutil_lib)
aegisub_2_1_CPPFLAGS = @FREETYPE_CFLAGS@
aegisub_2_1_LDFLAGS = @DEBUG_FLAGS@ @PROFILE_FLAGS@ @GL_LIBS@ @PTHREAD_LIBS@ @WX_LIBS@ @ICONV_LDFLAGS@ $(libosxutil_ldflags)
LIBS += @FREETYPE_LIBS@ @FONTCONFIG_LIBS@
if BUILD_DARWIN
aegisub_2_1_LDFLAGS += -L/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries
endif
if HAVE_ALSA
noinst_LIBRARIES += libaudio_alsa.a
libaudio_alsa_a_SOURCES = audio_player_alsa.cpp
aegisub_2_1_LDFLAGS += @ALSA_LDFLAGS@
aegisub_2_1_LDADD += libaudio_alsa.a
endif
if HAVE_PORTAUDIO
noinst_LIBRARIES += libaudio_portaudio.a
libaudio_portaudio_a_SOURCES = audio_player_portaudio.cpp
libaudio_portaudio_a_CPPFLAGS = @PORTAUDIO_CFLAGS@
aegisub_2_1_LDFLAGS += @PORTAUDIO_LDFLAGS@
aegisub_2_1_LDADD += libaudio_portaudio.a
endif
if HAVE_PULSEAUDIO
noinst_LIBRARIES += libaudio_pulseaudio.a
libaudio_pulseaudio_a_SOURCES = audio_player_pulse.cpp
libaudio_pulseaudio_a_CPPFLAGS = @LIBPULSE_CFLAGS@
aegisub_2_1_LDFLAGS += @LIBPULSE_LIBS@
aegisub_2_1_LDADD += libaudio_pulseaudio.a
endif
if HAVE_OPENAL
noinst_LIBRARIES += libaudio_openal.a
libaudio_openal_a_SOURCES = audio_player_openal.cpp
libaudio_openal_a_CPPFLAGS = @OPENAL_CFLAGS@
aegisub_2_1_LDFLAGS += @OPENAL_LIBS@
aegisub_2_1_LDADD += libaudio_openal.a
endif
if HAVE_FFMPEG
aegisub_2_1_LDFLAGS += @LIBAVFORMAT_LIBS@ @LIBAVCODEC_LIBS@ @LIBSWSCALE_LIBS@ @LIBAVUTIL_LIBS@
endif
if HAVE_PROVIDER_FFMPEG
noinst_LIBRARIES += libaudiovideo_ffmpeg.a
libaudiovideo_ffmpeg_a_SOURCES = audio_provider_lavc.cpp lavc_file.cpp video_provider_lavc.cpp lavc_keyframes.cpp
libaudiovideo_ffmpeg_a_CPPFLAGS = @LIBAVFORMAT_CFLAGS@ @LIBAVCODEC_CFLAGS@ @LIBSWSCALE_CFLAGS@ @LIBAVUTIL_CFLAGS@
aegisub_2_1_LDADD += libaudiovideo_ffmpeg.a
if WITH_LIBASS
libass = libass
endif
if HAVE_PROVIDER_FFMPEGSOURCE
noinst_LIBRARIES += libaudiovideo_ffmpegsource.a
libaudiovideo_ffmpegsource_a_SOURCES = audio_provider_ffmpegsource.cpp video_provider_ffmpegsource.cpp ffmpegsource_common.cpp
libaudiovideo_ffmpegsource_a_CPPFLAGS = @LIBAVFORMAT_CFLAGS@ @LIBAVCODEC_CFLAGS@ @LIBSWSCALE_CFLAGS@ @LIBAVUTIL_CFLAGS@ @LIBPOSTPROC_CFLAGS@
aegisub_2_1_LDADD += libaudiovideo_ffmpegsource.a ../FFmpegSource2/libffmpegsource2_aegisub.a
aegisub_2_1_LDFLAGS += @LIBPOSTPROC_LIBS@
ffmpegsource = libffms
endif
noinst_LIBRARIES += libsubtitle_provider.a
libsubtitle_provider_a_SOURCES = subtitles_provider.cpp
libsubtitle_provider_a_CPPFLAGS = @CSRI_CFLAGS@
aegisub_2_1_LDADD += libsubtitle_provider.a
SUBDIRS = \
$(univchardet) \
$(libass) \
$(ffmpegsource) \
src \
automation \
po \
desktop
if WITH_LIBASS
noinst_LIBRARIES += libsubtitle_ass.a
libsubtitle_ass_a_SOURCES = subtitles_provider_libass.cpp
libsubtitle_ass_a_CPPFLAGS = @LIBASS_CFLAGS@ @ICONV_CFLAGS@
LIBS += @LIBASS_LIBS@
aegisub_2_1_LDADD += libsubtitle_ass.a
aegisub_2_1_LDFLAGS += @FONTCONFIG_LIBS@
endif
if WITH_CSRI
noinst_LIBRARIES += libsubtitle_csri.a
libsubtitle_csri_a_SOURCES = subtitles_provider_csri.cpp
libsubtitle_csri_a_CPPFLAGS = @ICONV_CFLAGS@ @CSRI_CFLAGS@
LIBS += @CSRI_LIBS@
aegisub_2_1_LDADD += libsubtitle_csri.a
aegisub_2_1_LDFLAGS += @FONTCONFIG_LIBS@
endif
if HAVE_AUTO4_LUA
noinst_LIBRARIES += libauto4_lua.a
libauto4_lua_a_SOURCES = auto4_lua.cpp auto4_lua_assfile.cpp auto4_lua_dialog.cpp auto4_lua_scriptreader.cpp
libauto4_lua_a_CPPFLAGS = @LUA_CFLAGS@
LIBS += @LUA_LDFLAGS@
aegisub_2_1_LDADD += libauto4_lua.a
endif
if HAVE_AUTO4_PERL
noinst_LIBRARIES += libauto4_perl.a
libauto4_perl_a_SOURCES = auto4_perl.cpp auto4_perl_script.cpp auto4_perl_dialogs.cpp auto4_perl_ass.cpp auto4_perl_console.cpp auto4_perl.h auto4_perl_console.h
libauto4_perl_a_CPPFLAGS = @PERL_CFLAGS@
LIBS += @PERL_LDFLAGS@
aegisub_2_1_LDADD += libauto4_perl.a
endif
if HAVE_AUTO4_RUBY
noinst_LIBRARIES += libauto4_ruby.a
libauto4_ruby_a_SOURCES = auto4_ruby_assfile.cpp auto4_ruby.cpp auto4_ruby_dialog.cpp
libauto4_ruby_a_CPPFLAGS = @RUBY_CFLAGS@
aegisub_2_1_LDFLAGS += @RUBY_LDFLAGS@
aegisub_2_1_LDADD += libauto4_ruby.a
endif
if BUILD_DARWIN
AUTO3_LIB = ../auto3/.libs/libaegisub-auto3-2.1.0.dylib
else
AUTO3_LIB = ../auto3/.libs/libaegisub-auto3-2.1.so
endif
if HAVE_AUTO3_LUA
AUTO3_LUA = auto4_auto3.cpp
# This is a workaround top stop libtool from binging in dependency_libs which
# causes many link errors due to auto4 (lua 5.1) support.
#aegisub_2_1_LDADD += -L$(srcdir)/../auto3 -laegisub-auto3-2.1
aegisub_2_1_LDADD += ${AUTO3_LIB}
endif
if HAVE_HUNSPELL
noinst_LIBRARIES += libmisc_hunspell.a
libmisc_hunspell_a_SOURCES = spellchecker_hunspell.cpp
aegisub_2_1_LDFLAGS += @HUNSPELL_LIBS@
aegisub_2_1_LDADD += libmisc_hunspell.a
endif
if HAVE_UNIVCHARDET
noinst_LIBRARIES += libmisc_universalchardet.a
libmisc_universalchardet_a_SOURCES = charset_detect.cpp text_file_reader.cpp
libmisc_universalchardet_a_CPPFLAGS = -D_X86_
aegisub_2_1_LDADD += libmisc_universalchardet.a ../universalchardet/libuniversalchardet.a
else
UNIVCHARSET = charset_detect.cpp text_file_reader.cpp
endif
if BUILD_DARWIN
BEVEL_BUTTON = osx_bevelButton.cpp
endif
if FONTLISTER_FREETYPE
FONT_LISTER = font_file_lister_freetype.cpp
endif
if FONTLISTER_FONTCONFIG
FONT_LISTER = font_file_lister_fontconfig.cpp
endif
osx-bundle:
@SHELL@ scripts/osx-bundle.sh "Aegisub (r@SVN_REVISION@-@DARWIN_ARCH@@PACKAGE_DEBUG@)" @AEGISUB_VERSION_DATA@ DICT_DIR=$(DICT_DIR)
## These aren't built, but are listed here so 'make dist' can always find all the sources
## This should also list all Win32 specific files
EXTRA_aegisub_2_1_SOURCES = \
font_file_lister.cpp \
$(FONT_LISTER) \
audio_player_dsound.cpp \
audio_player_dsound2.cpp \
audio_player_portaudio.cpp \
audio_player_pulse.cpp \
audio_provider_avs.cpp \
audio_provider_lavc.cpp \
auto4_auto3.cpp \
auto4_lua.cpp \
auto4_lua_assfile.cpp \
auto4_lua_dialog.cpp \
auto4_lua_scriptreader.cpp \
auto4_ruby.cpp \
auto4_ruby_assfile.cpp \
auto4_ruby_dialog.cpp \
avisynth_wrap.cpp \
dialog_associations.cpp \
lavc_file.cpp \
lavc_keyframes.cpp \
osx_bevelButton.cpp \
setup.cpp \
spellchecker_hunspell.cpp \
stdwx.cpp \
subtitle_format_prs.cpp \
subtitles_provider_csri.cpp \
subtitles_provider_libass.cpp \
video_provider_avs.cpp \
video_provider_dshow.cpp \
video_provider_lavc.cpp
osx-dmg:
@SHELL@ scripts/osx-dmg.sh "Aegisub (r@SVN_REVISION@-@DARWIN_ARCH@@PACKAGE_DEBUG@)" "Aegisub (r@SVN_REVISION@-@DARWIN_ARCH@@PACKAGE_DEBUG@)"
osx-tinderbox-bundle:
@SHELL@ scripts/osx-bundle.sh "$(T_BUNDLE)" @AEGISUB_VERSION_DATA@ DICT_DIR="$(DICT_DIR)"
aegisub_2_1_SOURCES = \
$(AUTO3_LUA) \
$(FFMPEG) \
$(HUNSPELL) \
$(LIBASS) \
$(UNIVCHARSET) \
$(BEVEL_BUTTON) \
font_file_lister.cpp \
$(FONT_LISTER) \
MatroskaParser.c \
aegisublocale.cpp \
ass_attachment.cpp \
ass_dialogue.cpp \
ass_entry.cpp \
ass_export_filter.cpp \
ass_exporter.cpp \
ass_file.cpp \
ass_karaoke.cpp \
ass_override.cpp \
ass_style.cpp \
ass_style_storage.cpp \
ass_time.cpp \
audio_box.cpp \
audio_display.cpp \
audio_karaoke.cpp \
audio_player.cpp \
audio_provider.cpp \
audio_provider_convert.cpp \
audio_provider_downmix.cpp \
audio_provider_hd.cpp \
audio_provider_pcm.cpp \
audio_provider_ram.cpp \
audio_provider_stream.cpp \
audio_spectrum.cpp \
auto4_base.cpp \
avisynth_wrap.cpp \
base_grid.cpp \
browse_button.cpp \
colorspace.cpp \
colour_button.cpp \
dialog_about.cpp \
dialog_attachments.cpp \
dialog_automation.cpp \
dialog_colorpicker.cpp \
dialog_detached_video.cpp \
dialog_dummy_video.cpp \
dialog_export.cpp \
dialog_fonts_collector.cpp \
dialog_jumpto.cpp \
dialog_kanji_timer.cpp \
dialog_options.cpp \
dialog_paste_over.cpp \
dialog_progress.cpp \
dialog_properties.cpp \
dialog_resample.cpp \
dialog_search_replace.cpp \
dialog_selection.cpp \
dialog_shift_times.cpp \
dialog_spellchecker.cpp \
dialog_splash.cpp \
dialog_style_editor.cpp \
dialog_style_manager.cpp \
dialog_styling_assistant.cpp \
dialog_text_import.cpp \
dialog_timing_processor.cpp \
dialog_tip.cpp \
dialog_translation.cpp \
dialog_version_check.cpp \
dialog_video_details.cpp \
drop.cpp \
export_clean_info.cpp \
export_fixstyle.cpp \
export_framerate.cpp \
export_visible_lines.cpp \
fft.cpp \
frame_main.cpp \
frame_main_events.cpp \
gl_text.cpp \
gl_wrap.cpp \
help_button.cpp \
hilimod_textctrl.cpp \
hotkeys.cpp \
idle_field_event.cpp \
kana_table.cpp \
keyframe.cpp \
main.cpp \
md5.c \
mkv_wrap.cpp \
mythes.cxx \
options.cpp \
plugin_manager.cpp \
scintilla_text_ctrl.cpp \
spellchecker.cpp \
spline.cpp \
spline_curve.cpp \
standard_paths.cpp \
static_bmp.cpp \
string_codec.cpp \
subs_edit_box.cpp \
subs_edit_ctrl.cpp \
subs_grid.cpp \
subs_preview.cpp \
subtitle_format.cpp \
subtitle_format_ass.cpp \
subtitle_format_dvd.cpp \
subtitle_format_encore.cpp \
subtitle_format_microdvd.cpp \
subtitle_format_mkv.cpp \
subtitle_format_srt.cpp \
subtitle_format_transtation.cpp \
subtitle_format_ttxt.cpp \
subtitle_format_txt.cpp \
text_file_writer.cpp \
thesaurus.cpp \
thesaurus_myspell.cpp \
timeedit_ctrl.cpp \
toggle_bitmap.cpp \
tooltip_manager.cpp \
utils.cpp \
validators.cpp \
variable_data.cpp \
vector2d.cpp \
version.cpp \
vfr.cpp \
video_box.cpp \
video_context.cpp \
video_display.cpp \
video_frame.cpp \
video_provider_cache.cpp \
video_provider_dummy.cpp \
video_provider_manager.cpp \
video_slider.cpp \
visual_feature.cpp \
visual_tool.cpp \
visual_tool_clip.cpp \
visual_tool_cross.cpp \
visual_tool_drag.cpp \
visual_tool_rotatexy.cpp \
visual_tool_rotatez.cpp \
visual_tool_scale.cpp \
visual_tool_vector_clip.cpp
aegisub_2_1_SOURCES += \
$(srcdir)/*.h \
$(srcdir)/include/aegisub/*.h \
$(srcdir)/config/*.h
noinst_HEADERS = \
$(srcdir)/boost/*.hpp \
gl/glext.h \
$(srcdir)/*.hxx \
osx_bevelButton.h
osx-tinderbox-dmg:
@SHELL@ scripts/osx-dmg.sh "$(T_DMG)" "$(T_BUNDLE)"
mv "$(T_DMG).dmg" bundle.dmg
EXTRA_DIST = \
auto4_perldata.inc
intltool-extract.in \
intltool-merge.in \
intltool-update.in \
config.guess \
config.sub \
depcomp \
install-sh \
missing \
INSTALL \
README \
svn_revision
# m4macros/
EXTRA_DIST += \
m4macros/check_gnu_make.m4 \
m4macros/acx_pthread.m4 \
m4macros/ac_agi.m4 \
m4macros/ax_lang_compiler_ms.m4 \
m4macros/ac_agi_mdcpucfg.m4 \
m4macros/ax_openmp.m4 \
m4macros/ax_check_gl.m4 \
m4macros/ac_flag.m4
# scripts/
EXTRA_DIST += \
scripts/osx-bundle-restart-helper.c \
scripts/osx-bundle.sh \
scripts/osx-dmg-dsstore.pl \
scripts/osx-dmg.sh \
scripts/osx-fix-libs.py \
scripts/unix-gen-res.awk \
scripts/unix-gen-xpm.awk
# packages/osx_bundle/
EXTRA_DIST += \
packages/osx_bundle/Contents/Info.plist \
packages/osx_bundle/Contents/Resources/*.icns \
packages/osx_bundle/Contents/Resources/etc/fonts/fonts.conf \
packages/osx_bundle/Contents/Resources/etc/fonts/fonts.dtd \
packages/osx_bundle/Contents/Resources/etc/fonts/conf.d/*.conf
# packages/osx_dmg/
EXTRA_DIST += \
packages/osx_dmg/dmg_background.png \
packages/osx_dmg/dmg_set_style.applescript
CLEANFILES= \
intltool-extract \
intltool-merge \
intltool-update

View File

@ -34,7 +34,7 @@ test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
cd $srcdir
test -d aegisub || {
test -d src || {
echo
echo "You must run this script in the top-level $PROJECT directory."
echo
@ -188,7 +188,7 @@ if test -z "$BIN_CONVERT"; then
fi
$ECHO_N "checking for ImageMagick 'convert' utility ... "
if test -x "$BIN_CONVERT"; then
if test -x "$BIN_CONVERT" && $BIN_CONVERT --version |grep -c ImageMagick > /dev/null; then
echo $BIN_CONVERT
else
echo "not found"
@ -225,21 +225,22 @@ if test "$DIE" -eq 1; then
fi
echo
echo "I am going to run ./configure with the following arguments:"
echo
echo " --enable-maintainer-mode $AUTOGEN_CONFIGURE_ARGS $@"
echo
if ! test "$1" = "--skip-configure"; then
echo
echo "I am going to run ./configure with the following arguments:"
echo
echo " --enable-maintainer-mode $AUTOGEN_CONFIGURE_ARGS $@"
echo
if test -z "$*"; then
echo "If you wish to pass additional arguments, please specify them "
echo "on the $0 command line or set the AUTOGEN_CONFIGURE_ARGS "
echo "environment variable."
echo
if test -z "$*"; then
echo "If you wish to pass additional arguments, please specify them "
echo "on the $0 command line or set the AUTOGEN_CONFIGURE_ARGS "
echo "environment variable."
echo
fi
fi
echo "--- Checking for required M4 files ---"
if test -z "$ACLOCAL_FLAGS"; then
@ -282,19 +283,19 @@ fi
echo "--- Converting BMP resource files -> XPM ---"
# BMP -> XPM via src/res.rc
cat ${srcdir}/aegisub/res.rc | ${BIN_AWK} -f ${srcdir}/scripts/unix-gen-xpm.awk BIN_CONVERT="$BIN_CONVERT" > ${srcdir}/aegisub/bitmaps/Makefile.bitmaps
cd ${srcdir}/aegisub/bitmaps
cat ${srcdir}/src/res.rc | ${BIN_AWK} -f ${srcdir}/scripts/unix-gen-xpm.awk BIN_CONVERT="$BIN_CONVERT" > ${srcdir}/src/bitmaps/Makefile.bitmaps
cd ${srcdir}/src/bitmaps
make -f Makefile.bitmaps
cd ${srcdir}
$BIN_AWK '/BITMAP/ { image[count] = $1; ++count} END { printf("EXTRA_DIST="); for (v in image) printf(" \\\n %s_xpm.xpm", image[v])}' \
${srcdir}/aegisub/res.rc \
> ${srcdir}/aegisub/bitmaps/Makefile.am
${srcdir}/src/res.rc \
> ${srcdir}/src/bitmaps/Makefile.am
echo "--- Generating libresrc/resrc.cpp, libresrc/libresrc.h from res.rc ---"
$BIN_AWK -f scripts/unix-gen-res.awk ${srcdir}/aegisub/res.rc \
RESRC_CPP="${srcdir}/aegisub/libresrc/resrc.cpp" \
RESRC_H="${srcdir}/aegisub/libresrc/libresrc.h"
$BIN_AWK -f scripts/unix-gen-res.awk ${srcdir}/src/res.rc \
RESRC_CPP="${srcdir}/src/libresrc/resrc.cpp" \
RESRC_H="${srcdir}/src/libresrc/libresrc.h"
rm -rf autom4te.cache
@ -321,29 +322,34 @@ $AUTOCONF || exit $?
echo "--- $GETTEXTIZE ---"
$GETTEXTIZE --force || exit $?
echo "--- $INTTOOLIZE ---"
echo "--- $INTLTOOLIZE ---"
$INTLTOOLIZE --force --automake || exit $?
cd $ORIGDIR
echo "--- $srcdir/configure ---"
$srcdir/configure --enable-maintainer-mode $AUTOGEN_CONFIGURE_ARGS "$@"
RC=$?
echo
echo
echo "***********************************************************************"
echo "*"
echo "* Please do not ask for support when using the SVN verison of aegisub,"
echo "* download an official distfile in order to receive support."
echo "*"
echo "***********************************************************************"
echo
if test $RC -ne 0; then
if ! test "$1" = "--skip-configure"; then
echo "--- $srcdir/configure ---"
echo "Running '$srcdir/configure --enable-maintainer-mode $AUTOGEN_CONFIGURE_ARGS "$@"'"
echo
echo "Configure failed or did not finish!"
exit $RC
$srcdir/configure --enable-maintainer-mode $AUTOGEN_CONFIGURE_ARGS "$@"
RC=$?
echo
echo
echo "***********************************************************************"
echo "*"
echo "* Please do not ask for support when using the SVN verison of aegisub,"
echo "* download an official distfile in order to receive support."
echo "*"
echo "***********************************************************************"
echo
if test $RC -ne 0; then
echo
echo "Configure failed or did not finish!"
exit $RC
fi
echo "Now type 'make' to compile $PROJECT."
fi
echo "Now type 'make' to compile $PROJECT."

View File

@ -8,7 +8,7 @@ writing) @ http://www.malakith.net/aegiwiki
mechanism works. Even so, I am not resposible if it damages your subtitles permanently, so please
back up your subtitle file before applying the cleaning up
Copyright (c) 2007 ai-chan (Aegisub's forum member and registered nick holder of Rizon irc network)
Copyright (c) 2007-2009 Muhammad Lukman Nasaruddin (aka ai-chan, Aegisub's forum member)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
@ -28,9 +28,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
script_name = "Clean Tags"
script_description = "Clean subtitle lines by re-arranging ASS tags and override blocks within the lines"
script_author = "ai-chan"
script_version = "1.150"
script_modified = "12 September 2007"
script_author = "Muhammad Lukman Nasaruddin (ai-chan)"
script_version = "1.20"
script_modified = "25 February 2009"
include("cleantags.lua")
@ -38,11 +38,11 @@ function cleantags_subs(subtitles)
local linescleaned = 0
for i = 1, #subtitles do
aegisub.progress.set(i * 100 / #subtitles)
if subtitles[i].class == "dialogue" and subtitles[i].text ~= "" then
if subtitles[i].class == "dialogue" and not subtitles[i].comment and subtitles[i].text ~= "" then
ntext = cleantags(subtitles[i].text)
local nline = subtitles[i]
nline.text = ntext
subtitles[i] = nline -- I don't understand why we need these steps to incorporate new text
subtitles[i] = nline
linescleaned = linescleaned + 1
aegisub.progress.task(linescleaned .. " lines cleaned")
end

View File

@ -34,7 +34,7 @@
script_name = "Karaoke Templater"
script_description = "Macro and export filter to apply karaoke effects using the template language"
script_author = "Niels Martin Hansen"
script_version = "2.1.0"
script_version = "2.1.7"
include("karaskel.lua")
@ -265,6 +265,26 @@ function matching_templates(templates, line, tenv)
return test_next
end
-- Iterator function, run a loop using tenv.j and tenv.maxj as loop controllers
function template_loop(tenv, initmaxj)
local oldmaxj = initmaxj
tenv.maxj = initmaxj
tenv.j = 0
local function itor()
if tenv.j >= tenv.maxj or aegisub.progress.is_cancelled() then
return nil
else
tenv.j = tenv.j + 1
if oldmaxj ~= tenv.maxj then
aegisub.debug.out(5, "Number of loop iterations changed from %d to %d\n", oldmaxj, tenv.maxj)
oldmaxj = tenv.maxj
end
return tenv.j, tenv.maxj
end
end
return itor
end
-- Apply the templates
function apply_templates(meta, styles, subs, templates)
@ -278,6 +298,8 @@ function apply_templates(meta, styles, subs, templates)
}
tenv.tenv = tenv
-- Define helper functions in tenv
tenv.retime = function(mode, addstart, addend)
local line, syl = tenv.line, tenv.syl
local newstart, newend = line.start_time, line.end_time
@ -322,8 +344,31 @@ function apply_templates(meta, styles, subs, templates)
line.duration = newend - newstart
return ""
end
tenv.fxgroup = {}
tenv.relayer = function(layer)
line.layer = layer
return ""
end
tenv.restyle = function(style)
line.style = style
line.styleref = styles[style]
return ""
end
tenv.maxloop = function(newmaxj)
tenv.maxj = newmaxj
return ""
end
tenv.maxloops = tenv.maxloop
tenv.loopctl = function(newj, newmaxj)
tenv.j = newj
tenv.maxj = newmaxj
return ""
end
-- run all run-once code snippets
for k, t in pairs(templates.once) do
assert(t.code, "WTF, a 'once' template without code?")
@ -443,8 +488,7 @@ function apply_line(meta, styles, subs, line, templates, tenv)
-- Apply all line templates
aegisub.debug.out(5, "Running line templates\n")
for t in matching_templates(templates.line, line, tenv) do
tenv.j = 0
tenv.maxj = t.loops
if aegisub.progress.is_cancelled() then break end
-- Set varctx for per-line variables
varctx["start"] = varctx.lstart
@ -464,11 +508,15 @@ function apply_line(meta, styles, subs, line, templates, tenv)
varctx.x = varctx.lx
varctx.y = varctx.ly
while tenv.j < t.loops do
tenv.j = tenv.j + 1
for j, maxj in template_loop(tenv, t.loops) do
if t.code then
aegisub.debug.out(5, "Code template, %s\n", t.code)
tenv.line = line
-- Although run_code_template also performs template looping this works
-- by "luck", since by the time the first loop of this outer loop completes
-- the one run by run_code_template has already performed all iterations
-- and has tenv.j and tenv.maxj in a loop-ending state, causing the outer
-- loop to only ever run once.
run_code_template(t, tenv)
else
aegisub.debug.out(5, "Line template, pre = '%s', t = '%s'\n", t.pre, t.t)
@ -512,6 +560,7 @@ function apply_line(meta, styles, subs, line, templates, tenv)
-- Loop over syllables
for i = 0, line.kara.n do
if aegisub.progress.is_cancelled() then break end
local syl = line.kara[i]
aegisub.debug.out(5, "Applying templates to syllable: %s\n", syl.text)
@ -522,6 +571,7 @@ function apply_line(meta, styles, subs, line, templates, tenv)
-- Loop over furigana
for i = 1, line.furi.n do
if aegisub.progress.is_cancelled() then break end
local furi = line.furi[i]
aegisub.debug.out(5, "Applying templates to furigana: %s\n", furi.text)
@ -540,9 +590,7 @@ function run_code_template(template, tenv)
else
local pcall = pcall
setfenv(f, tenv)
tenv.maxj = template.loops
for j = 1, template.loops do
tenv.j = j
for j, maxj in template_loop(tenv, template.loops) do
local res, err = pcall(f)
if not res then
aegisub.debug.out(2, "Runtime error in template code: %s\nCode producing error: %s\n\n", err, template.code)
@ -600,20 +648,20 @@ function run_text_template(template, tenv, varctx)
end
function apply_syllable_templates(syl, line, templates, tenv, varctx, subs)
local applied_templates = false
local applied = 0
-- Loop over all templates matching the line style
for t in matching_templates(templates, line, tenv) do
if aegisub.progress.is_cancelled() then break end
tenv.syl = syl
tenv.basesyl = syl
set_ctx_syl(varctx, line, syl)
if apply_one_syllable_template(syl, line, t, tenv, varctx, subs, false, false) then
applied_templates = true
end
applied = applied + apply_one_syllable_template(syl, line, t, tenv, varctx, subs, false, false)
end
return applied_templates
return applied > 0
end
function is_syl_blank(syl)
@ -630,19 +678,21 @@ function is_syl_blank(syl)
end
function apply_one_syllable_template(syl, line, template, tenv, varctx, subs, skip_perchar, skip_multi)
if aegisub.progress.is_cancelled() then return 0 end
local t = template
local applied = 0
aegisub.debug.out(5, "Applying template to one syllable with text: %s\n", syl.text)
-- Check for right inline_fx
if t.fx and t.fx ~= syl.inline_fx then
aegisub.debug.out(5, "Syllable has wrong inline-fx (wanted '%s', got '%s'), skipping.\n", t.inline_fx, syl.inline_fx)
return false
return 0
end
if t.noblank and is_syl_blank(syl) then
aegisub.debug.out(5, "Syllable is blank, skipping.\n")
return false
return 0
end
-- Recurse to per-char if required
@ -665,10 +715,10 @@ function apply_one_syllable_template(syl, line, template, tenv, varctx, subs, sk
left = left + width
set_ctx_syl(varctx, line, charsyl)
apply_one_syllable_template(charsyl, line, t, tenv, varctx, subs, true, false)
applied = applied + apply_one_syllable_template(charsyl, line, t, tenv, varctx, subs, true, false)
end
return true
return applied
end
-- Recurse to multi-hl if required
@ -684,10 +734,10 @@ function apply_one_syllable_template(syl, line, template, tenv, varctx, subs, sk
hlsyl.duration = hldata.duration
set_ctx_syl(varctx, line, hlsyl)
apply_one_syllable_template(hlsyl, line, t, tenv, varctx, subs, true, true)
applied = applied + apply_one_syllable_template(hlsyl, line, t, tenv, varctx, subs, true, true)
end
return true
return applied
end
-- Regular processing
@ -697,9 +747,7 @@ function apply_one_syllable_template(syl, line, template, tenv, varctx, subs, sk
run_code_template(t, tenv)
else
aegisub.debug.out(5, "Running %d effect loops\n", t.loops)
tenv.maxj = t.loops
for j = 1, t.loops do
tenv.j = j
for j, maxj in template_loop(tenv, t.loops) do
local newline = table.copy(line)
newline.styleref = syl.style
newline.style = syl.style.name
@ -714,10 +762,11 @@ function apply_one_syllable_template(syl, line, template, tenv, varctx, subs, sk
newline.effect = "fx"
aegisub.debug.out(5, "Generated line with text: %s\n", newline.text)
subs.append(newline)
applied = applied + 1
end
end
return true
return applied
end

View File

@ -1,12 +1,11 @@
--[[
"Clean Tags" -- An Auto4 LUA script for cleaning up ASS subtitle lines of badly-formed override
blocks and redundant/duplicate tags
* Designed to work for Aegisub 2.0 and above (only pre-release version was available at the time of
writing) @ http://www.malakith.net/aegiwiki
* Designed to work for Aegisub 2.0 and above
* include()'ed this file from any auto4 script to use the cleantags() function below
* Might change from time to time so look out for cleantags_version below
Copyright (c) 2007 ai-chan (Aegisub's forum member and registered nick holder of Rizon irc network)
Copyright (c) 2007-2009 Muhammad Lukman Nasaruddin (aka ai-chan, Aegisub's forum member)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
@ -24,8 +23,8 @@ OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
cleantags_version = "1.200"
cleantags_modified = "13 September 2007"
cleantags_version = "1.300"
cleantags_modified = "27 February 2009"
ktag = "\\[kK][fo]?%d+"
@ -34,13 +33,13 @@ Takes: text
Returns: cleaned up text
]]
function cleantags(text)
--[[ Combine adjacentext override override blocks into one ]]
--[[ Combine adjacent override override blocks into one ]]
function combineadjacentnotks(block1, block2)
if string.find(block1, ktag) and string.find(block2, ktag) then
-- if both adjacentext override blocks have \k , letext them be
-- if both adjacent override blocks have \k , let them be
return "{" .. block1 .. "}" .. string.char(1) .. "{" .. block2 .. "}" -- char(1) prevents infinite loop
else
-- either one or both override blocks don'text have \k , so combine them into one override block
-- either one or both override blocks don't have \k , so combine them into one override block
return "{" .. block1 .. block2 .. "}"
end
end
@ -50,17 +49,17 @@ function cleantags(text)
until replaced == 0
text = string.gsub(text, string.char(1), "") -- removes all char(1) we inserted
--[[ Move firstext \k tag in override blocks to the frontext ]]
--[[ Move first \k tag in override blocks to the front ]]
text = string.gsub(text, "{([^{}]-)(" .. ktag .. ")(.-)}", "{%2%1%3}")
--[[ For some reasons if one override block has more than one \k tag,
push those to behind the firstext \k tag (which has been pushed to frontext already) ]]
push those to behind the first \k tag (which has been pushed to front already) ]]
repeat
if aegisub.progress.is_cancelled() then return end
text, replaced = string.gsub(text, "{([^{}]-)(" .. ktag .. ")(\\[^kK][^}]-)(" .. ktag .. ")(.-)}", "{%1%2%4%3%5}")
until replaced == 0
--[[ Move to the frontext all tags thatext affectext the whole line (i.e. notext affected by their positions in the line) ]]
--[[ Move to the front all tags that affect the whole line (i.e. not affected by their positions in the line) ]]
local linetags = ""
function first(pattern)
local p_s, _, p_tag = string.find(text, pattern)
@ -84,26 +83,29 @@ function cleantags(text)
first("(\\an?%d+)")
-- \org
first("(\\org%([^,%)]*,[^,%)]*%))")
-- \move and \pos (the firstext one wins)
-- \move and \pos (the first one wins)
firstoftwo("(\\move%([^,%)]*,[^,%)]*,[^,%)]*,[^,%)]*%))", "(\\pos%([^,%)]*,[^,%)]*%))")
-- \fade and \fad (the firstext one wins)
-- \fade and \fad (the first one wins)
firstoftwo("(\\fade%([^,%)]*,[^,%)]*,[^,%)]*,[^,%)]*,[^,%)]*,[^,%)]*,[^,%)]*%))", "(\\fad%([^,%)]*,[^,%)]*%))")
-- integrate
if string.len(linetags) > 0 then
if string.sub(text, 1, 1) == "{" then
text = "{" .. linetags .. string.sub(text, 2)
else
text = "{" .. linetags .. "}" .. t
text = "{" .. linetags .. "}" .. text
end
end
--[[ Remove any spaces within parenteses within override blocks ]]
--[[ (removed in v 1.2)
repeat
if aegisub.progress.is_cancelled() then return end
text, replaced2 = string.gsub(text, "({[^}]*%([^%s%)}]*,)%s+(.*%)[^}]*})", "%1%2")
until replaced2 == 0 ]]
--[[ Remove any spaces within parenteses within override blocks except for \clip tags ]]
local comb = function(a,b,c,d,e)
if c ~= "\\clip" or d:sub(-1):find("[,%({]") or e:sub(1,1):find("[,%)}]") then return a..b..d..e
else return a..b..d..string.char(2)..e end
end
repeat
text, replaced2 = string.gsub(text, "({[^}\\]*)([^}%s]*(\\[^%(}\\%s]*))%s*(%([^%s%)}]*)%s+([^}]*)", comb)
until replaced2 == 0
text, _ = text:gsub(string.char(2)," ")
--[[ Remove all empty override blocks ==> {} ]]
text = string.gsub(text, "{%s*}", "")

View File

@ -12,7 +12,28 @@ function test7(subtitles, selected_lines, active_line)
local a, b = aegisub.dialog.display({{class="label", label="Test..."}}, {})
report_dialog_result(a, b)
aegisub.progress.set(50)
a, b = aegisub.dialog.display({{class="edit", name="foo", text=""}}, {"foo", "bar"})
a, b = aegisub.dialog.display(
{
{class="edit", name="foo", text="", x=0, y=0},
{class="intedit", name="e1", value=20, x=0, y=1},
{class="intedit", name="e2", value=30, min=10, max=50, x=1, y=1},
{class="floatedit", name="e3", value=19.95, x=0, y=2},
{class="floatedit", name="e4", value=123.63423, min=-4.3, max=2091, x=1, y=2},
{class="floatedit", name="e5", value=-4, step=0.21, x=2, y=2},
{class="floatedit", name="e6", value=22, min=0, max=100, step=1.4, x=3, y=2},
{class="textbox", name="e7", text="hmm wuzzis say?", x=0, y=3, width=4},
{class="dropdown", name="l1", items={"abc", "def", "ghi"}, value="def", x=0, y=4},
{class="dropdown", name="l2", items={"abc", "def", "ghi"}, value="doesnotexist", x=1, y=4},
{class="checkbox", name="b1", value=true, label='checked', x=0, y=5},
{class="checkbox", name="b2", value=false, label='cleared', x=1, y=5},
{class="color", name="c1", value="#00ff11", x=0, y=6},
{class="color", name="c2", value="&H0011ff00", x=1, y=6},
{class="coloralpha", name="c3", value="#aabbccdd", x=0, y=7},
{class="coloralpha", name="c4", value="&Hddccbbaa&", x=1, y=7},
{class="alpha", name="c5", value="#12", x=0, y=8},
{class="alpha", name="c6", value="&H12&", x=1, y=8}
},
{"foo", "bar"})
report_dialog_result(a, b)
end
@ -26,7 +47,8 @@ function report_dialog_result(button, controls)
aegisub.debug.out("clicked '" .. button .. "'\n")
end
for key, val in pairs(controls) do
aegisub.debug.out(key .. ': ' .. val .. '\n')
local printable = (val == true and "true") or (val == false and "false") or tostring(val)
aegisub.debug.out("%s: %s\n", key, printable)
end
aegisub.debug.out(" - - - - -\n")
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Some files were not shown because too many files have changed in this diff Show More