FFmpegSource2: semi vfr fix

Originally committed to SVN as r2403.
This commit is contained in:
Fredrik Mellbin 2008-10-01 18:13:12 +00:00
parent 965cc7bfe2
commit b0137363f6
7 changed files with 61 additions and 36 deletions

View File

@ -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;
VI.fps_denominator = VP.FPSDenominator;
VI.fps_numerator = VP.FPSNumerator;
VI.num_frames = VP.NumFrames;
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;

View File

@ -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) { }

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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,8 +128,10 @@ 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)
@ -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);

View File

@ -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();
};