diff -Nru ffms2-2.22/build-win-deps.sh ffms2-2.23/build-win-deps.sh --- ffms2-2.22/build-win-deps.sh 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/build-win-deps.sh 2016-10-18 16:54:00.000000000 +0000 @@ -147,7 +147,6 @@ --disable-filters \ --disable-hwaccels \ --disable-muxers \ - --disable-network \ --disable-pthreads \ --disable-shared \ --enable-avresample \ diff -Nru ffms2-2.22/debian/changelog ffms2-2.23/debian/changelog --- ffms2-2.22/debian/changelog 2016-04-30 16:53:23.000000000 +0000 +++ ffms2-2.23/debian/changelog 2016-10-20 18:46:13.000000000 +0000 @@ -1,8 +1,15 @@ -ffms2 (2.22-1build1) yakkety; urgency=medium +ffms2 (2.23-1) unstable; urgency=medium - * Rebuild for ffmpeg 3.0. + * New upstream release. + * debian/copyright: Update copyright years. + * debian/{control,rules,compat}: Bump debhelper compat to 10. + * debian/control: + - Bump Standards-Version. + - Update Vcs-. + * debian/patches: Refresh patches. + * debian/libffms2-4.symbols: Add new symbols. - -- Colin Watson Sat, 30 Apr 2016 17:53:23 +0100 + -- Sebastian Ramacher Thu, 20 Oct 2016 20:46:13 +0200 ffms2 (2.22-1) unstable; urgency=medium diff -Nru ffms2-2.22/debian/compat ffms2-2.23/debian/compat --- ffms2-2.22/debian/compat 2013-12-02 19:21:21.000000000 +0000 +++ ffms2-2.23/debian/compat 2016-10-20 18:37:25.000000000 +0000 @@ -1 +1 @@ -9 +10 diff -Nru ffms2-2.22/debian/control ffms2-2.23/debian/control --- ffms2-2.22/debian/control 2015-07-14 19:34:13.000000000 +0000 +++ ffms2-2.23/debian/control 2016-10-20 18:38:06.000000000 +0000 @@ -5,8 +5,7 @@ Reinhard Tartler , Rico Tzschichholz , Sebastian Ramacher -Build-Depends: debhelper (>= 9), - dh-autoreconf, +Build-Depends: debhelper (>= 10), pkg-config, libavutil-dev (>= 4:0.8~), libavformat-dev (>= 4:0.8~), @@ -17,9 +16,9 @@ python3, python3-markdown Section: libs -Standards-Version: 3.9.6 -Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-multimedia/ffms2.git;a=summary -Vcs-Git: git://anonscm.debian.org/pkg-multimedia/ffms2.git +Standards-Version: 3.9.8 +Vcs-Browser: https://anonscm.debian.org/cgit/pkg-multimedia/ffms2.git +Vcs-Git: https://anonscm.debian.org/git/pkg-multimedia/ffms2.git Homepage: https://github.com/FFMS/ffms2 Package: libffms2-4 diff -Nru ffms2-2.22/debian/copyright ffms2-2.23/debian/copyright --- ffms2-2.22/debian/copyright 2015-10-13 15:55:46.000000000 +0000 +++ ffms2-2.23/debian/copyright 2016-10-20 18:45:16.000000000 +0000 @@ -4,7 +4,7 @@ Files: * Copyright: - 2007-2015 Fredrik Mellbin + 2007-2016 Fredrik Mellbin 2010-2011,2013-2014 Thomas Goyne 2007-2015 The FFmpegSource Project Comment: @@ -66,7 +66,7 @@ Copyright: 2009-2010 Rickard Närström 2010 Reinhard Tartler - 2013-2015 Sebastian Ramacher + 2013-2016 Sebastian Ramacher License: custom Copying and distribution of this package, with or without modification, are permitted in any medium without royalty diff -Nru ffms2-2.22/debian/libffms2-4.symbols ffms2-2.23/debian/libffms2-4.symbols --- ffms2-2.22/debian/libffms2-4.symbols 2015-10-13 15:54:01.000000000 +0000 +++ ffms2-2.23/debian/libffms2-4.symbols 2016-10-20 18:43:17.000000000 +0000 @@ -1,5 +1,5 @@ libffms2.so.4 libffms2-4 #MINVER# -| libffms2-4 (>= 2.22), libffms2-4 (<< 2.23) +| libffms2-4 (>= 2.23), libffms2-4 (<< 2.24) FFMS_CancelIndexing@Base 2.19 FFMS_CreateAudioSource@Base 2.19 FFMS_CreateIndexer@Base 2.19 @@ -13,6 +13,7 @@ FFMS_DestroyVideoSource@Base 2.19 FFMS_DoIndexing2@Base 2.21 FFMS_DoIndexing@Base 2.19 + FFMS_FreeIndexBuffer@Base 2.23 FFMS_GetAudio@Base 2.19 FFMS_GetAudioProperties@Base 2.19 FFMS_GetCodecNameI@Base 2.19 @@ -44,6 +45,7 @@ FFMS_Init@Base 2.19 FFMS_MakeIndex@Base 2.19 FFMS_ReadIndex@Base 2.19 + FFMS_ReadIndexFromBuffer@Base 2.23 FFMS_ResetInputFormatV@Base 2.19 FFMS_ResetOutputFormatV@Base 2.19 FFMS_SetAudioNameCallback@Base 2.21 @@ -55,6 +57,7 @@ FFMS_TrackIndexSettings@Base 2.21 FFMS_TrackTypeIndexSettings@Base 2.21 FFMS_WriteIndex@Base 2.19 + FFMS_WriteIndexToBuffer@Base 2.23 FFMS_WriteTimecodes@Base 2.19 (optional)VapourSynthPluginInit@Base 2.19 (regex|optional=templinst)"^_Z.*@Base$" 0 1 diff -Nru ffms2-2.22/debian/patches/fix-links.patch ffms2-2.23/debian/patches/fix-links.patch --- ffms2-2.22/debian/patches/fix-links.patch 2015-07-13 16:22:43.000000000 +0000 +++ ffms2-2.23/debian/patches/fix-links.patch 2016-10-20 18:39:43.000000000 +0000 @@ -2,18 +2,18 @@ Author: Sebastian Ramacher Last-Update: 2015-07-13 ---- ffms2-2.21.orig/doc/ffms2-api.md -+++ ffms2-2.21/doc/ffms2-api.md -@@ -184,7 +184,7 @@ How many characters you want to allocate +--- a/doc/ffms2-api.md ++++ b/doc/ffms2-api.md +@@ -184,7 +184,7 @@ ### FFMS_Init - initializes the library -[Init]: #ffms_init---initializes-the-library +[Init]: #ffms_init-initializes-the-library ```c++ - void FFMS_Init(int Unused, int UseUTF8Paths); + void FFMS_Init(int Unused, int Unused2); ``` -@@ -209,7 +209,7 @@ Prior to API version 2.14.0.0 this funct +@@ -204,7 +204,7 @@ ### FFMS_GetLogLevel - gets FFmpeg message level @@ -22,7 +22,7 @@ ```c++ int FFMS_GetLogLevel(); ``` -@@ -219,7 +219,7 @@ Alternatively, just copy the relevant co +@@ -214,7 +214,7 @@ ### FFMS_SetLogLevel - sets FFmpeg message level @@ -31,7 +31,7 @@ ```c++ void FFMS_SetLogLevel(int Level); ``` -@@ -227,7 +227,7 @@ Sets FFmpeg's logging/message level; see +@@ -222,7 +222,7 @@ ### FFMS_CreateVideoSource - creates a video source object @@ -40,7 +40,7 @@ ```c++ FFMS_VideoSource *FFMS_CreateVideoSource(const char *SourceFile, int Track, FFMS_Index *Index, int Threads, int SeekMode, FFMS_ErrorInfo *ErrorInfo); -@@ -268,7 +268,7 @@ Returns `NULL` and sets `ErrorMsg` on fa +@@ -263,7 +263,7 @@ ### FFMS_CreateAudioSource - creates an audio source object @@ -49,7 +49,7 @@ ```c++ FFMS_AudioSource *FFMS_CreateAudioSource(const char *SourceFile, int Track, FFMS_Index *Index, int DelayMode, FFMS_ErrorInfo *ErrorInfo); -@@ -291,8 +291,8 @@ Possible arguments are: +@@ -286,8 +286,8 @@ ### FFMS_DestroyVideoSource, FFMS_DestroyAudioSource - deallocates a video or audio source object @@ -60,7 +60,7 @@ ```c++ void FFMS_DestroyVideoSource(FFMS_VideoSource *V); void FFMS_DestroyAudioSource(FFMS_AudioSource *A); -@@ -301,7 +301,7 @@ Deallocates the given `FFMS_VideoSource` +@@ -296,7 +296,7 @@ ### FFMS_GetVideoProperties - retrieves video properties @@ -69,7 +69,7 @@ ```c++ const FFMS_VideoProperties *FFMS_GetVideoProperties(FFMS_VideoSource *V); ``` -@@ -310,7 +310,7 @@ Returns a pointer to said struct. +@@ -305,7 +305,7 @@ ### FFMS_GetAudioProperties - retrieves audio properties @@ -78,7 +78,7 @@ ```c++ const FFMS_AudioProperties *FFMS_GetAudioProperties(FFMS_AudioSource *A); ``` -@@ -319,7 +319,7 @@ See [FFMS_AudioProperties][AudioProperti +@@ -314,7 +314,7 @@ ### FFMS_GetFrame - retrieves a given video frame @@ -87,7 +87,7 @@ ```c++ const FFMS_Frame *FFMS_GetFrame(FFMS_VideoSource *V, int n, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -347,7 +347,7 @@ Note that while `FFMS_GetFrame` tends to +@@ -342,7 +342,7 @@ ### FFMS_GetFrameByTime - retrieves a video frame at a given timestamp @@ -96,7 +96,7 @@ ```c++ const FFMS_Frame *FFMS_GetFrameByTime(FFMS_VideoSource *V, double Time, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -356,7 +356,7 @@ This function exists for the people who +@@ -351,7 +351,7 @@ ### FFMS_GetAudio - decodes a number of audio samples @@ -105,7 +105,7 @@ ```c++ int FFMS_GetAudio(FFMS_AudioSource *A, void *Buf, int64_t Start, int64_t Count, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -388,7 +388,7 @@ Returns non-0 and sets `ErrorMsg` on fai +@@ -383,7 +383,7 @@ ### FFMS_SetOutputFormatV2 - sets the output format for video frames @@ -114,7 +114,7 @@ ```c++ int FFMS_SetOutputFormatV2(FFMS_VideoSource *V, int *TargetFormats, int Width, int Height, int Resizer, FFMS_ErrorInfo *ErrorInfo); -@@ -437,7 +437,7 @@ Returns non-0 and sets `ErrorMsg` on fai +@@ -432,7 +432,7 @@ ### FFMS_ResetOutputFormatV - resets the video output format @@ -123,7 +123,7 @@ ```c++ void FFMS_ResetOutputFormatV(FFMS_VideoSource *V); ``` -@@ -447,7 +447,7 @@ If you call it, you'd better call [FFMS_ +@@ -442,7 +442,7 @@ ### FFMS_SetInputFormatV - override the source format for video frames @@ -132,7 +132,7 @@ ```c++ int FFMS_SetInputFormatV(FFMS_VideoSource *V, int ColorSpace, int ColorRange, int PixelFormat, FFMS_ErrorInfo *ErrorInfo); -@@ -484,7 +484,7 @@ Returns non-0 and sets `ErrorMsg` on fai +@@ -479,7 +479,7 @@ ### FFMS_ResetInputFormatV - resets the video input format @@ -141,7 +141,7 @@ ```c++ void FFMS_ResetInputFormatV(FFMS_VideoSource *V); ``` -@@ -492,7 +492,7 @@ Resets the input format for the given `F +@@ -487,7 +487,7 @@ ### FFMS_DestroyIndex - deallocates an index object @@ -150,7 +150,7 @@ ```c++ void FFMS_DestroyFFMS_Index(FFMS_Index *Index); ``` -@@ -500,7 +500,7 @@ Deallocates the given `FFMS_Index` objec +@@ -495,7 +495,7 @@ ### FFMS_GetSourceType - gets which source module was used to open the given index @@ -159,7 +159,7 @@ ```c++ int FFMS_GetSourceType(FFMS_Index *Index); ``` -@@ -508,7 +508,7 @@ Returns `FFMS_SOURCE_LAVF`. +@@ -503,7 +503,7 @@ ### FFMS_GetSourceTypeI - gets which source module was used to open the given indexer @@ -168,7 +168,7 @@ ```c++ int FFMS_GetSourceTypeI(FFMS_Index *Indexer); ``` -@@ -516,7 +516,7 @@ Does the same thing as [FFMS_GetSourceTy +@@ -511,7 +511,7 @@ ### FFMS_GetErrorHandling - gets which error handling mode was used when creating the given index @@ -177,7 +177,7 @@ ```c++ int FFMS_GetErrorHandling(FFMS_Index *Index); ``` -@@ -524,7 +524,7 @@ Returns the value of the ErrorHandling p +@@ -519,7 +519,7 @@ ### FFMS_GetFirstTrackOfType - gets the track number of the first track of a given type @@ -186,7 +186,7 @@ ```c++ int FFMS_GetFirstTrackOfType(FFMS_Index *Index, int TrackType, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -548,7 +548,7 @@ Returns a negative integer and sets Erro +@@ -543,7 +543,7 @@ ### FFMS_GetFirstIndexedTrackOfType - gets the track number of the first track of a given type @@ -195,7 +195,7 @@ ```c++ int FFMS_GetFirstIndexedTrackOfType(FFMS_Index *Index, int TrackType, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -556,7 +556,7 @@ Does the exact same thing as [FFMS_GetFi +@@ -551,7 +551,7 @@ ### FFMS_GetNumTracks - gets the number of tracks in a given index @@ -204,7 +204,7 @@ ```c++ int FFMS_GetNumTracks(FFMS_Index *Index); ``` -@@ -564,7 +564,7 @@ Returns the total number of tracks in th +@@ -559,7 +559,7 @@ ### FFMS_GetNumTracksI - gets the number of tracks in a given indexer @@ -213,7 +213,7 @@ ```c++ int FFMS_GetNumTracksI(FFMS_Indexer *Indexer); ``` -@@ -573,7 +573,7 @@ In other words, does the same thing as [ +@@ -568,7 +568,7 @@ ### FFMS_GetTrackType - gets the track type of a given track @@ -222,7 +222,7 @@ ```c++ int FFMS_GetTrackType(FFMS_Track *T); ``` -@@ -581,7 +581,7 @@ Returns an integer representing the [FFM +@@ -576,7 +576,7 @@ ### FFMS_GetTrackTypeI - gets the track type of a given track @@ -231,7 +231,7 @@ ```c++ int FFMS_GetTrackTypeI(FFMS_Indexer *Indexer, int Track); ``` -@@ -592,7 +592,7 @@ Note that specifying an invalid track nu +@@ -587,7 +587,7 @@ ### FFMS_GetCodecNameI - gets the name of the codec used for a given track @@ -240,7 +240,7 @@ ```c++ const char *FFMS_GetCodecNameI(FFMS_Indexer *Indexer, int Track); ``` -@@ -602,7 +602,7 @@ Note that specifying an invalid track nu +@@ -597,7 +597,7 @@ ### FFMS_GetFormatNameI - gets the name of the container format used in the given indexer @@ -249,7 +249,7 @@ ```c++ const char *FFMS_GetFormatNameI(FFMS_Indexer *Indexer); ``` -@@ -610,7 +610,7 @@ Returns the human-readable name ("long n +@@ -605,7 +605,7 @@ ### FFMS_GetNumFrames - gets the number of frames in a given track @@ -258,7 +258,7 @@ ```c++ int FFMS_GetNumFrames(FFMS_Track *T); ``` -@@ -620,7 +620,7 @@ A return value of 0 indicates the track +@@ -615,7 +615,7 @@ ### FFMS_GetFrameInfo - gets information about a given frame @@ -267,7 +267,7 @@ ```c++ const FFMS_FrameInfo *FFMS_GetFrameInfo(FFMS_Track *T, int Frame); ``` -@@ -646,7 +646,7 @@ Returns `NULL` and sets `ErrorMsg` on fa +@@ -641,7 +641,7 @@ ### FFMS_GetTrackFromIndex - retrieves track info from an index @@ -276,7 +276,7 @@ ```c+++ FFMS_Track *FFMS_GetTrackFromIndex(FFMS_Index *Index, int Track); ``` -@@ -673,8 +673,8 @@ Note that requesting indexing informatio +@@ -668,8 +668,8 @@ ### FFMS_GetTrackFromVideo, FFMS_GetTrackFromAudio - retrieves track info from audio or video source @@ -287,7 +287,7 @@ ```c++ FFMS_Track *FFMS_GetTrackFromVideo(FFMS_VideoSource *V); FFMS_Track *FFMS_GetTrackFromAudio(FFMS_AudioSource *A); -@@ -685,7 +685,7 @@ Note that the returned `FFMS_Track` obje +@@ -680,7 +680,7 @@ ### FFMS_GetTimeBase - retrieves the time base for the given track @@ -296,7 +296,7 @@ ```c++ const FFMS_TrackTimeBase *FFMS_GetTimeBase(FFMS_Track *T); ``` -@@ -694,7 +694,7 @@ Note that it is only meaningful for vide +@@ -689,7 +689,7 @@ ### FFMS_WriteTimecodes - writes timecodes for the given track to disk @@ -305,7 +305,7 @@ ```c++ int FFMS_WriteTimecodes(FFMS_Track *T, const char *TimecodeFile, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -720,14 +720,14 @@ Returns non-0 and sets `ErrorMsg` on fai +@@ -715,14 +715,14 @@ ### FFMS_DefaultAudioFilename - default callback for audio filename generation @@ -322,7 +322,7 @@ ```c++ FFMS_Indexer *FFMS_CreateIndexer(const char *SourceFile, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -741,7 +741,7 @@ Returns `NULL` and sets `ErrorMsg` on fa +@@ -736,7 +736,7 @@ ### FFMS_CreateIndexerWithDemuxer - creates an indexer object for the given file, using the given source module @@ -331,7 +331,7 @@ ```c++ FFMS_Indexer *FFMS_CreateIndexerWithDemuxer(const char *SourceFile, int Demuxer, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -758,7 +758,7 @@ Returns `NULL` and sets `ErrorMsg` on fa +@@ -753,7 +753,7 @@ ### FFMS_DoIndexing2 - indexes the file represented by an indexer object @@ -340,7 +340,7 @@ ```c++ FFMS_Index *FFMS_DoIndexing2(FFMS_Indexer *Indexer, int ErrorHandling, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -788,7 +788,7 @@ Returns `NULL` and sets `ErrorMsg` on fa +@@ -783,7 +783,7 @@ ### FFMS_TrackIndexSettings - enable or disable indexing of a track @@ -349,7 +349,7 @@ ```c++ void FFMS_TrackIndexSettings(FFMS_Indexer *Indexer, int Track, int Index, int Dump); ``` -@@ -816,7 +816,7 @@ By default, no tracks are dumped. +@@ -811,7 +811,7 @@ ### FFMS_TrackTypeIndexSettings - enable or disable indexing of a tracks of a given type @@ -358,7 +358,7 @@ ```c++ void FFMS_TrackTypeIndexSettings(FFMS_Indexer *Indexer, int TrackType, int Index, int Dump); ``` -@@ -825,7 +825,7 @@ Like [FFMS_TrackIndexSettings][TrackInde +@@ -820,7 +820,7 @@ ### FFMS_SetAudioNameCallback - choose the filename for audio track dumping @@ -367,7 +367,7 @@ ```c++ void FFMS_SetAudioNameCallback(FFMS_Indexer *Indexer, TAudioNameCallback ANC, void *ANCPrivate); ``` -@@ -859,7 +859,7 @@ Most of the parameters may seem pointles +@@ -854,7 +854,7 @@ ### FFMS_SetProgressCallback - set callback function for indexing progress updates @@ -376,7 +376,7 @@ ```c++ void FFMS_SetProgressCallback(FFMS_Indexer *Indexer, TIndexCallback IC, void *ICPrivate); ``` -@@ -879,7 +879,7 @@ Return 0 from the callback function to c +@@ -874,7 +874,7 @@ ### FFMS_CancelIndexing - destroys the given indexer object @@ -385,7 +385,7 @@ ```c++ void FFMS_CancelIndexing(FFMS_Indexer *Indexer); ``` -@@ -887,7 +887,7 @@ Destroys the given `FFMS_Indexer` object +@@ -882,7 +882,7 @@ ### FFMS_ReadIndex - reads an index file from disk @@ -394,7 +394,7 @@ ```c++ FFMS_Index *FFMS_ReadIndex(const char *IndexFile, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -896,7 +896,7 @@ Returns the `FFMS_Index` on success; ret +@@ -901,7 +901,7 @@ ### FFMS_IndexBelongsToFile - check if a given index belongs to a given file @@ -403,7 +403,7 @@ ```c++ int FFMS_IndexBelongsToFile(FFMS_Index *Index, const char *SourceFile, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -917,7 +917,7 @@ Returns non-0 and sets `ErrorMsg` otherw +@@ -922,7 +922,7 @@ ### FFMS_WriteIndex - writes an index object to disk @@ -412,7 +412,7 @@ ```c++ int FFMS_WriteIndex(const char *IndexFile, FFMS_Index *TrackIndices, FFMS_ErrorInfo *ErrorInfo); ``` -@@ -926,7 +926,7 @@ Returns 0 on success; returns non-0 and +@@ -950,7 +950,7 @@ ### FFMS_GetPixFmt - gets a colorspace identifier from a colorspace name @@ -421,7 +421,7 @@ ```c++ int FFMS_GetPixFmt(const char *Name); ``` -@@ -948,7 +948,7 @@ Returns the integer constant representin +@@ -972,7 +972,7 @@ ### FFMS_GetPresentSources - checks what source modules the library was compiled with @@ -430,7 +430,7 @@ ```c++ int FFMS_GetPresentSources(); ``` -@@ -956,7 +956,7 @@ Checks which source modules the library +@@ -980,7 +980,7 @@ ### FFMS_GetEnabledSources - checks what source modules are actually available for use @@ -439,7 +439,7 @@ ```c++ int FFMS_GetEnabledSources(); ``` -@@ -964,7 +964,7 @@ Does the same thing as [FFMS_GetPresentS +@@ -988,7 +988,7 @@ ### FFMS_GetVersion - returns FFMS_VERSION constant @@ -448,7 +448,7 @@ ```c++ int FFMS_GetVersion(); ``` -@@ -972,7 +972,7 @@ Returns the FFMS_VERSION constant as def +@@ -996,7 +996,7 @@ ### FFMS_MakeIndex - indexes a given source file [DEPRECATED] @@ -457,7 +457,7 @@ ```c++ FFMS_Index *FFMS_MakeIndex(const char *SourceFile, int IndexMask, int DumpMask, TAudioNameCallback ANC, void *ANCPrivate, int ErrorHandling, -@@ -1071,7 +1071,7 @@ Returns `NULL` and sets `ErrorMsg` on fa +@@ -1095,7 +1095,7 @@ ### FFMS_DoIndexing - indexes the file represented by an indexer object [DEPRECATED] diff -Nru ffms2-2.22/debian/rules ffms2-2.23/debian/rules --- ffms2-2.22/debian/rules 2015-07-13 16:20:37.000000000 +0000 +++ ffms2-2.23/debian/rules 2016-10-20 18:37:19.000000000 +0000 @@ -3,7 +3,7 @@ export DEB_LDFLAGS_MAINT_APPEND=-Wl,--as-needed %: - dh $@ --parallel --with autoreconf + dh $@ override_dh_auto_configure: dh_auto_configure -- --enable-shared --disable-silent-rules diff -Nru ffms2-2.22/doc/ffms2-api.md ffms2-2.23/doc/ffms2-api.md --- ffms2-2.22/doc/ffms2-api.md 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/doc/ffms2-api.md 2016-10-18 16:54:00.000000000 +0000 @@ -186,10 +186,11 @@ [Init]: #ffms_init---initializes-the-library ```c++ -void FFMS_Init(int Unused, int UseUTF8Paths); +void FFMS_Init(int Unused, int Unused2); ``` Initializes the FFMS2 library. This function must be called once at the start of your program, before doing any other FFMS2 function calls. +This function is threadsafe and will only run once. #### Arguments @@ -197,15 +198,9 @@ This argument is no longer used and is left only for API/ABI compatibility. Pass 0. -##### `int UseUTF8Paths` +##### `int Unused2` -Controls filename handling on Windows; on all other operating systems this parameter does nothing and should be ignored. - -On Windows, setting this parameter to a true value will make FFMS assume that all filename strings passed to it are UTF-8 encoded; setting it to false will make it assume filenames are in the system default codepage for non-Unicode programs. -Setting this to true is one of two known ways to make FFMS2 open files with filenames containing characters that are not expressible in said codepage; the other is using the short (DOS 8.3 notation) filename. -You can use the Win32 API function `WideCharToMultiByte()` to convert your `wchar_t*` Unicode strings to UTF-8 in `char*`, if necessary. - -Prior to API version 2.14.0.0 this functionality was a compile-time option and was controlled via `FFMS_USE_UTF8_PATHS`. +This argument is also no longer used and is left only for API/ABI compatibility. Pass 0. ### FFMS_GetLogLevel - gets FFmpeg message level @@ -894,6 +889,16 @@ Attempts to read indexing information from the given `IndexFile`, which can be an absolute or relative path. Returns the `FFMS_Index` on success; returns `NULL` and sets `ErrorMsg` on failure. +### FFMS_ReadIndexFromBuffer - reads an index from a user-supplied buffer + +[ReadIndexFromBuffer]: #ffms_readindexfrombffer---reads-an-index-from-a-user-supplied-buffer +```c++ +FFMS_Index *FFMS_ReadIndexFromBuffer(const uint8_t *Buffer, size_t Size, FFMS_ErrorInfo *ErrorInfo); +``` + +Attempts to read indexing information from the super supplied buffer, `Buffer, of size `Size`. +Returns the `FFMS_Index` on success; returns `NULL` and sets `ErrorMsg` on failure. + ### FFMS_IndexBelongsToFile - check if a given index belongs to a given file [IndexBelongsToFile]: #ffms_indexbelongstofile---check-if-a-given-index-belongs-to-a-given-file @@ -924,6 +929,25 @@ Writes the indexing information from the given `FFMS_Index` to the given `IndexFile` (which can be an absolute or relative path; it will be truncated and overwritten if it already exists). Returns 0 on success; returns non-0 and sets `ErrorMsg` on failure. +### FFMS_WriteIndexToBuffer - writes an index to memory + +[WriteIndexToBuffer]: #ffms_writeindextobuffer---writes-an-index-to-memory +```c++ +int FFMS_WriteIndexToBuffer(uint8_t **BufferPtr, size_t *Size, FFMS_Index *Index, FFMS_ErrorInfo *ErrorInfo) +``` + +Writes the indexing information from the given `FFMS_Index` to memory, and sets `BufferPtr` to point to the buffer, and `Size` to the size of the returned buffer. Users are required to free the resulting buffer with [FFMS_FreeIndexBuffer][FreeIndexBuffer]. +Returns 0 on success; returns non-0 and sets `ErrorMsg` on failure. + +### FFMS_FreeIndexBuffer - frees a buffer allocated by [FFMS_WriteIndexToBuffer][WriteIndexToBuffer] + +[FreeIndexBuffer]: #ffms_freeindexbuffer---frees-a-buffer-alloctaed-by-ffms_writeindextobuffer +```c++ +void FFMS_FreeIndexBuffer(uint8_t **BufferPtr) +``` + +Frees the buffer pointed to by `BufferPtr` and sets it to NULL. + ### FFMS_GetPixFmt - gets a colorspace identifier from a colorspace name [GetPixFmt]: #ffms_getpixfmt---gets-a-colorspace-identifier-from-a-colorspace-name diff -Nru ffms2-2.22/doc/ffms2-avisynth.md ffms2-2.23/doc/ffms2-avisynth.md --- ffms2-2.22/doc/ffms2-avisynth.md 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/doc/ffms2-avisynth.md 2016-10-18 16:54:00.000000000 +0000 @@ -222,8 +222,10 @@ Note that `SPLINE` is completely different from Avisynth's builtin Spline resizers. ##### string colorspace = "" -Convert the output from whatever it was to the given colorspace, which can be one of `YV12`, `YUY2`, `RGB24` or `RGB32`. -Setting this to an empty string (the default) means keeping the same colorspace as the input. +Convert the output from whatever it was to the given colorspace, which can be one of `YV12`, `YV16`, `YV24`, `Y8`, `YUY2`, `YV411`, `YUV9`, `RGB24` or `RGB32`. +They can also be referred to with the more systematic names of `YUVsssPx`, `YUVAsssPx`, `Yx`, `RGBPx` or `RGBAPx` where `x` is the desired bitdepth and `sss` represents the subsampling. Formats with an `A` also have an alpha channel. +Examples: `YUV420P8`, `RGBAP16`, `Y16` +Setting this to an empty string (the default) means keeping the same colorspace as the input or in case it's not supported it'll be converted to the closest existing match. ##### bool utf8 = false Does the same thing as in `FFIndex()`; see that function for details. diff -Nru ffms2-2.22/doc/ffms2-changelog.md ffms2-2.23/doc/ffms2-changelog.md --- ffms2-2.22/doc/ffms2-changelog.md 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/doc/ffms2-changelog.md 2016-10-18 16:54:00.000000000 +0000 @@ -1,5 +1,16 @@ # FFmpegSource2 Changelog +- 2.23 + - Updated FFmpeg APIs used (Daemon404) + - Added new API that can read/write indexes to a memory buffer (Daemon404) + - Added support for high bitdepth output in Avisynth+ (Myrsloik) + - vapoursource: Add nfMakeLinear flag to better performance in most cases (Myrsloik) + - Remove bad colorspace matrix guessing for YUV (Myrsloik) + - Tell libavformat to discard packets we don't want (Daemon404) + - Restore original FFCopyrightInfringement behavior (Myrsloik) + - Make FFMS_Init threadsafe (Daemon404) + - Support latest libav* APIs (Daemon404) + - 2.22 - Fix possible off by 1 frame until first seek issue introduced in 2.21 (Myrsloik) - avisynth: Make FFMS2 a shorter alias for FFmpegSource2 to save some typing (Myrsloik) diff -Nru ffms2-2.22/include/ffmscompat.h ffms2-2.23/include/ffmscompat.h --- ffms2-2.22/include/ffmscompat.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/include/ffmscompat.h 2016-10-18 16:54:00.000000000 +0000 @@ -21,6 +21,12 @@ #ifndef FFMSCOMPAT_H #define FFMSCOMPAT_H +#ifdef __GNUC__ +# define ffms_used __attribute__((used)) +#else +# define ffms_used +#endif + // Defaults to libav compatibility, uncomment (when building with msvc) to force ffmpeg compatibility. //#define FFMS_USE_FFMPEG_COMPAT @@ -71,6 +77,16 @@ # define av_frame_free avcodec_free_frame # define av_frame_unref avcodec_get_frame_defaults # endif +# if VERSION_CHECK(LIBAVCODEC_VERSION_INT, <, 57, 8, 0, 57, 12, 100) +# define av_packet_unref av_free_packet +# endif +# if VERSION_CHECK(LIBAVCODEC_VERSION_INT, <, 57, 14, 0, 57, 33, 100) +# define FFMSCODEC codec +static ffms_used int make_context(AVCodecContext *dst, AVStream *src) { return avcodec_copy_context(dst, src->codec); } +# else +# define FFMSCODEC codecpar +static ffms_used int make_context(AVCodecContext *dst, AVStream *src) { return avcodec_parameters_to_context(dst, src->codecpar); } +# endif #endif #ifdef LIBAVUTIL_VERSION_INT @@ -85,9 +101,13 @@ # if VERSION_CHECK(LIBAVUTIL_VERSION_INT, <, 51, 42, 0, 51, 74, 100) # define AVPixelFormat PixelFormat # define FFMS_PIX_FMT(x) PIX_FMT_##x -# define FFMS_PIX_FMT_FLAG(x) PIX_FMT_##x # else # define FFMS_PIX_FMT(x) AV_PIX_FMT_##x +# endif + +# if VERSION_CHECK(LIBAVUTIL_VERSION_INT, <, 52, 11, 0, 52, 32, 100) +# define FFMS_PIX_FMT_FLAG(x) PIX_FMT_##x +# else # define FFMS_PIX_FMT_FLAG(x) AV_PIX_FMT_FLAG_##x # endif diff -Nru ffms2-2.22/include/ffms.h ffms2-2.23/include/ffms.h --- ffms2-2.22/include/ffms.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/include/ffms.h 2016-10-18 16:54:00.000000000 +0000 @@ -22,9 +22,10 @@ #define FFMS_H // Version format: major - minor - micro - bump -#define FFMS_VERSION ((2 << 24) | (22 << 16) | (0 << 8) | 0) +#define FFMS_VERSION ((2 << 24) | (23 << 16) | (0 << 8) | 0) #include +#include /******** @@ -64,7 +65,7 @@ #endif // And now for some symbol hide-and-seek... -#if defined(_WIN32) // MSVC +#if defined(_WIN32) && !defined(FFMS_STATIC) // MSVC # if defined(FFMS_EXPORTS) // building the FFMS2 library itself, with visible API symbols # define FFMS_API(ret) FFMS_EXTERN_C __declspec(dllexport) ret FFMS_CC # define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED __declspec(dllexport) ret FFMS_CC @@ -400,7 +401,7 @@ // Most functions return 0 on success // Functions without error message output can be assumed to never fail in a graceful way -FFMS_API(void) FFMS_Init(int CPUFeatures, int UseUTF8Paths); +FFMS_API(void) FFMS_Init(int, int); FFMS_API(int) FFMS_GetVersion(); FFMS_API(int) FFMS_GetLogLevel(); FFMS_API(void) FFMS_SetLogLevel(int Level); @@ -451,8 +452,11 @@ FFMS_API(FFMS_Index *) FFMS_DoIndexing2(FFMS_Indexer *Indexer, int ErrorHandling, FFMS_ErrorInfo *ErrorInfo); /* Introduced in FFMS_VERSION ((2 << 24) | (21 << 16) | (0 << 8) | 0) */ FFMS_API(void) FFMS_CancelIndexing(FFMS_Indexer *Indexer); FFMS_API(FFMS_Index *) FFMS_ReadIndex(const char *IndexFile, FFMS_ErrorInfo *ErrorInfo); +FFMS_API(FFMS_Index *) FFMS_ReadIndexFromBuffer(const uint8_t *Buffer, size_t Size, FFMS_ErrorInfo *ErrorInfo); FFMS_API(int) FFMS_IndexBelongsToFile(FFMS_Index *Index, const char *SourceFile, FFMS_ErrorInfo *ErrorInfo); FFMS_API(int) FFMS_WriteIndex(const char *IndexFile, FFMS_Index *Index, FFMS_ErrorInfo *ErrorInfo); +FFMS_API(int) FFMS_WriteIndexToBuffer(uint8_t **BufferPtr, size_t *Size, FFMS_Index *Index, FFMS_ErrorInfo *ErrorInfo); +FFMS_API(void) FFMS_FreeIndexBuffer(uint8_t **BufferPtr); FFMS_API(int) FFMS_GetPixFmt(const char *Name); FFMS_API(int) FFMS_GetPresentSources(); FFMS_API(int) FFMS_GetEnabledSources(); diff -Nru ffms2-2.22/src/avisynth/avisynth.cpp ffms2-2.23/src/avisynth/avisynth.cpp --- ffms2-2.22/src/avisynth/avisynth.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/avisynth/avisynth.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -336,7 +336,9 @@ static AVSValue __cdecl CreateFFCopyrightInfringement(AVSValue Args, void* UserData, IScriptEnvironment* Env) { const char *ArgNames[] = { "source" }; - return Env->Invoke("FFVideoSource", Args, ArgNames); + Env->Invoke("FFIndex", Args, ArgNames); + AVSValue ExArgs[2] = { Env->Invoke("FFVideoSource", Args, ArgNames), Env->Invoke("FFAudioSource", Args, ArgNames) }; + return Env->Invoke("AudioDubEx", AVSValue(ExArgs, sizeof(ExArgs) / sizeof(ExArgs[0]))); } static AVSValue __cdecl FFGetLogLevel(AVSValue Args, void* UserData, IScriptEnvironment* Env) { @@ -368,11 +370,6 @@ Env->AddFunction("FFImageSource", "[source]s[width]i[height]i[resizer]s[colorspace]s[utf8]b[varprefix]s", CreateFFImageSource, nullptr); Env->AddFunction("FFCopyrightInfringement", "[source]s", CreateFFCopyrightInfringement, nullptr); - /* - function FFInfo(clip c, bool "framenum", bool "frametype", bool "cfrtime", bool "vfrtime", string "varprefix", - \ bool "colorspace", bool "colorrange", bool "cropping", bool "sar", bool "version", bool "showprefix") - */ - Env->AddFunction("FFGetLogLevel", "", FFGetLogLevel, nullptr); Env->AddFunction("FFSetLogLevel", "i", FFSetLogLevel, nullptr); Env->AddFunction("FFGetVersion", "", FFGetVersion, nullptr); diff -Nru ffms2-2.22/src/avisynth/avssources.cpp ffms2-2.23/src/avisynth/avssources.cpp --- ffms2-2.22/src/avisynth/avssources.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/avisynth/avssources.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -1,4 +1,4 @@ -// Copyright (c) 2007-2015 Fredrik Mellbin +// Copyright (c) 2007-2016 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 @@ -23,25 +23,26 @@ #include "../core/utils.h" #include +#include -static AVPixelFormat CSNameToPIXFMT(const char *CSName, AVPixelFormat Default) { +static AVPixelFormat CSNameToPIXFMT(const char *CSName, AVPixelFormat Default, bool HighBitDepth) { if (!CSName) return FFMS_PIX_FMT(NONE); std::string s = CSName; std::transform(s.begin(), s.end(), s.begin(), toupper); if (s == "") return Default; - if (s == "YUV9") + if (s == "YUV9" || s == "YUV410P8") return FFMS_PIX_FMT(YUV410P); - if (s == "YV411") + if (s == "YV411" || s == "YUV411P8") return FFMS_PIX_FMT(YUV411P); - if (s == "YV12") + if (s == "YV12" || s == "YUV420P8") return FFMS_PIX_FMT(YUV420P); - if (s == "YV16") + if (s == "YV16" || s == "YUV422P8") return FFMS_PIX_FMT(YUV422P); - if (s == "YV24") + if (s == "YV24" || s == "YUV444P8") return FFMS_PIX_FMT(YUV444P); - if (s == "Y8") + if (s == "Y8" || s == "GRAY8") return FFMS_PIX_FMT(GRAY8); if (s == "YUY2") return FFMS_PIX_FMT(YUYV422); @@ -49,6 +50,44 @@ return FFMS_PIX_FMT(BGR24); if (s == "RGB32") return FFMS_PIX_FMT(RGB32); + if (HighBitDepth) { + if (s == "YUVA420P8") + return FFMS_PIX_FMT(YUVA420P); + if (s == "YUVA422P8") + return FFMS_PIX_FMT(YUVA422P); + if (s == "YUVA444P8") + return FFMS_PIX_FMT(YUVA444P); + if (s == "YUV420P16") + return FFMS_PIX_FMT(YUV420P16); + if (s == "YUVA420P16") + return FFMS_PIX_FMT(YUVA420P16); + if (s == "YUV422P16") + return FFMS_PIX_FMT(YUV422P16); + if (s == "YUVA422P16") + return FFMS_PIX_FMT(YUVA422P16); + if (s == "YUV444P16") + return FFMS_PIX_FMT(YUV444P16); + if (s == "YUVA444P16") + return FFMS_PIX_FMT(YUVA444P16); + if (s == "YUV420P10") + return FFMS_PIX_FMT(YUV420P10); + if (s == "YUVA420P10") + return FFMS_PIX_FMT(YUVA420P10); + if (s == "YUV422P10") + return FFMS_PIX_FMT(YUV422P10); + if (s == "YUVA422P10") + return FFMS_PIX_FMT(YUVA422P10); + if (s == "YUV444P10") + return FFMS_PIX_FMT(YUV444P10); + if (s == "YUVA444P10") + return FFMS_PIX_FMT(YUVA444P10); + if (s == "RGBP16") + return FFMS_PIX_FMT(GBRP16); + if (s == "RGBAP16") + return FFMS_PIX_FMT(GBRAP16); + if (s == "Y16" || s == "GRAY16") + return FFMS_PIX_FMT(GRAY16); + } return FFMS_PIX_FMT(NONE); } @@ -64,6 +103,11 @@ { VI = {}; + // check if the two functions we need for many bits are present + VI.pixel_type = VideoInfo::CS_Y16; + HighBitDepth = (VI.ComponentSize() == 2 && VI.IsY()); + VI.pixel_type = VideoInfo::CS_UNKNOWN; + ErrorInfo E; V = FFMS_CreateVideoSource(SourceFile, Track, Index, Threads, SeekMode, &E); if (!V) @@ -198,6 +242,20 @@ FFMS_DestroyVideoSource(V); } +static int GetSubSamplingH(const VideoInfo &vi) { + if (vi.IsYUV() && vi.IsPlanar()) + return vi.GetPlaneHeightSubsampling(PLANAR_U); + else + return 0; +} + +static int GetSubSamplingW(const VideoInfo &vi) { + if (vi.IsYUV() && vi.IsPlanar()) + return vi.GetPlaneWidthSubsampling(PLANAR_U); + else + return 0; +} + void AvisynthVideoSource::InitOutputFormat( int ResizeToWidth, int ResizeToHeight, const char *ResizerName, const char *ConvertToFormatName, IScriptEnvironment *Env) { @@ -208,25 +266,50 @@ if (!F) Env->ThrowError("FFVideoSource: %s", E.Buffer); - int TargetFormats[9]; - TargetFormats[0] = FFMS_GetPixFmt("yuv410p"); - TargetFormats[1] = FFMS_GetPixFmt("yuv411p"); - TargetFormats[2] = FFMS_GetPixFmt("yuv420p"); - TargetFormats[3] = FFMS_GetPixFmt("yuv422p"); - TargetFormats[4] = FFMS_GetPixFmt("yuv444p"); - TargetFormats[5] = FFMS_GetPixFmt("gray8"); - TargetFormats[6] = FFMS_GetPixFmt("yuyv422"); - TargetFormats[7] = FFMS_GetPixFmt("bgra"); - TargetFormats[8] = -1; + std::vector TargetFormats; + if (HighBitDepth) { + TargetFormats.push_back(FFMS_GetPixFmt("yuv420p16")); + TargetFormats.push_back(FFMS_GetPixFmt("yuva420p16")); + TargetFormats.push_back(FFMS_GetPixFmt("yuv422p16")); + TargetFormats.push_back(FFMS_GetPixFmt("yuva422p16")); + TargetFormats.push_back(FFMS_GetPixFmt("yuv444p16")); + TargetFormats.push_back(FFMS_GetPixFmt("yuva444p16")); + TargetFormats.push_back(FFMS_GetPixFmt("yuv420p10")); + TargetFormats.push_back(FFMS_GetPixFmt("yuva420p10")); + TargetFormats.push_back(FFMS_GetPixFmt("yuv422p10")); + TargetFormats.push_back(FFMS_GetPixFmt("yuva422p10")); + TargetFormats.push_back(FFMS_GetPixFmt("yuv444p10")); + TargetFormats.push_back(FFMS_GetPixFmt("yuva444p10")); + TargetFormats.push_back(FFMS_GetPixFmt("gbrp16")); + TargetFormats.push_back(FFMS_GetPixFmt("gbrap16")); + TargetFormats.push_back(FFMS_GetPixFmt("gray16")); + TargetFormats.push_back(FFMS_GetPixFmt("yuva420p")); + TargetFormats.push_back(FFMS_GetPixFmt("yuva422p")); + TargetFormats.push_back(FFMS_GetPixFmt("yuva444p")); + } + TargetFormats.push_back(FFMS_GetPixFmt("yuv410p")); + TargetFormats.push_back(FFMS_GetPixFmt("yuv411p")); + TargetFormats.push_back(FFMS_GetPixFmt("yuv420p")); + TargetFormats.push_back(FFMS_GetPixFmt("yuv422p")); + TargetFormats.push_back(FFMS_GetPixFmt("yuv444p")); + TargetFormats.push_back(FFMS_GetPixFmt("gray8")); + TargetFormats.push_back(FFMS_GetPixFmt("yuyv422")); + TargetFormats.push_back(FFMS_GetPixFmt("bgra")); + + // Remove unsupported formats from list so they don't appear as an early termination + TargetFormats.erase(std::remove(TargetFormats.begin(), TargetFormats.end(), -1), TargetFormats.end()); + + TargetFormats.push_back(-1); // PIX_FMT_NV21 is misused as a return value different to the defined ones in the function - AVPixelFormat TargetPixelFormat = CSNameToPIXFMT(ConvertToFormatName, FFMS_PIX_FMT(NV21)); + AVPixelFormat TargetPixelFormat = CSNameToPIXFMT(ConvertToFormatName, FFMS_PIX_FMT(NV21), HighBitDepth); if (TargetPixelFormat == FFMS_PIX_FMT(NONE)) Env->ThrowError("FFVideoSource: Invalid colorspace name specified"); if (TargetPixelFormat != FFMS_PIX_FMT(NV21)) { - TargetFormats[0] = TargetPixelFormat; - TargetFormats[1] = -1; + TargetFormats.clear(); + TargetFormats.push_back(TargetPixelFormat); + TargetFormats.push_back(-1); } if (ResizeToWidth <= 0) @@ -239,16 +322,17 @@ if (Resizer == 0) Env->ThrowError("FFVideoSource: Invalid resizer name specified"); - if (FFMS_SetOutputFormatV2(V, TargetFormats, + if (FFMS_SetOutputFormatV2(V, TargetFormats.data(), ResizeToWidth, ResizeToHeight, Resizer, &E)) Env->ThrowError("FFVideoSource: No suitable output format found"); F = FFMS_GetFrame(V, 0, &E); - TargetFormats[0] = F->ConvertedPixelFormat; - TargetFormats[1] = -1; + TargetFormats.clear(); + TargetFormats.push_back(F->ConvertedPixelFormat); + TargetFormats.push_back(-1); // This trick is required to first get the "best" default format and then set only that format as the output - if (FFMS_SetOutputFormatV2(V, TargetFormats, + if (FFMS_SetOutputFormatV2(V, TargetFormats.data(), ResizeToWidth, ResizeToHeight, Resizer, &E)) Env->ThrowError("FFVideoSource: No suitable output format found"); @@ -256,10 +340,16 @@ if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuvj420p") || F->ConvertedPixelFormat == FFMS_GetPixFmt("yuv420p")) VI.pixel_type = VideoInfo::CS_I420; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuva420p")) + VI.pixel_type = VideoInfo::CS_YUVA420; else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuvj422p") || F->ConvertedPixelFormat == FFMS_GetPixFmt("yuv422p")) VI.pixel_type = VideoInfo::CS_YV16; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuva422p")) + VI.pixel_type = VideoInfo::CS_YUVA422; else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuvj444p") || F->ConvertedPixelFormat == FFMS_GetPixFmt("yuv444p")) VI.pixel_type = VideoInfo::CS_YV24; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuva444p")) + VI.pixel_type = VideoInfo::CS_YUVA444; else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuv411p")) VI.pixel_type = VideoInfo::CS_YV411; else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuv410p")) @@ -272,6 +362,36 @@ VI.pixel_type = VideoInfo::CS_BGR32; else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("bgr24")) VI.pixel_type = VideoInfo::CS_BGR24; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuv420p16")) + VI.pixel_type = VideoInfo::CS_YUV420P16; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuva420p16")) + VI.pixel_type = VideoInfo::CS_YUVA420P16; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuv422p16")) + VI.pixel_type = VideoInfo::CS_YUV422P16; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuva422p16")) + VI.pixel_type = VideoInfo::CS_YUVA422P16; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuv444p16")) + VI.pixel_type = VideoInfo::CS_YUV444P16; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuva444p16")) + VI.pixel_type = VideoInfo::CS_YUVA444P16; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuv420p10")) + VI.pixel_type = VideoInfo::CS_YUV420P10; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuva420p10")) + VI.pixel_type = VideoInfo::CS_YUVA420P10; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuv422p10")) + VI.pixel_type = VideoInfo::CS_YUV422P10; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuva422p10")) + VI.pixel_type = VideoInfo::CS_YUVA422P10; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuv444p10")) + VI.pixel_type = VideoInfo::CS_YUV444P10; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("yuva444p10")) + VI.pixel_type = VideoInfo::CS_YUVA444P10; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("gbrp16")) + VI.pixel_type = VideoInfo::CS_RGBP16; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("gbrap16")) + VI.pixel_type = VideoInfo::CS_RGBAP16; + else if (F->ConvertedPixelFormat == FFMS_GetPixFmt("gray16")) + VI.pixel_type = VideoInfo::CS_Y16; else Env->ThrowError("FFVideoSource: No suitable output format found"); @@ -293,45 +413,39 @@ VI.width = F->ScaledWidth; VI.height = F->ScaledHeight; - // Crop to obey avisynth's even width/height requirements - if (VI.pixel_type == VideoInfo::CS_I420) { - VI.height -= VI.height & 1; - VI.width -= VI.width & 1; - } - - if (VI.pixel_type == VideoInfo::CS_YUY2) { - VI.width -= VI.width & 1; - } - - if (RFFMode > 0) { - VI.height -= VI.height & 1; - } + // Crop to obey subsampling width/height requirements + VI.width -= VI.width % (1 << GetSubSamplingW(VI)); + VI.height -= VI.height % (1 << (GetSubSamplingH(VI) + (RFFMode > 0 ? 1 : 0))); } -static void BlitPlane(const FFMS_Frame *Frame, PVideoFrame &Dst, IScriptEnvironment *Env, int Plane) { - int PlaneId = 1 << Plane; +static void BlitPlane(const FFMS_Frame *Frame, PVideoFrame &Dst, IScriptEnvironment *Env, int Plane, int PlaneId) { Env->BitBlt(Dst->GetWritePtr(PlaneId), Dst->GetPitch(PlaneId), Frame->Data[Plane], Frame->Linesize[Plane], Dst->GetRowSize(PlaneId), Dst->GetHeight(PlaneId)); } void AvisynthVideoSource::OutputFrame(const FFMS_Frame *Frame, PVideoFrame &Dst, IScriptEnvironment *Env) { - if (VI.pixel_type == VideoInfo::CS_I420) { - BlitPlane(Frame, Dst, Env, 0); - BlitPlane(Frame, Dst, Env, 1); - BlitPlane(Frame, Dst, Env, 2); + if (VI.IsPlanar()) { + BlitPlane(Frame, Dst, Env, 0, VI.IsRGB() ? PLANAR_G : PLANAR_Y); + if (HighBitDepth ? !VI.IsY() : !VI.IsY8()) { + BlitPlane(Frame, Dst, Env, 1, VI.IsRGB() ? PLANAR_B : PLANAR_U); + BlitPlane(Frame, Dst, Env, 2, VI.IsRGB() ? PLANAR_R : PLANAR_V); + } + if (VI.IsYUVA() || VI.IsPlanarRGBA()) + BlitPlane(Frame, Dst, Env, 3, PLANAR_A); } else if (VI.IsYUY2()) { - BlitPlane(Frame, Dst, Env, 0); - } else { // RGB + BlitPlane(Frame, Dst, Env, 0, 0); + } else if (VI.IsRGB24() || VI.IsRGB32()) { Env->BitBlt( Dst->GetWritePtr() + Dst->GetPitch() * (Dst->GetHeight() - 1), -Dst->GetPitch(), Frame->Data[0], Frame->Linesize[0], Dst->GetRowSize(), Dst->GetHeight()); - } + } else { + assert(false); + } } -static void BlitField(const FFMS_Frame *Frame, PVideoFrame &Dst, IScriptEnvironment *Env, int Plane, int Field) { - int PlaneId = 1 << Plane; +static void BlitField(const FFMS_Frame *Frame, PVideoFrame &Dst, IScriptEnvironment *Env, int Plane, int PlaneId, int Field) { Env->BitBlt( Dst->GetWritePtr(PlaneId) + Dst->GetPitch(PlaneId) * Field, Dst->GetPitch(PlaneId) * 2, Frame->Data[Plane] + Frame->Linesize[Plane] * Field, Frame->Linesize[Plane] * 2, @@ -339,20 +453,25 @@ } void AvisynthVideoSource::OutputField(const FFMS_Frame *Frame, PVideoFrame &Dst, int Field, IScriptEnvironment *Env) { - const FFMS_Frame *SrcPicture = (Frame); - - if (VI.pixel_type == VideoInfo::CS_I420) { - BlitField(Frame, Dst, Env, 0, Field); - BlitField(Frame, Dst, Env, 1, Field); - BlitField(Frame, Dst, Env, 2, Field); + const FFMS_Frame *SrcPicture = Frame; + if (VI.IsPlanar()) { + BlitField(Frame, Dst, Env, 0, VI.IsRGB() ? PLANAR_G : PLANAR_Y, Field); + if (HighBitDepth ? !VI.IsY() : !VI.IsY8()) { + BlitField(Frame, Dst, Env, 1, VI.IsRGB() ? PLANAR_B : PLANAR_U, Field); + BlitField(Frame, Dst, Env, 2, VI.IsRGB() ? PLANAR_R : PLANAR_V, Field); + } + if (VI.IsYUVA() || VI.IsPlanarRGBA()) + BlitField(Frame, Dst, Env, 3, PLANAR_A, Field); } else if (VI.IsYUY2()) { - BlitField(Frame, Dst, Env, 0, Field); - } else { // RGB + BlitField(Frame, Dst, Env, 0, 0, Field); + } else if (VI.IsRGB24() || VI.IsRGB32()) { Env->BitBlt( Dst->GetWritePtr() + Dst->GetPitch() * (Dst->GetHeight() - 1 - Field), -Dst->GetPitch() * 2, SrcPicture->Data[0] + SrcPicture->Linesize[0] * Field, SrcPicture->Linesize[0] * 2, Dst->GetRowSize(), Dst->GetHeight() / 2); - } + } else { + assert(false); + } } PVideoFrame AvisynthVideoSource::GetFrame(int n, IScriptEnvironment *Env) { diff -Nru ffms2-2.22/src/avisynth/avssources.h ffms2-2.23/src/avisynth/avssources.h --- ffms2-2.22/src/avisynth/avssources.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/avisynth/avssources.h 2016-10-18 16:54:00.000000000 +0000 @@ -41,6 +41,7 @@ }; VideoInfo VI; + bool HighBitDepth; FFMS_VideoSource *V; int FPSNum; int FPSDen; diff -Nru ffms2-2.22/src/core/audiosource.cpp ffms2-2.23/src/core/audiosource.cpp --- ffms2-2.22/src/core/audiosource.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/audiosource.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -185,7 +185,7 @@ // Cache stores audio in the output format, so clear it and reopen the file Cache.clear(); PacketNumber = 0; - ReopenFile(); + OpenFile(); FlushBuffers(CodecContext); BytesPerSample = av_get_bytes_per_sample(static_cast(opt.SampleFormat)) * av_get_channel_layout_nb_channels(opt.ChannelLayout); @@ -391,7 +391,7 @@ PacketNumber = NewPacketNumber; CurrentSample = -1; DecodeFrame.reset(); - avcodec_flush_buffers(CodecContext); + FlushBuffers(CodecContext); Seek(); } } diff -Nru ffms2-2.22/src/core/audiosource.h ffms2-2.23/src/core/audiosource.h --- ffms2-2.22/src/core/audiosource.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/audiosource.h 2016-10-18 16:54:00.000000000 +0000 @@ -92,7 +92,9 @@ // Close and reopen the source file to seek back to the beginning. Only // needs to do anything for formats that can't seek to the beginning otherwise. - virtual void ReopenFile() { } + // + // If the file is not already open, it is merely just opened. + virtual void OpenFile() { } protected: // First sample which is stored in the decoding buffer int64_t CurrentSample = -1; diff -Nru ffms2-2.22/src/core/ffms.cpp ffms2-2.23/src/core/ffms.cpp --- ffms2-2.22/src/core/ffms.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/ffms.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -26,9 +26,11 @@ #include "videoutils.h" extern "C" { +#include #include } +#include #include #include @@ -36,12 +38,9 @@ # include #endif +static std::once_flag FFmpegOnce; static bool FFmpegInited = false; -#ifdef _WIN32 -bool GlobalUseUTF8Paths = false; -#endif - #ifdef FFMS_WIN_DEBUG void av_log_windebug_callback(void* ptr, int level, const char* fmt, va_list vl) { @@ -78,16 +77,11 @@ #endif -FFMS_API(void) FFMS_Init(int, int UseUTF8Paths) { - if (!FFmpegInited) { +FFMS_API(void) FFMS_Init(int, int) { + std::call_once(FFmpegOnce, []() { av_register_all(); avformat_network_init(); RegisterCustomParsers(); -#ifdef _WIN32 - GlobalUseUTF8Paths = !!UseUTF8Paths; -#else - (void)UseUTF8Paths; -#endif #ifdef FFMS_WIN_DEBUG av_log_set_callback(av_log_windebug_callback); av_log_set_level(AV_LOG_INFO); @@ -95,7 +89,7 @@ av_log_set_level(AV_LOG_QUIET); #endif FFmpegInited = true; - } + }); } FFMS_API(int) FFMS_GetVersion() { @@ -448,6 +442,16 @@ } } +FFMS_API(FFMS_Index *) FFMS_ReadIndexFromBuffer(const uint8_t *Buffer, size_t Size, FFMS_ErrorInfo *ErrorInfo) { + ClearErrorInfo(ErrorInfo); + try { + return new FFMS_Index(Buffer, Size); + } catch (FFMS_Exception &e) { + e.CopyOut(ErrorInfo); + return nullptr; + } +} + FFMS_API(int) FFMS_IndexBelongsToFile(FFMS_Index *Index, const char *SourceFile, FFMS_ErrorInfo *ErrorInfo) { ClearErrorInfo(ErrorInfo); try { @@ -463,13 +467,34 @@ FFMS_API(int) FFMS_WriteIndex(const char *IndexFile, FFMS_Index *Index, FFMS_ErrorInfo *ErrorInfo) { ClearErrorInfo(ErrorInfo); try { - Index->WriteIndex(IndexFile); + Index->WriteIndexFile(IndexFile); } catch (FFMS_Exception &e) { return e.CopyOut(ErrorInfo); } return FFMS_ERROR_SUCCESS; } +FFMS_API(int) FFMS_WriteIndexToBuffer(uint8_t **BufferPtr, size_t *Size, FFMS_Index *Index, FFMS_ErrorInfo *ErrorInfo) { + ClearErrorInfo(ErrorInfo); + uint8_t *buf; + + try { + buf = Index->WriteIndexBuffer(Size); + } catch (FFMS_Exception &e) { + *Size = 0; + *BufferPtr = nullptr; + return e.CopyOut(ErrorInfo); + } + + *BufferPtr = buf; + + return FFMS_ERROR_SUCCESS; +} + +FFMS_API(void) FFMS_FreeIndexBuffer(uint8_t **BufferPtr) { + av_freep(BufferPtr); +} + FFMS_API(int) FFMS_GetPixFmt(const char *Name) { return av_get_pix_fmt(Name); } diff -Nru ffms2-2.22/src/core/filehandle.h ffms2-2.23/src/core/filehandle.h --- ffms2-2.22/src/core/filehandle.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/filehandle.h 2016-10-18 16:54:00.000000000 +0000 @@ -33,6 +33,7 @@ public: FileHandle(const char *filename, const char *mode, int error_source, int error_cause); + FileHandle() : avio(nullptr) {} ~FileHandle(); void Seek(int64_t offset, int origin); diff -Nru ffms2-2.22/src/core/indexing.cpp ffms2-2.23/src/core/indexing.cpp --- ffms2-2.22/src/core/indexing.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/indexing.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -35,14 +35,13 @@ } #define INDEXID 0x53920873 +#define INDEX_VERSION 1 SharedVideoContext::~SharedVideoContext() { if (CodecContext) { - avcodec_close(CodecContext); + avcodec_free_context(&CodecContext); } av_parser_close(Parser); - if (BitStreamFilter) - av_bitstream_filter_close(BitStreamFilter); } SharedAudioContext::~SharedAudioContext() { @@ -124,12 +123,11 @@ return (CFilesize == Filesize && !memcmp(CDigest, Digest, sizeof(Digest))); } -void FFMS_Index::WriteIndex(const char *IndexFile) { - ZipFile zf(IndexFile, "wb"); - +void FFMS_Index::WriteIndex(ZipFile &zf) { // Write the index file header zf.Write(INDEXID); zf.Write(FFMS_VERSION); + zf.Write(INDEX_VERSION); zf.Write(size()); zf.Write(Decoder); zf.Write(ErrorHandling); @@ -146,9 +144,21 @@ zf.Finish(); } -FFMS_Index::FFMS_Index(const char *IndexFile) { - ZipFile zf(IndexFile, "rb"); +void FFMS_Index::WriteIndexFile(const char *IndexFile) { + ZipFile zf(IndexFile, "wb"); + + WriteIndex(zf); +} + +uint8_t *FFMS_Index::WriteIndexBuffer(size_t *Size) { + ZipFile zf; + + WriteIndex(zf); + + return zf.GetBuffer(Size); +} +void FFMS_Index::ReadIndex(ZipFile &zf, const char *IndexFile) { // Read the index file header if (zf.Read() != INDEXID) throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, @@ -156,6 +166,10 @@ if (zf.Read() != FFMS_VERSION) throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, + std::string("'") + IndexFile + "' was not created with the expected FFMS2 version"); + + if (zf.Read() != INDEX_VERSION) + throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, std::string("'") + IndexFile + "' is not the expected index version"); uint32_t Tracks = zf.Read(); @@ -190,6 +204,18 @@ } } +FFMS_Index::FFMS_Index(const char *IndexFile) { + ZipFile zf(IndexFile, "rb"); + + ReadIndex(zf, IndexFile); +} + +FFMS_Index::FFMS_Index(const uint8_t *Buffer, size_t Size) { + ZipFile zf(Buffer, Size); + + ReadIndex(zf, "User supplied buffer"); +} + FFMS_Index::FFMS_Index(int64_t Filesize, uint8_t Digest[20], int Decoder, int ErrorHandling) : Decoder(Decoder) , ErrorHandling(ErrorHandling) diff -Nru ffms2-2.22/src/core/indexing.h ffms2-2.23/src/core/indexing.h --- ffms2-2.22/src/core/indexing.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/indexing.h 2016-10-18 16:54:00.000000000 +0000 @@ -27,11 +27,11 @@ #include class Wave64Writer; +class ZipFile; struct SharedVideoContext { AVCodecContext *CodecContext = nullptr; AVCodecParserContext *Parser = nullptr; - AVBitStreamFilterContext *BitStreamFilter = nullptr; ~SharedVideoContext(); }; @@ -48,6 +48,8 @@ int RefCount = 1; FFMS_Index(FFMS_Index const&) = delete; FFMS_Index& operator=(FFMS_Index const&) = delete; + void ReadIndex(ZipFile &zf, const char* IndexFile); + void WriteIndex(ZipFile &zf); public: static void CalculateFileSignature(const char *Filename, int64_t *Filesize, uint8_t Digest[20]); @@ -61,9 +63,11 @@ void Finalize(std::vector const& video_contexts); bool CompareFileSignature(const char *Filename); - void WriteIndex(const char *IndexFile); + void WriteIndexFile(const char *IndexFile); + uint8_t *WriteIndexBuffer(size_t *Size); FFMS_Index(const char *IndexFile); + FFMS_Index(const uint8_t *Buffer, size_t Size); FFMS_Index(int64_t Filesize, uint8_t Digest[20], int Decoder, int ErrorHandling); }; diff -Nru ffms2-2.22/src/core/lavfaudio.cpp ffms2-2.23/src/core/lavfaudio.cpp --- ffms2-2.22/src/core/lavfaudio.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/lavfaudio.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -29,26 +29,37 @@ std::string SourceFile; bool ReadPacket(AVPacket *) override; - void FreePacket(AVPacket *Packet) override { av_free_packet(Packet); } + void FreePacket(AVPacket *Packet) override { av_packet_unref(Packet); } void Seek() override; int64_t FrameTS(size_t Packet) const; - void ReopenFile() override { - avcodec_close(CodecContext); - avformat_close_input(&FormatContext); + void OpenFile() override { + AVCodecContext *Context = CodecContext; - LAVFOpenFile(SourceFile.c_str(), FormatContext); - CodecContext.reset(FormatContext->streams[TrackNumber]->codec); - OpenCodec(); - } + if (Context && avcodec_is_open(Context)) { + avcodec_free_context(&Context); + avformat_close_input(&FormatContext); + } - void OpenCodec() { - AVCodec *Codec = avcodec_find_decoder(CodecContext->codec_id); - if (!Codec) + LAVFOpenFile(SourceFile.c_str(), FormatContext, TrackNumber); + + AVCodec *Codec = avcodec_find_decoder(FormatContext->streams[TrackNumber]->FFMSCODEC->codec_id); + if (Codec == nullptr) throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, "Audio codec not found"); + AVCodecContext *NewContext = avcodec_alloc_context3(Codec); + if (NewContext == nullptr) + throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_ALLOCATION_FAILED, + "Could not allocate audio decoding context"); + + if (make_context(NewContext, FormatContext->streams[TrackNumber]) < 0) + throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, + "Could not copy audio codec parameters"); + + CodecContext.reset(NewContext); + if (avcodec_open2(CodecContext, Codec, nullptr) < 0) throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, "Could not open audio codec"); @@ -64,15 +75,12 @@ , LastValidTS(ffms_av_nopts_value) , SourceFile(SourceFile) { - LAVFOpenFile(SourceFile, FormatContext); - - CodecContext.reset(FormatContext->streams[TrackNumber]->codec); - assert(CodecContext); - try { - OpenCodec(); + OpenFile(); } catch (...) { + AVCodecContext *Context = CodecContext; + avcodec_free_context(&Context); avformat_close_input(&FormatContext); throw; } @@ -85,7 +93,9 @@ } FFLAVFAudio::~FFLAVFAudio() { - avcodec_close(CodecContext); + AVCodecContext *Context = CodecContext; + + avcodec_free_context(&Context); avformat_close_input(&FormatContext); } @@ -128,7 +138,7 @@ return true; } } - av_free_packet(Packet); + av_packet_unref(Packet); } return false; } diff -Nru ffms2-2.22/src/core/lavfindexer.cpp ffms2-2.23/src/core/lavfindexer.cpp --- ffms2-2.22/src/core/lavfindexer.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/lavfindexer.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -43,7 +43,7 @@ } for (unsigned int i = 0; i < FormatContext->nb_streams; i++) - if (FormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) + if (FormatContext->streams[i]->FFMSCODEC->codec_type == AVMEDIA_TYPE_VIDEO) IndexMask[i] = false; } @@ -58,11 +58,11 @@ FFMS_Sources GetSourceType() override { return FFMS_SOURCE_LAVF; } FFMS_TrackType GetTrackType(int Track) override { - return static_cast(FormatContext->streams[Track]->codec->codec_type); + return static_cast(FormatContext->streams[Track]->FFMSCODEC->codec_type); } const char *GetTrackCodec(int Track) override { - AVCodec *codec = avcodec_find_decoder(FormatContext->streams[Track]->codec->codec_id); + AVCodec *codec = avcodec_find_decoder(FormatContext->streams[Track]->FFMSCODEC->codec_id); return codec ? codec->name : nullptr; } }; @@ -76,37 +76,56 @@ for (unsigned int i = 0; i < FormatContext->nb_streams; i++) { TrackIndices->emplace_back((int64_t)FormatContext->streams[i]->time_base.num * 1000, FormatContext->streams[i]->time_base.den, - static_cast(FormatContext->streams[i]->codec->codec_type)); + static_cast(FormatContext->streams[i]->FFMSCODEC->codec_type)); - if (IndexMask.count(i) && FormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - AVCodec *VideoCodec = avcodec_find_decoder(FormatContext->streams[i]->codec->codec_id); + if (IndexMask.count(i) && FormatContext->streams[i]->FFMSCODEC->codec_type == AVMEDIA_TYPE_VIDEO) { + AVCodec *VideoCodec = avcodec_find_decoder(FormatContext->streams[i]->FFMSCODEC->codec_id); if (!VideoCodec) { + FormatContext->streams[i]->discard = AVDISCARD_ALL; IndexMask.erase(i); continue; } - if (avcodec_open2(FormatContext->streams[i]->codec, VideoCodec, nullptr) < 0) + AVCodecContext *VideoCodecContext = avcodec_alloc_context3(VideoCodec); + if (VideoCodecContext == nullptr) + throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_ALLOCATION_FAILED, + "Could not allocate video codec context"); + + if (make_context(VideoCodecContext, FormatContext->streams[i]) < 0) + throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_DECODING, + "Could not copy video codec paramaters"); + + if (avcodec_open2(VideoCodecContext, VideoCodec, nullptr) < 0) throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_DECODING, "Could not open video codec"); - VideoContexts[i].CodecContext = FormatContext->streams[i]->codec; - VideoContexts[i].Parser = av_parser_init(FormatContext->streams[i]->codec->codec_id); + VideoContexts[i].CodecContext = VideoCodecContext; + VideoContexts[i].Parser = av_parser_init(FormatContext->streams[i]->FFMSCODEC->codec_id); if (VideoContexts[i].Parser) VideoContexts[i].Parser->flags = PARSER_FLAG_COMPLETE_FRAMES; - if (FormatContext->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) + if (FormatContext->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) { + FormatContext->streams[i]->discard = AVDISCARD_ALL; IndexMask.erase(i); - else + } else { IndexMask[i] = false; + } } - else if (IndexMask.count(i) && FormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - AVCodecContext *AudioCodecContext = FormatContext->streams[i]->codec; - - AVCodec *AudioCodec = avcodec_find_decoder(AudioCodecContext->codec_id); + else if (IndexMask.count(i) && FormatContext->streams[i]->FFMSCODEC->codec_type == AVMEDIA_TYPE_AUDIO) { + AVCodec *AudioCodec = avcodec_find_decoder(FormatContext->streams[i]->FFMSCODEC->codec_id); if (AudioCodec == nullptr) throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_UNSUPPORTED, "Audio codec not found"); + AVCodecContext *AudioCodecContext = avcodec_alloc_context3(AudioCodec); + if (AudioCodecContext == nullptr) + throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_ALLOCATION_FAILED, + "Could not allocate audio codec context"); + + if (make_context(AudioCodecContext, FormatContext->streams[i]) < 0) + throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_DECODING, + "Could not copy audio codec paramaters"); + if (avcodec_open2(AudioCodecContext, AudioCodec, nullptr) < 0) throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_DECODING, "Could not open audio codec"); @@ -114,6 +133,7 @@ AudioContexts[i].CodecContext = AudioCodecContext; (*TrackIndices)[i].HasTS = false; } else { + FormatContext->streams[i]->discard = AVDISCARD_ALL; IndexMask.erase(i); } } @@ -133,7 +153,7 @@ "Cancelled by user"); } if (!IndexMask.count(Packet.stream_index)) { - av_free_packet(&Packet); + av_packet_unref(&Packet); continue; } @@ -142,7 +162,7 @@ bool KeyFrame = !!(Packet.flags & AV_PKT_FLAG_KEY); ReadTS(Packet, LastValidTS[Track], (*TrackIndices)[Track].UseDTS); - if (FormatContext->streams[Track]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (FormatContext->streams[Track]->FFMSCODEC->codec_type == AVMEDIA_TYPE_VIDEO) { int64_t PTS = TrackInfo.UseDTS ? Packet.dts : Packet.pts; if (PTS == ffms_av_nopts_value) { if (Packet.duration == 0) @@ -166,7 +186,7 @@ TrackInfo.AddVideoFrame(PTS, RepeatPict, KeyFrame, FrameType, Packet.pos, Invisible); } - else if (FormatContext->streams[Track]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + else if (FormatContext->streams[Track]->FFMSCODEC->codec_type == AVMEDIA_TYPE_AUDIO) { // For video seeking timestamps are used only if all packets have // timestamps, while for audio they're used if any have timestamps, // as it's pretty common for only some packets to have timestamps @@ -181,7 +201,7 @@ StartSample, SampleCount, KeyFrame, Packet.pos); } - av_free_packet(&Packet); + av_packet_unref(&Packet); } TrackIndices->Finalize(VideoContexts); diff -Nru ffms2-2.22/src/core/lavfvideo.cpp ffms2-2.23/src/core/lavfvideo.cpp --- ffms2-2.22/src/core/lavfvideo.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/lavfvideo.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -76,7 +76,7 @@ void FFLAVFVideo::Free(bool CloseCodec) { if (CloseCodec) - avcodec_close(CodecContext); + avcodec_free_context(&CodecContext); avformat_close_input(&FormatContext); } @@ -86,17 +86,23 @@ , SeekMode(SeekMode) , Res(this) { - LAVFOpenFile(SourceFile, FormatContext); + LAVFOpenFile(SourceFile, FormatContext, VideoTrack); - CodecContext = FormatContext->streams[VideoTrack]->codec; - CodecContext->thread_count = DecodingThreads; - CodecContext->has_b_frames = Frames.MaxBFrames; - - AVCodec *Codec = avcodec_find_decoder(CodecContext->codec_id); + AVCodec *Codec = avcodec_find_decoder(FormatContext->streams[VideoTrack]->FFMSCODEC->codec_id); if (Codec == nullptr) throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, "Video codec not found"); + CodecContext = avcodec_alloc_context3(Codec); + if (CodecContext == nullptr) + throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_ALLOCATION_FAILED, + "Could not allocate video codec context."); + if (make_context(CodecContext, FormatContext->streams[VideoTrack]) < 0) + throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, + "Could not copy video decoder paramaters."); + CodecContext->thread_count = DecodingThreads; + CodecContext->has_b_frames = Frames.MaxBFrames; + if (avcodec_open2(CodecContext, Codec, nullptr) < 0) throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC, "Could not open video codec"); @@ -162,7 +168,7 @@ while (ReadFrame(&Packet) >= 0) { if (Packet.stream_index != VideoTrack) { - av_free_packet(&Packet); + av_packet_unref(&Packet); continue; } @@ -173,7 +179,7 @@ Pos = Packet.pos; bool FrameFinished = DecodePacket(&Packet); - av_free_packet(&Packet); + av_packet_unref(&Packet); if (FrameFinished) return; } diff -Nru ffms2-2.22/src/core/track.cpp ffms2-2.23/src/core/track.cpp --- ffms2-2.22/src/core/track.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/track.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -25,8 +25,11 @@ #include +extern "C" { #include #include +#include +} namespace { FrameInfo ReadFrame(ZipFile &stream, FrameInfo const& prev, const FFMS_TrackType TT) { diff -Nru ffms2-2.22/src/core/utils.cpp ffms2-2.23/src/core/utils.cpp --- ffms2-2.22/src/core/utils.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/utils.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -36,8 +36,6 @@ #include #include -extern bool GlobalUseUTF8Paths; - FFMS_Exception::FFMS_Exception(int ErrorType, int SubType, const char *Message) : _Message(Message), _ErrorType(ErrorType), _SubType(SubType) { } FFMS_Exception::FFMS_Exception(int ErrorType, int SubType, const std::string &Message) : _Message(Message), _ErrorType(ErrorType), _SubType(SubType) { } @@ -118,32 +116,9 @@ AP.ChannelLayout = av_get_default_channel_layout(AP.Channels); } -// All this filename chikanery that follows is supposed to make sure both local -// codepage (used by avisynth etc) and UTF8 (potentially used by API users) strings -// work correctly on Win32. -// It's a really ugly hack, and I blame Microsoft for it. -#ifdef _WIN32 -static std::wstring char_to_wstring(const char *s, unsigned int cp) { - std::wstring ret; - int len; - if (!(len = MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, s, -1, nullptr, 0))) - return ret; - - ret.resize(len); - if (MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, s, -1 , &ret[0], len) <= 0) - return ret; - - return ret; -} - -std::wstring widen_path(const char *s) { - return char_to_wstring(s, GlobalUseUTF8Paths ? CP_UTF8 : CP_ACP); -} -#endif - // End of filename hackery. -void LAVFOpenFile(const char *SourceFile, AVFormatContext *&FormatContext) { +void LAVFOpenFile(const char *SourceFile, AVFormatContext *&FormatContext, int Track) { if (avformat_open_input(&FormatContext, SourceFile, nullptr, nullptr) != 0) throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, std::string("Couldn't open '") + SourceFile + "'"); @@ -154,26 +129,14 @@ throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, "Couldn't find stream information"); } + + for (int i = 0; i < (int) FormatContext->nb_streams; i++) + if (i != Track) + FormatContext->streams[i]->discard = AVDISCARD_ALL; } void FlushBuffers(AVCodecContext *CodecContext) { - if (CodecContext->codec->flush) - avcodec_flush_buffers(CodecContext); - else { - // If the codec doesn't have flush(), it might not need it... or it - // might need it and just not implement it as in the case of VC-1, so - // close and reopen the codec - const AVCodec *codec = CodecContext->codec; - - // Raw video codec forgets the palette if "flushed" this way - if (codec->id != FFMS_ID(RAWVIDEO)) { - avcodec_close(CodecContext); - // Whether or not codec is const varies between versions - if (avcodec_open2(CodecContext, const_cast(codec), nullptr) < 0) - throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_CODEC, - "Couldn't re-open codec."); - } - } + avcodec_flush_buffers(CodecContext); } int ResizerNameToSWSResizer(const char *ResizerName) { diff -Nru ffms2-2.22/src/core/utils.h ffms2-2.23/src/core/utils.h --- ffms2-2.22/src/core/utils.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/utils.h 2016-10-18 16:54:00.000000000 +0000 @@ -130,12 +130,10 @@ typedef unknown_size FFResampleContext; void ClearErrorInfo(FFMS_ErrorInfo *ErrorInfo); -bool AudioFMTIsFloat(AVSampleFormat FMT); void InitNullPacket(AVPacket &pkt); void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames); -std::wstring widen_path(const char *s); -void LAVFOpenFile(const char *SourceFile, AVFormatContext *&FormatContext); +void LAVFOpenFile(const char *SourceFile, AVFormatContext *&FormatContext, int Track); void FlushBuffers(AVCodecContext *CodecContext); diff -Nru ffms2-2.22/src/core/videosource.cpp ffms2-2.23/src/core/videosource.cpp --- ffms2-2.22/src/core/videosource.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/videosource.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -27,10 +27,10 @@ #include namespace { -void CopyAVPictureFields(AVPicture &Picture, FFMS_Frame &Dst) { +void CopyAVFrameFields(uint8_t *data[4], int linesize[4], FFMS_Frame &Dst) { for (int i = 0; i < 4; i++) { - Dst.Data[i] = Picture.data[i]; - Dst.Linesize[i] = Picture.linesize[i]; + Dst.Data[i] = data[i]; + Dst.Linesize[i] = linesize[i]; } } @@ -67,8 +67,8 @@ } if (SWS) { - sws_scale(SWS, Frame->data, Frame->linesize, 0, CodecContext->height, SWSFrame.data, SWSFrame.linesize); - CopyAVPictureFields(SWSFrame, LocalFrame); + sws_scale(SWS, Frame->data, Frame->linesize, 0, CodecContext->height, SWSFrameData, SWSFrameLinesize); + CopyAVFrameFields(SWSFrameData, SWSFrameLinesize, LocalFrame); } else { // Special case to avoid ugly casts for (int i = 0; i < 4; i++) { @@ -157,7 +157,9 @@ LastDecodedFrame = av_frame_alloc(); // Dummy allocations so the unallocated case doesn't have to be handled later - avpicture_alloc(&SWSFrame, FFMS_PIX_FMT(GRAY8), 16, 16); + if (av_image_alloc(SWSFrameData, SWSFrameLinesize, 16, 16, FFMS_PIX_FMT(GRAY8), 4) < 0) + throw FFMS_Exception(FFMS_ERROR_INDEX, FFMS_ERROR_ALLOCATION_FAILED, + "Could not allocate dummy frame."); Index.AddRef(); } @@ -166,7 +168,7 @@ if (SWS) sws_freeContext(SWS); - avpicture_free(&SWSFrame); + av_freep(&SWSFrameData[0]); av_freep(&DecodeFrame); av_freep(&LastDecodedFrame); @@ -232,8 +234,6 @@ if (InputColorSpace == AVCOL_SPC_UNSPECIFIED) InputColorSpace = CodecContext->colorspace; - if (InputColorSpace == AVCOL_SPC_UNSPECIFIED) - InputColorSpace = GetAssumedColorSpace(CodecContext->width, CodecContext->height); } void FFMS_VideoSource::ReAdjustOutputFormat() { @@ -279,8 +279,10 @@ } } - avpicture_free(&SWSFrame); - avpicture_alloc(&SWSFrame, OutputFormat, TargetWidth, TargetHeight); + av_freep(&SWSFrameData[0]); + if (av_image_alloc(SWSFrameData, SWSFrameLinesize, TargetWidth, TargetHeight, OutputFormat, 4) < 0) + throw FFMS_Exception(FFMS_ERROR_SCALING, FFMS_ERROR_ALLOCATION_FAILED, + "Could not allocate frame with new resolution."); } void FFMS_VideoSource::ResetOutputFormat() { diff -Nru ffms2-2.22/src/core/videosource.h ffms2-2.23/src/core/videosource.h --- ffms2-2.22/src/core/videosource.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/videosource.h 2016-10-18 16:54:00.000000000 +0000 @@ -25,6 +25,7 @@ #include #include #include +#include } #include @@ -55,7 +56,8 @@ AVColorRange InputColorRange; AVColorSpace InputColorSpace; - AVPicture SWSFrame; + uint8_t *SWSFrameData[4]; + int SWSFrameLinesize[4]; void DetectInputFormat(); diff -Nru ffms2-2.22/src/core/videoutils.cpp ffms2-2.23/src/core/videoutils.cpp --- ffms2-2.22/src/core/videoutils.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/videoutils.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -61,13 +61,6 @@ return Context; } -AVColorSpace GetAssumedColorSpace(int W, int H) { - if (W > 1024 || H >= 600) - return AVCOL_SPC_BT709; - else - return AVCOL_SPC_BT470BG; -} - /*************************** ** ** Two functions for making FFMS pretend it's not quite as VFR-based as it really is. diff -Nru ffms2-2.22/src/core/videoutils.h ffms2-2.23/src/core/videoutils.h --- ffms2-2.22/src/core/videoutils.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/videoutils.h 2016-10-18 16:54:00.000000000 +0000 @@ -34,9 +34,7 @@ // swscale and pp-related functions -int64_t GetSWSCPUFlags(); SwsContext *GetSwsContext(int SrcW, int SrcH, AVPixelFormat SrcFormat, int SrcColorSpace, int SrcColorRange, int DstW, int DstH, AVPixelFormat DstFormat, int DstColorSpace, int DstColorRange, int64_t Flags); -AVColorSpace GetAssumedColorSpace(int Width, int Height); // timebase-related functions void CorrectRationalFramerate(int *Num, int *Den); diff -Nru ffms2-2.22/src/core/zipfile.cpp ffms2-2.23/src/core/zipfile.cpp --- ffms2-2.22/src/core/zipfile.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/zipfile.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -20,16 +20,37 @@ #include "zipfile.h" +extern "C" { +#include +} + #include "utils.h" ZipFile::ZipFile(const char *filename, const char *mode) : file(filename, mode, FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ) +, is_file(true) +, state(Initial) +{ + buffer.resize(65536); + z = {}; +} + +ZipFile::ZipFile() +: is_file(false) , state(Initial) { buffer.resize(65536); z = {}; } +ZipFile::ZipFile(const uint8_t *in_buffer, const size_t size) +: is_file(false) +, index_buffer(in_buffer, in_buffer + size) +, state(Initial) +{ + z = {}; +} + ZipFile::~ZipFile() { if (state == Inflate) inflateEnd(&z); @@ -50,13 +71,21 @@ z.next_out = static_cast(data); z.avail_out = size; + if (!z.avail_in && !is_file) { + z.next_in = reinterpret_cast(&index_buffer[0]); + z.avail_in = index_buffer.size(); + } do { - if (!z.avail_in) { + if (!z.avail_in && is_file) { z.next_in = reinterpret_cast(&buffer[0]); z.avail_in = file.Read(&buffer[0], buffer.size()); } - if (!z.avail_in && !file.Tell()) - throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, "Failed to read data: File is empty"); + if (!z.avail_in) { + if (!is_file) + throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, "Failed to read data: Buffer is empty"); + else if (!file.Tell()) + throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ, "Failed to read data: File is empty"); + } switch (inflate(&z, Z_SYNC_FLUSH)) { case Z_NEED_DICT: @@ -91,8 +120,12 @@ z.next_out = reinterpret_cast(&buffer[0]); ret = deflate(&z, size > 0 ? Z_NO_FLUSH : Z_FINISH); uInt written = buffer.size() - z.avail_out; - if (written) - file.Write(&buffer[0], written); + if (written) { + if (is_file) + file.Write(&buffer[0], written); + else + index_buffer.insert(index_buffer.end(), &buffer[0], &buffer[written]); + } } while (z.avail_out == 0); return ret; } @@ -102,3 +135,14 @@ deflateEnd(&z); state = Initial; } + +uint8_t *ZipFile::GetBuffer(size_t *size) { + uint8_t *ret = (uint8_t *) av_malloc(index_buffer.size()); + if (ret == nullptr) + throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_ALLOCATION_FAILED, "Failed to allocate index return buffer"); + + memcpy(ret, reinterpret_cast(&index_buffer[0]), index_buffer.size()); + *size = index_buffer.size(); + + return ret; +} diff -Nru ffms2-2.22/src/core/zipfile.h ffms2-2.23/src/core/zipfile.h --- ffms2-2.22/src/core/zipfile.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/core/zipfile.h 2016-10-18 16:54:00.000000000 +0000 @@ -18,6 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#ifndef ZIPFILE_H +#define ZIPFILE_H + #include "filehandle.h" #include @@ -26,6 +29,8 @@ class ZipFile { FileHandle file; std::vector buffer; + std::vector index_buffer; + bool is_file; z_stream z; enum { Initial, @@ -35,11 +40,14 @@ public: ZipFile(const char *filename, const char *mode); + ZipFile(const uint8_t *in_buffer, const size_t size); + ZipFile(); ~ZipFile(); void Read(void *buffer, size_t size); int Write(const void *buffer, size_t size); void Finish(); + uint8_t *GetBuffer(size_t *size); template T Read() { @@ -53,3 +61,5 @@ Write(&value, sizeof value); } }; + +#endif diff -Nru ffms2-2.22/src/index/ffmsindex.cpp ffms2-2.23/src/index/ffmsindex.cpp --- ffms2-2.22/src/index/ffmsindex.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/index/ffmsindex.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -161,9 +161,10 @@ int Progress = 0; FFMS_Index *Index = FFMS_ReadIndex(CacheFile.c_str(), &E); - if (!Overwrite && Index) { + if (Index) { FFMS_DestroyIndex(Index); - throw Error("Error: index file already exists, use -f if you are sure you want to overwrite it."); + if (!Overwrite) + throw Error("Error: index file already exists, use -f if you are sure you want to overwrite it."); } UpdateProgress(0, 100, nullptr); diff -Nru ffms2-2.22/src/vapoursynth/vapoursource.cpp ffms2-2.23/src/vapoursynth/vapoursource.cpp --- ffms2-2.22/src/vapoursynth/vapoursource.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/vapoursynth/vapoursource.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -322,7 +322,9 @@ VI[0].width = F->ScaledWidth; VI[0].height = F->ScaledHeight; - // fixme? Crop to obey sane even width/height requirements + // Crop to obey subsampling width/height requirements + VI[0].width -= VI[0].width % (1 << VI[0].format->subSamplingW); + VI[0].height -= VI[0].height % (1 << VI[0].format->subSamplingH); } void VSVideoSource::OutputFrame(const FFMS_Frame *Frame, VSFrameRef *Dst, const VSAPI *vsapi) { diff -Nru ffms2-2.22/src/vapoursynth/vapoursource.h ffms2-2.23/src/vapoursynth/vapoursource.h --- ffms2-2.22/src/vapoursynth/vapoursource.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/vapoursynth/vapoursource.h 2016-10-18 16:54:00.000000000 +0000 @@ -26,6 +26,7 @@ #include #include #include +#include #include } diff -Nru ffms2-2.22/src/vapoursynth/vapoursynth.cpp ffms2-2.23/src/vapoursynth/vapoursynth.cpp --- ffms2-2.22/src/vapoursynth/vapoursynth.cpp 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/vapoursynth/vapoursynth.cpp 2016-10-18 16:54:00.000000000 +0000 @@ -238,7 +238,7 @@ return vsapi->setError(out, e.what()); } - vsapi->createFilter(in, out, "Source", VSVideoSource::Init, VSVideoSource::GetFrame, VSVideoSource::Free, fmUnordered, 0,vs, core); + vsapi->createFilter(in, out, "Source", VSVideoSource::Init, VSVideoSource::GetFrame, VSVideoSource::Free, fmUnordered, nfMakeLinear, vs, core); FFMS_DestroyIndex(Index); } diff -Nru ffms2-2.22/src/vapoursynth/VapourSynth.h ffms2-2.23/src/vapoursynth/VapourSynth.h --- ffms2-2.22/src/vapoursynth/VapourSynth.h 2015-10-12 21:18:22.000000000 +0000 +++ ffms2-2.23/src/vapoursynth/VapourSynth.h 2016-10-18 16:54:00.000000000 +0000 @@ -24,14 +24,20 @@ #include #define VAPOURSYNTH_API_MAJOR 3 -#define VAPOURSYNTH_API_MINOR 2 +#define VAPOURSYNTH_API_MINOR 3 #define VAPOURSYNTH_API_VERSION ((VAPOURSYNTH_API_MAJOR << 16) | (VAPOURSYNTH_API_MINOR)) /* Convenience for C++ users. */ #ifdef __cplusplus # define VS_EXTERN_C extern "C" +# if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) +# define VS_NOEXCEPT noexcept +# else +# define VS_NOEXCEPT +# endif #else # define VS_EXTERN_C +# define VS_NOEXCEPT #endif #if defined(_WIN32) && !defined(_WIN64) @@ -148,8 +154,9 @@ } VSFormat; typedef enum VSNodeFlags { - nfNoCache = 1, - nfIsCache = 2 + nfNoCache = 1, + nfIsCache = 2, + nfMakeLinear = 4 } VSNodeFlags; typedef enum VSPropTypes { @@ -225,100 +232,100 @@ typedef void (VS_CC *VSMessageHandler)(int msgType, const char *msg, void *userData); struct VSAPI { - VSCore *(VS_CC *createCore)(int threads); - void (VS_CC *freeCore)(VSCore *core); - const VSCoreInfo *(VS_CC *getCoreInfo)(VSCore *core); - - const VSFrameRef *(VS_CC *cloneFrameRef)(const VSFrameRef *f); - VSNodeRef *(VS_CC *cloneNodeRef)(VSNodeRef *node); - VSFuncRef *(VS_CC *cloneFuncRef)(VSFuncRef *f); - - void (VS_CC *freeFrame)(const VSFrameRef *f); - void (VS_CC *freeNode)(VSNodeRef *node); - void (VS_CC *freeFunc)(VSFuncRef *f); - - VSFrameRef *(VS_CC *newVideoFrame)(const VSFormat *format, int width, int height, const VSFrameRef *propSrc, VSCore *core); - VSFrameRef *(VS_CC *copyFrame)(const VSFrameRef *f, VSCore *core); - void (VS_CC *copyFrameProps)(const VSFrameRef *src, VSFrameRef *dst, VSCore *core); - - void (VS_CC *registerFunction)(const char *name, const char *args, VSPublicFunction argsFunc, void *functionData, VSPlugin *plugin); - VSPlugin *(VS_CC *getPluginById)(const char *identifier, VSCore *core); - VSPlugin *(VS_CC *getPluginByNs)(const char *ns, VSCore *core); - VSMap *(VS_CC *getPlugins)(VSCore *core); - VSMap *(VS_CC *getFunctions)(VSPlugin *plugin); - void (VS_CC *createFilter)(const VSMap *in, VSMap *out, const char *name, VSFilterInit init, VSFilterGetFrame getFrame, VSFilterFree free, int filterMode, int flags, void *instanceData, VSCore *core); - void (VS_CC *setError)(VSMap *map, const char *errorMessage); /* use to signal errors outside filter getframe functions */ - const char *(VS_CC *getError)(const VSMap *map); /* use to query errors, returns 0 if no error */ - void (VS_CC *setFilterError)(const char *errorMessage, VSFrameContext *frameCtx); /* use to signal errors in the filter getframe function */ - VSMap *(VS_CC *invoke)(VSPlugin *plugin, const char *name, const VSMap *args); - - const VSFormat *(VS_CC *getFormatPreset)(int id, VSCore *core); - const VSFormat *(VS_CC *registerFormat)(int colorFamily, int sampleType, int bitsPerSample, int subSamplingW, int subSamplingH, VSCore *core); - - const VSFrameRef *(VS_CC *getFrame)(int n, VSNodeRef *node, char *errorMsg, int bufSize); /* do never use inside a filter's getframe function, for external applications using the core as a library or for requesting frames in a filter constructor */ - void (VS_CC *getFrameAsync)(int n, VSNodeRef *node, VSFrameDoneCallback callback, void *userData); /* do never use inside a filter's getframe function, for external applications using the core as a library or for requesting frames in a filter constructor */ - const VSFrameRef *(VS_CC *getFrameFilter)(int n, VSNodeRef *node, VSFrameContext *frameCtx); /* only use inside a filter's getframe function */ - void (VS_CC *requestFrameFilter)(int n, VSNodeRef *node, VSFrameContext *frameCtx); /* only use inside a filter's getframe function */ - void (VS_CC *queryCompletedFrame)(VSNodeRef **node, int *n, VSFrameContext *frameCtx); /* only use inside a filter's getframe function */ - void (VS_CC *releaseFrameEarly)(VSNodeRef *node, int n, VSFrameContext *frameCtx); /* only use inside a filter's getframe function */ - - int (VS_CC *getStride)(const VSFrameRef *f, int plane); - const uint8_t *(VS_CC *getReadPtr)(const VSFrameRef *f, int plane); - uint8_t *(VS_CC *getWritePtr)(VSFrameRef *f, int plane); - - VSFuncRef *(VS_CC *createFunc)(VSPublicFunction func, void *userData, VSFreeFuncData free, VSCore *core, const VSAPI *vsapi); - void (VS_CC *callFunc)(VSFuncRef *func, const VSMap *in, VSMap *out, VSCore *core, const VSAPI *vsapi); /* core and vsapi arguments are completely ignored, they only remain to preserve ABI */ - - /* property access functions */ - VSMap *(VS_CC *createMap)(void); - void (VS_CC *freeMap)(VSMap *map); - void (VS_CC *clearMap)(VSMap *map); - - const VSVideoInfo *(VS_CC *getVideoInfo)(VSNodeRef *node); - void (VS_CC *setVideoInfo)(const VSVideoInfo *vi, int numOutputs, VSNode *node); - const VSFormat *(VS_CC *getFrameFormat)(const VSFrameRef *f); - int (VS_CC *getFrameWidth)(const VSFrameRef *f, int plane); - int (VS_CC *getFrameHeight)(const VSFrameRef *f, int plane); - const VSMap *(VS_CC *getFramePropsRO)(const VSFrameRef *f); - VSMap *(VS_CC *getFramePropsRW)(VSFrameRef *f); - - int (VS_CC *propNumKeys)(const VSMap *map); - const char *(VS_CC *propGetKey)(const VSMap *map, int index); - int (VS_CC *propNumElements)(const VSMap *map, const char *key); - char (VS_CC *propGetType)(const VSMap *map, const char *key); - - int64_t(VS_CC *propGetInt)(const VSMap *map, const char *key, int index, int *error); - double(VS_CC *propGetFloat)(const VSMap *map, const char *key, int index, int *error); - const char *(VS_CC *propGetData)(const VSMap *map, const char *key, int index, int *error); - int (VS_CC *propGetDataSize)(const VSMap *map, const char *key, int index, int *error); - VSNodeRef *(VS_CC *propGetNode)(const VSMap *map, const char *key, int index, int *error); - const VSFrameRef *(VS_CC *propGetFrame)(const VSMap *map, const char *key, int index, int *error); - VSFuncRef *(VS_CC *propGetFunc)(const VSMap *map, const char *key, int index, int *error); - - int (VS_CC *propDeleteKey)(VSMap *map, const char *key); - int (VS_CC *propSetInt)(VSMap *map, const char *key, int64_t i, int append); - int (VS_CC *propSetFloat)(VSMap *map, const char *key, double d, int append); - int (VS_CC *propSetData)(VSMap *map, const char *key, const char *data, int size, int append); - int (VS_CC *propSetNode)(VSMap *map, const char *key, VSNodeRef *node, int append); - int (VS_CC *propSetFrame)(VSMap *map, const char *key, const VSFrameRef *f, int append); - int (VS_CC *propSetFunc)(VSMap *map, const char *key, VSFuncRef *func, int append); - - /* mixed functions added after API R3.0 */ - int64_t (VS_CC *setMaxCacheSize)(int64_t bytes, VSCore *core); - int (VS_CC *getOutputIndex)(VSFrameContext *frameCtx); - VSFrameRef *(VS_CC *newVideoFrame2)(const VSFormat *format, int width, int height, const VSFrameRef **planeSrc, const int *planes, const VSFrameRef *propSrc, VSCore *core); - void (VS_CC *setMessageHandler)(VSMessageHandler handler, void *userData); - int (VS_CC *setThreadCount)(int threads, VSCore *core); + VSCore *(VS_CC *createCore)(int threads) VS_NOEXCEPT; + void (VS_CC *freeCore)(VSCore *core) VS_NOEXCEPT; + const VSCoreInfo *(VS_CC *getCoreInfo)(VSCore *core) VS_NOEXCEPT; + + const VSFrameRef *(VS_CC *cloneFrameRef)(const VSFrameRef *f) VS_NOEXCEPT; + VSNodeRef *(VS_CC *cloneNodeRef)(VSNodeRef *node) VS_NOEXCEPT; + VSFuncRef *(VS_CC *cloneFuncRef)(VSFuncRef *f) VS_NOEXCEPT; + + void (VS_CC *freeFrame)(const VSFrameRef *f) VS_NOEXCEPT; + void (VS_CC *freeNode)(VSNodeRef *node) VS_NOEXCEPT; + void (VS_CC *freeFunc)(VSFuncRef *f) VS_NOEXCEPT; + + VSFrameRef *(VS_CC *newVideoFrame)(const VSFormat *format, int width, int height, const VSFrameRef *propSrc, VSCore *core) VS_NOEXCEPT; + VSFrameRef *(VS_CC *copyFrame)(const VSFrameRef *f, VSCore *core) VS_NOEXCEPT; + void (VS_CC *copyFrameProps)(const VSFrameRef *src, VSFrameRef *dst, VSCore *core) VS_NOEXCEPT; + + void (VS_CC *registerFunction)(const char *name, const char *args, VSPublicFunction argsFunc, void *functionData, VSPlugin *plugin) VS_NOEXCEPT; + VSPlugin *(VS_CC *getPluginById)(const char *identifier, VSCore *core) VS_NOEXCEPT; + VSPlugin *(VS_CC *getPluginByNs)(const char *ns, VSCore *core) VS_NOEXCEPT; + VSMap *(VS_CC *getPlugins)(VSCore *core) VS_NOEXCEPT; + VSMap *(VS_CC *getFunctions)(VSPlugin *plugin) VS_NOEXCEPT; + void (VS_CC *createFilter)(const VSMap *in, VSMap *out, const char *name, VSFilterInit init, VSFilterGetFrame getFrame, VSFilterFree free, int filterMode, int flags, void *instanceData, VSCore *core) VS_NOEXCEPT; + void (VS_CC *setError)(VSMap *map, const char *errorMessage) VS_NOEXCEPT; /* use to signal errors outside filter getframe functions */ + const char *(VS_CC *getError)(const VSMap *map) VS_NOEXCEPT; /* use to query errors, returns 0 if no error */ + void (VS_CC *setFilterError)(const char *errorMessage, VSFrameContext *frameCtx) VS_NOEXCEPT; /* use to signal errors in the filter getframe function */ + VSMap *(VS_CC *invoke)(VSPlugin *plugin, const char *name, const VSMap *args) VS_NOEXCEPT; + + const VSFormat *(VS_CC *getFormatPreset)(int id, VSCore *core) VS_NOEXCEPT; + const VSFormat *(VS_CC *registerFormat)(int colorFamily, int sampleType, int bitsPerSample, int subSamplingW, int subSamplingH, VSCore *core) VS_NOEXCEPT; + + const VSFrameRef *(VS_CC *getFrame)(int n, VSNodeRef *node, char *errorMsg, int bufSize) VS_NOEXCEPT; /* do never use inside a filter's getframe function, for external applications using the core as a library or for requesting frames in a filter constructor */ + void (VS_CC *getFrameAsync)(int n, VSNodeRef *node, VSFrameDoneCallback callback, void *userData) VS_NOEXCEPT; /* do never use inside a filter's getframe function, for external applications using the core as a library or for requesting frames in a filter constructor */ + const VSFrameRef *(VS_CC *getFrameFilter)(int n, VSNodeRef *node, VSFrameContext *frameCtx) VS_NOEXCEPT; /* only use inside a filter's getframe function */ + void (VS_CC *requestFrameFilter)(int n, VSNodeRef *node, VSFrameContext *frameCtx) VS_NOEXCEPT; /* only use inside a filter's getframe function */ + void (VS_CC *queryCompletedFrame)(VSNodeRef **node, int *n, VSFrameContext *frameCtx) VS_NOEXCEPT; /* only use inside a filter's getframe function */ + void (VS_CC *releaseFrameEarly)(VSNodeRef *node, int n, VSFrameContext *frameCtx) VS_NOEXCEPT; /* only use inside a filter's getframe function */ + + int (VS_CC *getStride)(const VSFrameRef *f, int plane) VS_NOEXCEPT; + const uint8_t *(VS_CC *getReadPtr)(const VSFrameRef *f, int plane) VS_NOEXCEPT; + uint8_t *(VS_CC *getWritePtr)(VSFrameRef *f, int plane) VS_NOEXCEPT; + + VSFuncRef *(VS_CC *createFunc)(VSPublicFunction func, void *userData, VSFreeFuncData free, VSCore *core, const VSAPI *vsapi) VS_NOEXCEPT; + void (VS_CC *callFunc)(VSFuncRef *func, const VSMap *in, VSMap *out, VSCore *core, const VSAPI *vsapi) VS_NOEXCEPT; /* core and vsapi arguments are completely ignored, they only remain to preserve ABI */ + + /* property access functions */ + VSMap *(VS_CC *createMap)(void) VS_NOEXCEPT; + void (VS_CC *freeMap)(VSMap *map) VS_NOEXCEPT; + void (VS_CC *clearMap)(VSMap *map) VS_NOEXCEPT; + + const VSVideoInfo *(VS_CC *getVideoInfo)(VSNodeRef *node) VS_NOEXCEPT; + void (VS_CC *setVideoInfo)(const VSVideoInfo *vi, int numOutputs, VSNode *node) VS_NOEXCEPT; + const VSFormat *(VS_CC *getFrameFormat)(const VSFrameRef *f) VS_NOEXCEPT; + int (VS_CC *getFrameWidth)(const VSFrameRef *f, int plane) VS_NOEXCEPT; + int (VS_CC *getFrameHeight)(const VSFrameRef *f, int plane) VS_NOEXCEPT; + const VSMap *(VS_CC *getFramePropsRO)(const VSFrameRef *f) VS_NOEXCEPT; + VSMap *(VS_CC *getFramePropsRW)(VSFrameRef *f) VS_NOEXCEPT; + + int (VS_CC *propNumKeys)(const VSMap *map) VS_NOEXCEPT; + const char *(VS_CC *propGetKey)(const VSMap *map, int index) VS_NOEXCEPT; + int (VS_CC *propNumElements)(const VSMap *map, const char *key) VS_NOEXCEPT; + char (VS_CC *propGetType)(const VSMap *map, const char *key) VS_NOEXCEPT; + + int64_t(VS_CC *propGetInt)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT; + double(VS_CC *propGetFloat)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT; + const char *(VS_CC *propGetData)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT; + int (VS_CC *propGetDataSize)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT; + VSNodeRef *(VS_CC *propGetNode)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT; + const VSFrameRef *(VS_CC *propGetFrame)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT; + VSFuncRef *(VS_CC *propGetFunc)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT; + + int (VS_CC *propDeleteKey)(VSMap *map, const char *key) VS_NOEXCEPT; + int (VS_CC *propSetInt)(VSMap *map, const char *key, int64_t i, int append) VS_NOEXCEPT; + int (VS_CC *propSetFloat)(VSMap *map, const char *key, double d, int append) VS_NOEXCEPT; + int (VS_CC *propSetData)(VSMap *map, const char *key, const char *data, int size, int append) VS_NOEXCEPT; + int (VS_CC *propSetNode)(VSMap *map, const char *key, VSNodeRef *node, int append) VS_NOEXCEPT; + int (VS_CC *propSetFrame)(VSMap *map, const char *key, const VSFrameRef *f, int append) VS_NOEXCEPT; + int (VS_CC *propSetFunc)(VSMap *map, const char *key, VSFuncRef *func, int append) VS_NOEXCEPT; + + /* mixed functions added after API R3.0 */ + int64_t(VS_CC *setMaxCacheSize)(int64_t bytes, VSCore *core) VS_NOEXCEPT; + int (VS_CC *getOutputIndex)(VSFrameContext *frameCtx) VS_NOEXCEPT; + VSFrameRef *(VS_CC *newVideoFrame2)(const VSFormat *format, int width, int height, const VSFrameRef **planeSrc, const int *planes, const VSFrameRef *propSrc, VSCore *core) VS_NOEXCEPT; + void (VS_CC *setMessageHandler)(VSMessageHandler handler, void *userData) VS_NOEXCEPT; + int (VS_CC *setThreadCount)(int threads, VSCore *core) VS_NOEXCEPT; - const char *(VS_CC *getPluginPath)(const VSPlugin *plugin); + const char *(VS_CC *getPluginPath)(const VSPlugin *plugin) VS_NOEXCEPT; - const int64_t *(VS_CC *propGetIntArray)(const VSMap *map, const char *key, int *error); - const double *(VS_CC *propGetFloatArray)(const VSMap *map, const char *key, int *error); + const int64_t *(VS_CC *propGetIntArray)(const VSMap *map, const char *key, int *error) VS_NOEXCEPT; + const double *(VS_CC *propGetFloatArray)(const VSMap *map, const char *key, int *error) VS_NOEXCEPT; - int (VS_CC *propSetIntArray)(VSMap *map, const char *key, const int64_t *i, int size); - int (VS_CC *propSetFloatArray)(VSMap *map, const char *key, const double *d, int size); + int (VS_CC *propSetIntArray)(VSMap *map, const char *key, const int64_t *i, int size) VS_NOEXCEPT; + int (VS_CC *propSetFloatArray)(VSMap *map, const char *key, const double *d, int size) VS_NOEXCEPT; }; -VS_API(const VSAPI *) getVapourSynthAPI(int version); +VS_API(const VSAPI *) getVapourSynthAPI(int version) VS_NOEXCEPT; #endif /* VAPOURSYNTH_H */