FFmpegSource2: semi vfr fix
Originally committed to SVN as r2403.
This commit is contained in:
parent
965cc7bfe2
commit
b0137363f6
7 changed files with 61 additions and 36 deletions
|
@ -21,10 +21,12 @@
|
|||
#include "ffavisynth.h"
|
||||
#include "utils.h"
|
||||
|
||||
AvisynthVideoSource::AvisynthVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, const char *PP, int Threads, int SeekMode, IScriptEnvironment* Env, char *ErrorMsg, unsigned MsgSize) {
|
||||
AvisynthVideoSource::AvisynthVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, int FPSNum, int FPSDen, const char *PP, int Threads, int SeekMode, IScriptEnvironment* Env, char *ErrorMsg, unsigned MsgSize) {
|
||||
memset(&VI, 0, sizeof(VI));
|
||||
SWS = NULL;
|
||||
ConvertToFormat = PIX_FMT_NONE;
|
||||
this->FPSNum = FPSNum;
|
||||
this->FPSDen = FPSDen;
|
||||
|
||||
VS = FFMS_CreateVideoSource(SourceFile, Track, TrackIndices, PP, Threads, SeekMode, ErrorMsg, MsgSize);
|
||||
if (!VS)
|
||||
|
@ -35,9 +37,16 @@ AvisynthVideoSource::AvisynthVideoSource(const char *SourceFile, int Track, Fram
|
|||
VI.image_type = VideoInfo::IT_TFF;
|
||||
VI.width = VP.Width;
|
||||
VI.height = VP.Height;
|
||||
|
||||
if (FPSNum > 0 && FPSDen > 0) {
|
||||
VI.fps_denominator = FPSDen;
|
||||
VI.fps_numerator = FPSNum;
|
||||
VI.num_frames = ceil(((VP.LastTime - VP.FirstTime) * FPSNum) / FPSDen);
|
||||
} else {
|
||||
VI.fps_denominator = VP.FPSDenominator;
|
||||
VI.fps_numerator = VP.FPSNumerator;
|
||||
VI.num_frames = VP.NumFrames;
|
||||
}
|
||||
|
||||
try {
|
||||
InitOutputFormat(VP.PixelFormat, Env);
|
||||
|
@ -129,7 +138,13 @@ PVideoFrame AvisynthVideoSource::OutputFrame(const AVFrameLite *Frame, IScriptEn
|
|||
PVideoFrame AvisynthVideoSource::GetFrame(int n, IScriptEnvironment *Env) {
|
||||
char ErrorMsg[1024];
|
||||
unsigned MsgSize = sizeof(ErrorMsg);
|
||||
const AVFrameLite *Frame = FFMS_GetFrame(VS, n, ErrorMsg, MsgSize);
|
||||
const AVFrameLite *Frame;
|
||||
|
||||
if (FPSNum > 0 && FPSDen > 0)
|
||||
Frame = FFMS_GetFrameByTime(VS, FFMS_GetVideoProperties(VS)->FirstTime + (double)(n * (int64_t)FPSDen) / FPSNum, ErrorMsg, MsgSize);
|
||||
else
|
||||
Frame = FFMS_GetFrame(VS, n, ErrorMsg, MsgSize);
|
||||
|
||||
if (Frame == NULL)
|
||||
Env->ThrowError("FFVideoSource: %s", ErrorMsg);
|
||||
|
||||
|
@ -137,7 +152,6 @@ PVideoFrame AvisynthVideoSource::GetFrame(int n, IScriptEnvironment *Env) {
|
|||
return OutputFrame(Frame, Env);
|
||||
}
|
||||
|
||||
|
||||
AvisynthAudioSource::AvisynthAudioSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, IScriptEnvironment* Env, char *ErrorMsg, unsigned MsgSize) {
|
||||
memset(&VI, 0, sizeof(VI));
|
||||
|
||||
|
@ -147,7 +161,6 @@ AvisynthAudioSource::AvisynthAudioSource(const char *SourceFile, int Track, Fram
|
|||
|
||||
const AudioProperties AP = *FFMS_GetAudioProperties(AS);
|
||||
|
||||
|
||||
VI.nchannels = AP.Channels;
|
||||
VI.num_audio_samples = AP.NumSamples;
|
||||
VI.audio_samples_per_second = AP.SampleRate;
|
||||
|
|
|
@ -38,11 +38,13 @@ private:
|
|||
VideoBase *VS;
|
||||
SwsContext *SWS;
|
||||
int ConvertToFormat;
|
||||
int FPSNum;
|
||||
int FPSDen;
|
||||
|
||||
void InitOutputFormat(int CurrentFormat, IScriptEnvironment *Env);
|
||||
PVideoFrame OutputFrame(const AVFrameLite *SrcPicture, IScriptEnvironment *Env);
|
||||
public:
|
||||
AvisynthVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, const char *PP, int Threads, int SeekMode, IScriptEnvironment* Env, char *ErrorMsg, unsigned MsgSize);
|
||||
AvisynthVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, int FPSNum, int FPSDen, const char *PP, int Threads, int SeekMode, IScriptEnvironment* Env, char *ErrorMsg, unsigned MsgSize);
|
||||
~AvisynthVideoSource();
|
||||
bool __stdcall GetParity(int n) { return false; }
|
||||
void __stdcall SetCacheHints(int cachehints, int frame_range) { }
|
||||
|
|
|
@ -92,10 +92,12 @@ AVSValue __cdecl CreateFFVideoSource(AVSValue Args, void* UserData, IScriptEnvir
|
|||
int Track = Args[1].AsInt(-1);
|
||||
bool Cache = Args[2].AsBool(true);
|
||||
const char *CacheFile = Args[3].AsString("");
|
||||
const char *PP = Args[4].AsString("");
|
||||
int Threads = Args[5].AsInt(-1);
|
||||
const char *Timecodes = Args[6].AsString("");
|
||||
int SeekMode = Args[7].AsInt(1);
|
||||
int FPSNum = Args[4].AsInt(-1);
|
||||
int FPSDen = Args[5].AsInt(1);
|
||||
const char *PP = Args[6].AsString("");
|
||||
int Threads = Args[7].AsInt(-1);
|
||||
const char *Timecodes = Args[8].AsString("");
|
||||
int SeekMode = Args[9].AsInt(1);
|
||||
|
||||
if (Track <= -2)
|
||||
Env->ThrowError("FFVideoSource: No video track selected");
|
||||
|
@ -145,7 +147,7 @@ AVSValue __cdecl CreateFFVideoSource(AVSValue Args, void* UserData, IScriptEnvir
|
|||
AvisynthVideoSource *Filter;
|
||||
|
||||
try {
|
||||
Filter = new AvisynthVideoSource(Source, Track, Index, PP, Threads, SeekMode, Env, ErrorMsg, MsgSize);
|
||||
Filter = new AvisynthVideoSource(Source, Track, Index, FPSNum, FPSDen, PP, Threads, SeekMode, Env, ErrorMsg, MsgSize);
|
||||
} catch (...) {
|
||||
FFMS_DestroyFrameIndex(Index);
|
||||
throw;
|
||||
|
@ -219,7 +221,7 @@ AVSValue __cdecl CreateSWScale(AVSValue Args, void* UserData, IScriptEnvironment
|
|||
|
||||
extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* Env) {
|
||||
Env->AddFunction("FFIndex", "[source]s[cachefile]s[indexmask]i[dumpmask]i[audiofile]s[overwrite]b", CreateFFIndex, 0);
|
||||
Env->AddFunction("FFVideoSource", "[source]s[track]i[cache]b[cachefile]s[pp]s[threads]i[timecodes]s[seekmode]i", CreateFFVideoSource, 0);
|
||||
Env->AddFunction("FFVideoSource", "[source]s[track]i[cache]b[cachefile]s[fpsnum]i[fpsden]i[pp]s[threads]i[timecodes]s[seekmode]i", CreateFFVideoSource, 0);
|
||||
Env->AddFunction("FFAudioSource", "[source]s[track]i[cache]b[cachefile]s", CreateFFAudioSource, 0);
|
||||
Env->AddFunction("FFPP", "c[pp]s", CreateFFPP, 0);
|
||||
Env->AddFunction("SWScale", "c[width]i[height]i[resizer]s[colorspace]s", CreateSWScale, 0);
|
||||
|
|
|
@ -110,8 +110,8 @@ FFMS_API(int) FFMS_GetAudio(AudioBase *AB, void *Buf, int64_t Start, int64_t Cou
|
|||
return AB->GetAudio(Buf, Start, Count, ErrorMsg, MsgSize);
|
||||
}
|
||||
|
||||
FFMS_API(int) FFMS_SetOutputFormat(VideoBase *VB, int TargetFormat, int Width, int Height) {
|
||||
return VB->SetOutputFormat(TargetFormat, Width, Height);
|
||||
FFMS_API(int) FFMS_SetOutputFormat(VideoBase *VB, int TargetFormat, int Width, int Height, char *ErrorMsg, unsigned MsgSize) {
|
||||
return VB->SetOutputFormat(TargetFormat, Width, Height, ErrorMsg, MsgSize);
|
||||
}
|
||||
|
||||
FFMS_API(void) FFMS_ResetOutputFormat(VideoBase *VB) {
|
||||
|
@ -130,15 +130,15 @@ FFMS_API(int) FFMS_GetFirstTrackOfType(FrameIndex *TrackIndices, int TrackType,
|
|||
return -1;
|
||||
}
|
||||
|
||||
FFMS_API(int) FFMS_GetNumTracks(FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize) {
|
||||
FFMS_API(int) FFMS_GetNumTracks(FrameIndex *TrackIndices) {
|
||||
return TrackIndices->size();
|
||||
}
|
||||
|
||||
FFMS_API(int) FFMS_GetTrackType(FrameInfoVector *FIV, char *ErrorMsg, unsigned MsgSize) {
|
||||
FFMS_API(int) FFMS_GetTrackType(FrameInfoVector *FIV) {
|
||||
return FIV->TT;
|
||||
}
|
||||
|
||||
FFMS_API(int) FFMS_GetNumFrames(FrameInfoVector *FIV, char *ErrorMsg, unsigned MsgSize) {
|
||||
FFMS_API(int) FFMS_GetNumFrames(FrameInfoVector *FIV) {
|
||||
return FIV->size();
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,7 @@ FFMS_API(FrameInfoVector *) FFMS_GetTITrackIndex(FrameIndex *TrackIndices, int T
|
|||
}
|
||||
}
|
||||
|
||||
FFMS_API(FrameInfoVector *) FFMS_GetVSTrackIndex(VideoBase *VB, char *ErrorMsg, unsigned MsgSize) {
|
||||
FFMS_API(FrameInfoVector *) FFMS_GetVSTrackIndex(VideoBase *VB) {
|
||||
return VB->GetFrameInfoVector();
|
||||
}
|
||||
|
||||
|
@ -173,15 +173,15 @@ FFMS_API(int) FFMS_FindClosestKeyFrame(FrameInfoVector *FIV, int Frame, char *Er
|
|||
}
|
||||
}
|
||||
|
||||
FFMS_API(int) FFMS_FrameFromDTS(FrameInfoVector *FIV, int64_t DTS, char *ErrorMsg, unsigned MsgSize) {
|
||||
FFMS_API(int) FFMS_FrameFromDTS(FrameInfoVector *FIV, int64_t DTS) {
|
||||
return FIV->FrameFromDTS(DTS);
|
||||
}
|
||||
|
||||
FFMS_API(int) FFMS_ClosestFrameFromDTS(FrameInfoVector *FIV, int64_t DTS, char *ErrorMsg, unsigned MsgSize) {
|
||||
FFMS_API(int) FFMS_ClosestFrameFromDTS(FrameInfoVector *FIV, int64_t DTS) {
|
||||
return FIV->ClosestFrameFromDTS(DTS);
|
||||
}
|
||||
|
||||
FFMS_API(const TrackTimeBase *) FFMS_GetTimeBase(FrameInfoVector *FIV, char *ErrorMsg, unsigned MsgSize) {
|
||||
FFMS_API(const TrackTimeBase *) FFMS_GetTimeBase(FrameInfoVector *FIV) {
|
||||
return &FIV->TB;
|
||||
}
|
||||
|
||||
|
|
|
@ -157,6 +157,8 @@ struct AudioProperties {
|
|||
int64_t NumSamples;
|
||||
};
|
||||
|
||||
// Most functions return 0 on success
|
||||
// Functions without error message output can be assumed to never fail
|
||||
FFMS_API(void) FFMS_Init();
|
||||
FFMS_API(VideoBase *) FFMS_CreateVideoSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, const char *PP, int Threads, int SeekMode, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(AudioBase *) FFMS_CreateAudioSource(const char *SourceFile, int Track, FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize);
|
||||
|
@ -167,21 +169,21 @@ FFMS_API(const AudioProperties *) FFMS_GetAudioProperties(AudioBase *AB);
|
|||
FFMS_API(const AVFrameLite *) FFMS_GetFrame(VideoBase *VB, int n, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(const AVFrameLite *) FFMS_GetFrameByTime(VideoBase *VB, double Time, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(int) FFMS_GetAudio(AudioBase *AB, void *Buf, int64_t Start, int64_t Count, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(int) FFMS_SetOutputFormat(VideoBase *VB, int TargetFormat, int Width, int Height);
|
||||
FFMS_API(int) FFMS_SetOutputFormat(VideoBase *VB, int TargetFormat, int Width, int Height, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(void) FFMS_ResetOutputFormat(VideoBase *VB);
|
||||
FFMS_API(void) FFMS_DestroyFrameIndex(FrameIndex *FI);
|
||||
FFMS_API(int) FFMS_GetFirstTrackOfType(FrameIndex *TrackIndices, int TrackType, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(int) FFMS_GetNumTracks(FrameIndex *TrackIndices, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(int) FFMS_GetTrackType(FrameInfoVector *FIV, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(int) FFMS_GetNumFrames(FrameInfoVector *FIV, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(int) FFMS_GetNumTracks(FrameIndex *TrackIndices);
|
||||
FFMS_API(int) FFMS_GetTrackType(FrameInfoVector *FIV);
|
||||
FFMS_API(int) FFMS_GetNumFrames(FrameInfoVector *FIV);
|
||||
FFMS_API(const FrameInfo *) FFMS_GetFrameInfo(FrameInfoVector *FIV, int Frame, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(FrameInfoVector *) FFMS_GetTITrackIndex(FrameIndex *TrackIndices, int Track, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(FrameInfoVector *) FFMS_GetVSTrackIndex(VideoBase *VB, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(FrameInfoVector *) FFMS_GetASTrackIndex(AudioBase *AB, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(FrameInfoVector *) FFMS_GetVSTrackIndex(VideoBase *VB);
|
||||
FFMS_API(FrameInfoVector *) FFMS_GetASTrackIndex(AudioBase *AB);
|
||||
FFMS_API(int) FFMS_FindClosestKeyFrame(FrameInfoVector *FIV, int Frame, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(int) FFMS_FrameFromDTS(FrameInfoVector *FIV, int64_t DTS, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(int) FFMS_ClosestFrameFromDTS(FrameInfoVector *FIV, int64_t DTS, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(const TrackTimeBase *) FFMS_GetTimeBase(FrameInfoVector *FIV, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(int) FFMS_FrameFromDTS(FrameInfoVector *FIV, int64_t DTS);
|
||||
FFMS_API(int) FFMS_ClosestFrameFromDTS(FrameInfoVector *FIV, int64_t DTS);
|
||||
FFMS_API(const TrackTimeBase *) FFMS_GetTimeBase(FrameInfoVector *FIV);
|
||||
FFMS_API(int) FFMS_WriteTimecodes(FrameInfoVector *FIV, const char *TimecodeFile, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(FrameIndex *) FFMS_MakeIndex(const char *SourceFile, int IndexMask, int DumpMask, const char *AudioFile, bool IgnoreDecodeErrors, IndexCallback IP, void *Private, char *ErrorMsg, unsigned MsgSize);
|
||||
FFMS_API(FrameIndex *) FFMS_ReadIndex(const char *IndexFile, char *ErrorMsg, unsigned MsgSize);
|
||||
|
|
|
@ -110,11 +110,11 @@ VideoBase::~VideoBase() {
|
|||
}
|
||||
|
||||
AVFrameLite *VideoBase::GetFrameByTime(double Time, char *ErrorMsg, unsigned MsgSize) {
|
||||
int Frame = Frames.ClosestFrameFromDTS(Time * Frames.TB.Den / Frames.TB.Num);
|
||||
int Frame = Frames.ClosestFrameFromDTS((Time * Frames.TB.Num) / Frames.TB.Den);
|
||||
return GetFrame(Frame, ErrorMsg, MsgSize);
|
||||
}
|
||||
|
||||
int VideoBase::SetOutputFormat(int TargetFormats, int Width, int Height) {
|
||||
int VideoBase::SetOutputFormat(int TargetFormats, int Width, int Height, char *ErrorMsg, unsigned MsgSize) {
|
||||
// FIXME: investigate the possible bug in avcodec_find_best_pix_fmt
|
||||
// int Loss;
|
||||
// int OutputFormat = avcodec_find_best_pix_fmt(TargetFormats,
|
||||
|
@ -128,9 +128,11 @@ int VideoBase::SetOutputFormat(int TargetFormats, int Width, int Height) {
|
|||
if (CodecContext->pix_fmt != OutputFormat || Width != CodecContext->width || Height != CodecContext->height) {
|
||||
NewSWS = sws_getContext(CodecContext->width, CodecContext->height, CodecContext->pix_fmt, Width, Height,
|
||||
OutputFormat, GetCPUFlags() | SWS_BICUBIC, NULL, NULL, NULL);
|
||||
if (NewSWS == NULL)
|
||||
if (NewSWS == NULL) {
|
||||
_snprintf(ErrorMsg, MsgSize, "Failed to allocate SWScale context");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (SWS)
|
||||
sws_freeContext(SWS);
|
||||
|
@ -234,6 +236,8 @@ FFVideoSource::FFVideoSource(const char *SourceFile, int Track, FrameIndex *Trac
|
|||
VP.FPSNumerator = FormatContext->streams[VideoTrack]->time_base.den;
|
||||
VP.NumFrames = Frames.size();
|
||||
VP.PixelFormat = CodecContext->pix_fmt;
|
||||
VP.FirstTime = (Frames.front().DTS * Frames.TB.Den) / (double)Frames.TB.Num;
|
||||
VP.LastTime = (Frames.back().DTS * Frames.TB.Den) / (double)Frames.TB.Num;
|
||||
|
||||
if (VP.Width <= 0 || VP.Height <= 0) {
|
||||
Free(true);
|
||||
|
@ -451,6 +455,8 @@ MatroskaVideoSource::MatroskaVideoSource(const char *SourceFile, int Track,
|
|||
VP.FPSNumerator = 30;
|
||||
VP.NumFrames = Frames.size();
|
||||
VP.PixelFormat = CodecContext->pix_fmt;
|
||||
VP.FirstTime = (Frames.front().DTS * Frames.TB.Den) / (double)Frames.TB.Num;
|
||||
VP.LastTime = (Frames.back().DTS * Frames.TB.Den) / (double)Frames.TB.Num;
|
||||
|
||||
if (VP.Width <= 0 || VP.Height <= 0) {
|
||||
Free(true);
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
FrameInfoVector *GetFrameInfoVector() { return &Frames; }
|
||||
virtual AVFrameLite *GetFrame(int n, char *ErrorMsg, unsigned MsgSize) = 0;
|
||||
AVFrameLite *GetFrameByTime(double Time, char *ErrorMsg, unsigned MsgSize);
|
||||
int SetOutputFormat(int TargetFormats, int Width, int Height);
|
||||
int SetOutputFormat(int TargetFormats, int Width, int Height, char *ErrorMsg, unsigned MsgSize);
|
||||
void ResetOutputFormat();
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue