FFmpegSource 1.19

Originally committed to SVN as r2195.
This commit is contained in:
Fredrik Mellbin 2008-05-31 09:16:05 +00:00
parent d65b697e12
commit e091763052
8 changed files with 241 additions and 38 deletions

View File

@ -46,9 +46,8 @@ int FFMatroskaSource::GetTrackIndex(int Index, unsigned char ATrackType, IScript
FFMatroskaSource::FFMatroskaSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, FFMatroskaSource::FFMatroskaSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes,
bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString, bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString,
int AQuality, int AThreads, IScriptEnvironment* Env, FrameInfoVector *AFrames) { int AQuality, int AThreads, IScriptEnvironment* Env) {
AFrames = &Frames;
CurrentFrame = 0; CurrentFrame = 0;
int VideoTrack; int VideoTrack;
int AudioTrack; int AudioTrack;
@ -289,6 +288,11 @@ FFMatroskaSource::FFMatroskaSource(const char *ASource, int AVideoTrack, int AAu
Env->SetVar("FFSAR_DEN", ffsar_den); Env->SetVar("FFSAR_DEN", ffsar_den);
Env->SetVar("FFSAR", ffsar_num / (double)ffsar_den); Env->SetVar("FFSAR", ffsar_num / (double)ffsar_den);
// Set crop variables
Env->SetVar("FFCROP_LEFT", (int)VideoTI->AV.Video.CropL);
Env->SetVar("FFCROP_RIGHT", (int)VideoTI->AV.Video.CropR);
Env->SetVar("FFCROP_TOP", (int)VideoTI->AV.Video.CropT);
Env->SetVar("FFCROP_BOTTOM", (int)VideoTI->AV.Video.CropB);
} }
} }

View File

@ -42,23 +42,23 @@ int FFmpegAudioSource::GetTrackIndex(int Index, CodecType ATrackType, IScriptEnv
return Index; return Index;
} }
bool FFmpegAudioSource::LoadSampleInfoFromFile(const char *AAudioCacheFile, const char *ADemuxedAudioFile, const char *ASource, int AAudioTrack) { bool FFmpegAudioSource::LoadSampleInfoFromFile(const char *AAudioCacheFile, const char *AAudioCacheFile2, const char *ASource, int AAudioTrack) {
if (!FFAudioBase::LoadSampleInfoFromFile(AAudioCacheFile, ASource, AAudioTrack)) if (!FFAudioBase::LoadSampleInfoFromFile(AAudioCacheFile, ASource, AAudioTrack))
return false; return false;
char DefaultCacheFilename[1024]; char DefaultCacheFilename[1024];
sprintf(DefaultCacheFilename, "%s.ffasd%dcache", ASource, AAudioTrack); sprintf(DefaultCacheFilename, "%s.ffasd%dcache", ASource, AAudioTrack);
if (!strcmp(ADemuxedAudioFile, "")) if (!strcmp(AAudioCacheFile2, ""))
ADemuxedAudioFile = DefaultCacheFilename; AAudioCacheFile2 = DefaultCacheFilename;
RawCache = fopen(ADemuxedAudioFile, "rb"); RawCache = fopen(AAudioCacheFile2, "rb");
if (!RawCache) if (!RawCache)
return false; return false;
return true; return true;
} }
FFmpegAudioSource::FFmpegAudioSource(const char *ASource, int AAudioTrack, const char *AAudioCache, const char *ADemuxedAudioFile, IScriptEnvironment *Env) { FFmpegAudioSource::FFmpegAudioSource(const char *ASource, int AAudioTrack, const char *AAudioCache, const char *AAudioCache2, IScriptEnvironment *Env) {
BufferSize = 0; BufferSize = 0;
Buffer = NULL; Buffer = NULL;
RawCache = NULL; RawCache = NULL;
@ -97,14 +97,14 @@ FFmpegAudioSource::FFmpegAudioSource(const char *ASource, int AAudioTrack, const
} }
//load cache //load cache
bool ACacheIsValid = LoadSampleInfoFromFile(AAudioCache, ADemuxedAudioFile, ASource, AudioTrack); bool ACacheIsValid = LoadSampleInfoFromFile(AAudioCache, AAudioCache2, ASource, AudioTrack);
char DefaultCacheFilename[1024]; char DefaultCacheFilename[1024];
sprintf(DefaultCacheFilename, "%s.ffasd%dcache", ASource, AudioTrack); sprintf(DefaultCacheFilename, "%s.ffasd%dcache", ASource, AudioTrack);
if (!strcmp(ADemuxedAudioFile, "")) if (!strcmp(AAudioCache2, ""))
ADemuxedAudioFile = DefaultCacheFilename; AAudioCache2 = DefaultCacheFilename;
if (!RawCache) if (!RawCache)
RawCache = fopen(ADemuxedAudioFile, "wb+"); RawCache = fopen(AAudioCache2, "wb+");
// Needs to be indexed? // Needs to be indexed?
if (!ACacheIsValid) { if (!ACacheIsValid) {

View File

@ -46,9 +46,8 @@ int FFmpegSource::GetTrackIndex(int Index, CodecType ATrackType, IScriptEnvironm
FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes,
bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString, bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString,
int AQuality, int AThreads, int ASeekMode, IScriptEnvironment *Env, FrameInfoVector *AFrames) { int AQuality, int AThreads, int ASeekMode, IScriptEnvironment *Env) {
AFrames = &Frames;
CurrentFrame = 0; CurrentFrame = 0;
SeekMode = ASeekMode; SeekMode = ASeekMode;
@ -224,6 +223,12 @@ FFmpegSource::FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack
Env->SetVar("FFSAR_NUM", VideoCodecContext->sample_aspect_ratio.num); Env->SetVar("FFSAR_NUM", VideoCodecContext->sample_aspect_ratio.num);
Env->SetVar("FFSAR_DEN", VideoCodecContext->sample_aspect_ratio.den); Env->SetVar("FFSAR_DEN", VideoCodecContext->sample_aspect_ratio.den);
Env->SetVar("FFSAR", av_q2d(VideoCodecContext->sample_aspect_ratio)); Env->SetVar("FFSAR", av_q2d(VideoCodecContext->sample_aspect_ratio));
// Set crop variables
Env->SetVar("FFCROP_LEFT", (int)0);
Env->SetVar("FFCROP_RIGHT", (int)0);
Env->SetVar("FFCROP_TOP", (int)0);
Env->SetVar("FFCROP_BOTTOM", (int)0);
} }
} }

View File

@ -43,6 +43,8 @@ extern "C" {
#include "MatroskaParser.h" #include "MatroskaParser.h"
#include "avisynth.h" #include "avisynth.h"
#define strcmpi _strcmpi
enum AudioCacheFormat {acNone, acRaw}; enum AudioCacheFormat {acNone, acRaw};
struct FrameInfo { struct FrameInfo {
@ -70,6 +72,9 @@ typedef std::vector<SampleInfo> SampleInfoVector;
int GetPPCPUFlags(IScriptEnvironment *Env); int GetPPCPUFlags(IScriptEnvironment *Env);
int GetSWSCPUFlags(IScriptEnvironment *Env); int GetSWSCPUFlags(IScriptEnvironment *Env);
int CSNameToPIXFMT(const char * ACSName, int ADefault);
int ResizerNameToSWSResizer(const char *AResizerName);
int GetNumberOfLogicalCPUs();
CodecID MatroskaToFFCodecID(TrackInfo *TI); CodecID MatroskaToFFCodecID(TrackInfo *TI);
class FFPP : public GenericVideoFilter { class FFPP : public GenericVideoFilter {
@ -86,6 +91,18 @@ public:
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* Env); PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* Env);
}; };
class SWScale : public GenericVideoFilter {
private:
SwsContext *Context;
int OrigWidth;
int OrigHeight;
bool FlipOutput;
public:
SWScale(PClip AChild, int AResizeToWidth, int AResizeToHeight, const char *AResizer, const char *AConvertToFormat, IScriptEnvironment *Env);
~SWScale();
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env);
};
class FFBase : public IClip{ class FFBase : public IClip{
private: private:
pp_context_t *PPContext; pp_context_t *PPContext;
@ -141,7 +158,7 @@ private:
int GetTrackIndex(int Index, CodecType ATrackType, IScriptEnvironment *Env); int GetTrackIndex(int Index, CodecType ATrackType, IScriptEnvironment *Env);
int DecodeNextFrame(AVFrame *Frame, int64_t *DTS); int DecodeNextFrame(AVFrame *Frame, int64_t *DTS);
public: public:
FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString, int AQuality, int AThreads, int ASeekMode, IScriptEnvironment *Env, FrameInfoVector *AFrames); FFmpegSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString, int AQuality, int AThreads, int ASeekMode, IScriptEnvironment *Env);
~FFmpegSource(); ~FFmpegSource();
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env); PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env);
}; };
@ -162,7 +179,7 @@ private:
int DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime, IScriptEnvironment* Env); int DecodeNextFrame(AVFrame *AFrame, int64_t *AFirstStartTime, IScriptEnvironment* Env);
int GetTrackIndex(int Index, unsigned char ATrackType, IScriptEnvironment *Env); int GetTrackIndex(int Index, unsigned char ATrackType, IScriptEnvironment *Env);
public: public:
FFMatroskaSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString, int AQuality, int AThreads, IScriptEnvironment *Env, FrameInfoVector *AFrames); FFMatroskaSource(const char *ASource, int AVideoTrack, int AAudioTrack, const char *ATimecodes, bool AVCache, const char *AVideoCache, const char *AAudioCache, const char *APPString, int AQuality, int AThreads, IScriptEnvironment *Env);
~FFMatroskaSource(); ~FFMatroskaSource();
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env); PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env);
}; };
@ -196,11 +213,11 @@ private:
unsigned int BufferSize; unsigned int BufferSize;
uint8_t *Buffer; uint8_t *Buffer;
bool LoadSampleInfoFromFile(const char *AAudioCacheFile, const char *ADemuxedAudioFile, const char *ASource, int AAudioTrack); bool LoadSampleInfoFromFile(const char *AAudioCacheFile, const char *AAudioCacheFile2, const char *ASource, int AAudioTrack);
int DecodeNextAudioBlock(uint8_t *ABuf, int64_t *ACount, uint64_t AFilePos, unsigned int AFrameSize, IScriptEnvironment *Env); int DecodeNextAudioBlock(uint8_t *ABuf, int64_t *ACount, uint64_t AFilePos, unsigned int AFrameSize, IScriptEnvironment *Env);
int GetTrackIndex(int Index, CodecType ATrackType, IScriptEnvironment *Env); int GetTrackIndex(int Index, CodecType ATrackType, IScriptEnvironment *Env);
public: public:
FFmpegAudioSource(const char *ASource, int AAudioTrack, const char *AAudioCache, const char *ADemuxedAudioFile, IScriptEnvironment *Env); FFmpegAudioSource(const char *ASource, int AAudioTrack, const char *AAudioCache, const char *AAudioCacheFile2, IScriptEnvironment *Env);
~FFmpegAudioSource(); ~FFmpegAudioSource();
void __stdcall GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment *Env); void __stdcall GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment *Env);

View File

@ -7,7 +7,7 @@ FFmpegSource Documentation
<body> <body>
<h1>FFmpegSource Documentation</h1> <h1>FFmpegSource Documentation</h1>
<p> <p>
Loads video files without sucking Opens files using ffmpeg and nothing else. May be frame accurate on good days. The source is BSD licensed and can be obtained from https://spaceboyz.net/svn/aegisub/trunk/FFmpegSource. The precompiled binary is GPL licensed.
</p> </p>
<h2>Compatibility - Video</h2> <h2>Compatibility - Video</h2>
@ -17,18 +17,19 @@ Loads video files without sucking
<li>OGM: Messed up first frame and seeking produces smearing with seekmode=3, incredibly slow seeking without, remux to mkv or avi</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>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>MPG: Seeking seems to be off by one or two frames now and then</li>
<li>TS: don't bother</li> <li>M2TS, TS: Linear access only (seekmode=-1)</li>
<li>Image files: most formats can be opened if seekmode=-1 is set</li> <li>Image files: most formats can be opened if seekmode=-1 is set</li>
</ul> </ul>
<h2>Compatibility - Audio</h2> <h2>Compatibility - Audio</h2>
<ul> <ul>
<li>Should be sample accurate in all containers with audio cache</li> <li>Should be sample accurate in all containers with audio cache</li>
<li>Can produce very bad distortions when caching is not used for certain formats like aac</li>
</ul> </ul>
<h2>Usage</h2> <h2>Usage</h2>
<p> <p>
<b>FFmpegSource(string source, int vtrack = -1, int atrack = -2, string timecodes, bool vcache = true, string vcachefile, string acachefile, string pp, int ppquality = 6, int threads = 1, int seekmode = 1)</b><br /> <b>FFmpegSource(string source, int vtrack = -1, int atrack = -2, string timecodes, bool vcache = true, string vcachefile, string acachefile, string pp, int ppquality = 6, int threads = -1, int seekmode = 1)</b><br />
</p> </p>
<p> <p>
@ -36,7 +37,7 @@ Note that the audio cache will always be created when opening files with audio a
</p> </p>
<p> <p>
<b>FFAudioSource(string source, int atrack = -1, string acachefile, string ademuxedfile)</b><br /> <b>FFAudioSource(string source, int atrack = -1, string acachefile, string acachefile2)</b><br />
</p> </p>
<p> <p>
@ -48,6 +49,11 @@ Experimental, may or may not be accurate enough for real usage.
Separate postprocessing which also seems to include a few simple deinterlacers Separate postprocessing which also seems to include a few simple deinterlacers
</p> </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>
<p> <p>
<b>source:</b> <b>source:</b>
Source file. Source file.
@ -70,13 +76,8 @@ Experimental, may or may not be accurate enough for real usage.
</p> </p>
<p> <p>
<b>vcachefile &amp; acachefile:</b> <b>vcachefile, acachefile &amp; acachefile2:</b>
Specifies the file to store the index information or raw audio in, if nothing is specified (source).ffv(tracknumber)cache is used for video and (source).ffa(d if FFAudioSource is used)(tracknumber)cache for audio. Specifies the file to store the index information or raw audio in, if nothing is specified (source).ffv(tracknumber)cache is used for video and (source).ffa(d if FFAudioSource is used)(tracknumber)cache for audio. The second audio cache file is only required/created when not opening matroska files.
</p>
<p>
<b>ademuxedfile:</b>
Specifies the file to store the demuxed audio stream in. Only used by FFAudioSource if the stream isn't matroska. If nothing is specified (source).ffasd(tracknumber)cache is used.
</p> </p>
<p> <p>
@ -91,7 +92,7 @@ Experimental, may or may not be accurate enough for real usage.
<p> <p>
<b>threads:</b> <b>threads:</b>
Sets the number of decoder threads used, ignored if the used decoder doesn't implement it. 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>
<p> <p>
@ -104,6 +105,24 @@ Experimental, may or may not be accurate enough for real usage.
<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 <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>
<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> <h2>PP string format</h2>
<pre> <pre>
Available postprocessing filters: Available postprocessing filters:
@ -165,6 +184,13 @@ Note that --enable-w32threads is required for multithreaded decoding to work.
<h2>Changes</h2> <h2>Changes</h2>
<ul> <ul>
<li>1.19<ul>
<li>Now automatically detects the number of cpus and uses it as the default for the number of decoding threads</li>
<li>Added SWScale filter which can perform colorspace conversions and resizing and has many different resizers to choose from</li>
<li>Now exports the stored cropping values in mkv files in the variables FFCROP_LEFT, FFCROP_RIGHT, FFCROP_TOP and FFCROP_BOTTOM</li>
<li>Updated FFmpeg to rev 13572</li>
</ul></li>
<li>1.18<ul> <li>1.18<ul>
<li>Reverted error handling because it broke vc1</li> <li>Reverted error handling because it broke vc1</li>
</ul></li> </ul></li>

View File

@ -48,6 +48,52 @@ int GetSWSCPUFlags(IScriptEnvironment *Env) {
return Flags; return Flags;
} }
int CSNameToPIXFMT(const char * ACSName, int ADefault) {
if (!strcmpi(ACSName, ""))
return ADefault;
if (!strcmpi(ACSName, "YV12"))
return PIX_FMT_YUV420P;
if (!strcmpi(ACSName, "YUY2"))
return PIX_FMT_YUYV422;
if (!strcmpi(ACSName, "RGB24"))
return PIX_FMT_BGR24;
if (!strcmpi(ACSName, "RGB32"))
return PIX_FMT_RGB32;
return PIX_FMT_NONE;
}
int ResizerNameToSWSResizer(const char *AResizerName) {
if (!strcmpi(AResizerName, "FAST_BILINEAR"))
return SWS_FAST_BILINEAR;
if (!strcmpi(AResizerName, "BILINEAR"))
return SWS_BILINEAR;
if (!strcmpi(AResizerName, "BICUBIC"))
return SWS_BICUBIC;
if (!strcmpi(AResizerName, "X"))
return SWS_X;
if (!strcmpi(AResizerName, "POINT"))
return SWS_POINT;
if (!strcmpi(AResizerName, "AREA"))
return SWS_AREA;
if (!strcmpi(AResizerName, "BICUBLIN"))
return SWS_BICUBLIN;
if (!strcmpi(AResizerName, "GAUSS"))
return SWS_GAUSS;
if (!strcmpi(AResizerName, "SINC"))
return SWS_SINC;
if (!strcmpi(AResizerName, "LANCZOS"))
return SWS_LANCZOS;
if (!strcmpi(AResizerName, "SPLINE"))
return SWS_SPLINE;
return 0;
}
int GetNumberOfLogicalCPUs() {
SYSTEM_INFO SI;
GetSystemInfo(&SI);
return SI.dwNumberOfProcessors;
}
AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnvironment* Env) { AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
if (!UserData) { if (!UserData) {
av_register_all(); av_register_all();
@ -66,7 +112,7 @@ AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnviro
const char *ACacheFile = Args[6].AsString(""); const char *ACacheFile = Args[6].AsString("");
const char *PPString = Args[7].AsString(""); const char *PPString = Args[7].AsString("");
int PPQuality = Args[8].AsInt(PP_QUALITY_MAX); int PPQuality = Args[8].AsInt(PP_QUALITY_MAX);
int Threads = Args[9].AsInt(1); int Threads = Args[9].AsInt(-1);
int SeekMode = Args[10].AsInt(1); int SeekMode = Args[10].AsInt(1);
if (VTrack <= -2 && ATrack <= -2) if (VTrack <= -2 && ATrack <= -2)
@ -75,6 +121,8 @@ AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnviro
if (SeekMode < -1 || SeekMode > 3) if (SeekMode < -1 || SeekMode > 3)
Env->ThrowError("FFmpegSource: Invalid seekmode selected"); Env->ThrowError("FFmpegSource: Invalid seekmode selected");
if (Threads <= 0)
Threads = GetNumberOfLogicalCPUs();
if (Threads < 1) if (Threads < 1)
Env->ThrowError("FFmpegSource: Invalid thread count"); Env->ThrowError("FFmpegSource: Invalid thread count");
@ -85,22 +133,20 @@ AVSValue __cdecl CreateFFmpegSource(AVSValue Args, void* UserData, IScriptEnviro
bool IsMatroska = !strcmp(FormatContext->iformat->name, "matroska"); bool IsMatroska = !strcmp(FormatContext->iformat->name, "matroska");
av_close_input_file(FormatContext); av_close_input_file(FormatContext);
FrameInfoVector Frames;
if (IsMatroska) { if (IsMatroska) {
return new FFMatroskaSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, PPString, PPQuality, Threads, Env, &Frames); return new FFMatroskaSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, PPString, PPQuality, Threads, Env);
} else { } else {
// Do a separate indexing pass, enjoy the constructor sideeffects // Do a separate indexing pass, enjoy the constructor sideeffects
if (SeekMode == -1) if (SeekMode == -1)
delete new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, PPString, PPQuality, Threads, -2, Env, &Frames); delete new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, PPString, PPQuality, Threads, -2, Env);
return new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, PPString, PPQuality, Threads, SeekMode, Env, &Frames); return new FFmpegSource(Source, VTrack, ATrack, Timecodes, VCache, VCacheFile, ACacheFile, PPString, PPQuality, Threads, SeekMode, Env);
} }
} }
AVSValue __cdecl CreateFFAudioSource(AVSValue Args, void* UserData, IScriptEnvironment* Env) { AVSValue __cdecl CreateFFAudioSource(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
if (!UserData) { if (!UserData) {
av_register_all(); av_register_all();
UserData = (void *)-1; UserData = (void *)1;
} }
if (!Args[0].Defined()) if (!Args[0].Defined())
@ -132,9 +178,14 @@ AVSValue __cdecl CreateFFPP(AVSValue Args, void* UserData, IScriptEnvironment* E
return new FFPP(Args[0].AsClip(), Args[1].AsString(""), Args[2].AsInt(PP_QUALITY_MAX), Env); return new FFPP(Args[0].AsClip(), Args[1].AsString(""), Args[2].AsInt(PP_QUALITY_MAX), 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);
}
extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* Env) { extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* Env) {
Env->AddFunction("FFmpegSource", "[source]s[vtrack]i[atrack]i[timecodes]s[vcache]b[vcachefile]s[acachefile]s[pp]s[ppquality]i[threads]i[seekmode]i", CreateFFmpegSource, 0); Env->AddFunction("FFmpegSource", "[source]s[vtrack]i[atrack]i[timecodes]s[vcache]b[vcachefile]s[acachefile]s[pp]s[ppquality]i[threads]i[seekmode]i", CreateFFmpegSource, 0);
Env->AddFunction("FFAudioSource", "[source]s[atrack]i[acachefile]s[ademuxedfile]s", CreateFFAudioSource, 0); Env->AddFunction("FFAudioSource", "[source]s[atrack]i[acachefile]s[acachefile2]s", CreateFFAudioSource, 0);
Env->AddFunction("FFPP", "c[pp]s[ppquality]i", CreateFFPP, 0); Env->AddFunction("FFPP", "c[pp]s[ppquality]i", CreateFFPP, 0);
Env->AddFunction("SWScale", "c[width]i[height]i[resizer]s[colorspace]s", CreateSWScale, 0);
return "FFmpegSource"; return "FFmpegSource";
}; };

View File

@ -0,0 +1,99 @@
// Copyright (c) 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 "ffmpegsource.h"
SWScale::SWScale(PClip AChild, int AResizeToWidth, int AResizeToHeight, const char *AResizer, const char *AConvertToFormat, IScriptEnvironment *Env) : GenericVideoFilter(AChild) {
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 (AResizeToHeight <= 0)
AResizeToHeight = OrigHeight;
else
vi.height = AResizeToHeight;
if (AResizeToWidth <= 0)
AResizeToWidth = OrigWidth;
else
vi.width = AResizeToWidth;
int ConvertToFormat = CSNameToPIXFMT(AConvertToFormat, ConvertFromFormat);
if (ConvertToFormat == PIX_FMT_NONE)
Env->ThrowError("SWScale: Invalid colorspace specified (%s)", AConvertToFormat);
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(AResizer);
if (Resizer == 0)
Env->ThrowError("SWScale: Invalid resizer specified (%s)", AResizer);
if (ConvertToFormat == PIX_FMT_YUV420P && vi.height & 1)
Env->ThrowError("SWScale: mod 2 output height required", AResizer);
if ((ConvertToFormat == PIX_FMT_YUV420P || ConvertToFormat == PIX_FMT_YUYV422) && vi.width & 1)
Env->ThrowError("SWScale: mod 2 output width required", AResizer);
// may one day need a SWS_CS_DEFAULT in flags
Context = sws_getContext(OrigWidth, OrigHeight, ConvertFromFormat, vi.width, vi.height, ConvertToFormat, GetSWSCPUFlags(Env) | Resizer, NULL, NULL, NULL);
}
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

@ -108,8 +108,9 @@ CodecID MatroskaToFFCodecID(TrackInfo *TI) {
case MAKEFOURCC('P', 'D', 'V', 'C'): case MAKEFOURCC('P', 'D', 'V', 'C'):
return CODEC_ID_DVVIDEO; return CODEC_ID_DVVIDEO;
case MAKEFOURCC('H', 'F', 'Y', 'U'): case MAKEFOURCC('H', 'F', 'Y', 'U'):
case MAKEFOURCC('F', 'F', 'V', 'H'):
return CODEC_ID_HUFFYUV; return CODEC_ID_HUFFYUV;
case MAKEFOURCC('F', 'F', 'V', 'H'):
return CODEC_ID_FFVHUFF;
case MAKEFOURCC('C', 'Y', 'U', 'V'): case MAKEFOURCC('C', 'Y', 'U', 'V'):
return CODEC_ID_CYUV; return CODEC_ID_CYUV;
case MAKEFOURCC('A', 'S', 'V', '1'): case MAKEFOURCC('A', 'S', 'V', '1'):