Skip to content

Commit a983269

Browse files
committed
Remove rffmode completely
1 parent 0a279ab commit a983269

8 files changed

+60
-211
lines changed

doc/ffms2-avisynth.md

+3-19
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ Corresponds to the FFmpeg demuxer option of the same name. You will know if you
116116
```
117117
FFVideoSource(string source, int track = -1, bool cache = true,
118118
string cachefile = source + ".ffindex", int fpsnum = -1, int fpsden = 1,
119-
int threads = -1, string timecodes = "", int seekmode = 1, int rffmode = 0,
119+
int threads = -1, string timecodes = "", int seekmode = 1,
120120
int width = -1, int height = -1, string resizer = "BICUBIC",
121121
string colorspace = "", string varprefix = "")
122122
```
@@ -173,21 +173,6 @@ Valid modes are:
173173
- **2**: Unsafe normal. Same as mode 1, but no error will be thrown if the exact seek destination has to be guessed.
174174
- **3**: Aggressive. Seeks in the forward direction even if no closer keyframe is known to exist. Only useful for testing and containers where libavformat doesn't report keyframes properly.
175175

176-
##### int rffmode = 0
177-
Controls how RFF flags in the video stream are treated; in other words it's equivalent to the "field operation" mode switch in DVD2AVI/DGIndex.
178-
Valid modes are:
179-
180-
- **0**: Ignore all flags (the default mode).
181-
- **1**: Honor all pulldown flags.
182-
- **2**: Equivalent to DVD2AVI's "force film" mode.
183-
184-
Note that using modes 1 or 2 will make `FFVideoSource` throw an error if the video stream has no RFF flags at all.
185-
When using either of those modes, it will also make the output be assumed as CFR, disallow vertical scaling and disallow setting the output colorspace.
186-
`FFPICT_TYPE` will also not be set as the output is a combination of several frames.
187-
Other subtle behavior changes may also exist.
188-
189-
Also note that "force film" is mostly useless and only here for completeness' sake, since if your source really is safe to force film on, using mode 0 will have the exact same effect while being considerably more efficient.
190-
191176
##### int width = -1, int height = -1
192177
Sets the resolution of the output video, in pixels.
193178
Setting either dimension to less than or equal to zero means the resolution of the first decoded video frame is used for that dimension.
@@ -251,7 +236,7 @@ FFmpegSource2/FFMS2(string source, int vtrack = -1, int atrack = -2, bool cache
251236
string cachefile = source + ".ffindex", int fpsnum = -1, int fpsden = 1,
252237
int threads = -1, string timecodes = "", int seekmode = 1,
253238
bool overwrite = false, int width = -1, int height = -1,
254-
string resizer = "BICUBIC", string colorspace = "", int rffmode = 0,
239+
string resizer = "BICUBIC", string colorspace = "",
255240
int adjustdelay = -1, string varprefix = "")
256241
```
257242
A convenience function that combines the functionality of `FFVideoSource` and `FFAudioSource`.
@@ -379,7 +364,6 @@ Note that using the width/height/colorspace parameters to FFVideoSource may unde
379364
##### FFPICT_TYPE
380365
The picture type of the most recently requested frame as the ASCII number of the character listed below.
381366
Use `Chr()` to convert it to an actual letter in Avisynth. Use after_frame=true in Avisynth's conditional scripting for proper results.
382-
Only set when rffmode=0.
383367
The FFmpeg source definition of the characters:
384368
```
385369
I: Intra
@@ -394,7 +378,7 @@ b: FF_BI_TYPE (no good explanation available)
394378

395379
##### FFVFR_TIME
396380
The actual time of the source frame in milliseconds.
397-
Only set when no type of CFR conversion is being done (`rffmode` and `fpsnum` left at their defaults).
381+
Only set when no type of CFR conversion is being done (`fpsnum` and `fpsden` left at their defaults).
398382

399383
##### FFCHANNEL_LAYOUT
400384
The audio channel layout of the audio stream.

doc/ffms2-changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- Alpha planes are now correctly marked as being full range
1212
- The full set of demuxer options can now be passed using the FFMS2 API
1313
- Now sets channel layout in Avisynth+
14+
- Removed the unfixable and always broken rffmode from Avisynth source
1415

1516
- 2.3000
1617
- Added support for VapourSynth API4 (Myrsloik)

src/avisynth/avisynth.cpp

+2-5
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,9 @@ static AVSValue __cdecl CreateFFVideoSource(AVSValue Args, void* UserData, IScri
115115
if (SeekMode < -1 || SeekMode > 3)
116116
Env->ThrowError("FFVideoSource: Invalid seekmode selected");
117117

118-
if (RFFMode < 0 || RFFMode > 2)
118+
if (RFFMode != 0)
119119
Env->ThrowError("FFVideoSource: Invalid RFF mode selected");
120120

121-
if (RFFMode > 0 && FPSNum > 0)
122-
Env->ThrowError("FFVideoSource: RFF modes may not be combined with CFR conversion");
123-
124121
if (IsSamePath(Source, Timecodes))
125122
Env->ThrowError("FFVideoSource: Timecodes will overwrite the source");
126123

@@ -177,7 +174,7 @@ static AVSValue __cdecl CreateFFVideoSource(AVSValue Args, void* UserData, IScri
177174
AvisynthVideoSource *Filter;
178175

179176
try {
180-
Filter = new AvisynthVideoSource(Source, Track, Index, FPSNum, FPSDen, Threads, SeekMode, RFFMode, Width, Height, Resizer, ColorSpace, VarPrefix, Env);
177+
Filter = new AvisynthVideoSource(Source, Track, Index, FPSNum, FPSDen, Threads, SeekMode, Width, Height, Resizer, ColorSpace, VarPrefix, Env);
181178
} catch (...) {
182179
FFMS_DestroyIndex(Index);
183180
throw;

src/avisynth/avssources.cpp

+50-171
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,11 @@ static AVPixelFormat CSNameToPIXFMT(const char *CSName, AVPixelFormat Default, b
114114
}
115115

116116
AvisynthVideoSource::AvisynthVideoSource(const char *SourceFile, int Track, FFMS_Index *Index,
117-
int AFPSNum, int AFPSDen, int Threads, int SeekMode, int RFFMode,
117+
int AFPSNum, int AFPSDen, int Threads, int SeekMode,
118118
int ResizeToWidth, int ResizeToHeight, const char *ResizerName,
119119
const char *ConvertToFormatName, const char *VarPrefix, IScriptEnvironment* Env)
120120
: FPSNum(AFPSNum)
121121
, FPSDen(AFPSDen)
122-
, RFFMode(RFFMode)
123122
, VarPrefix(VarPrefix) {
124123
VI = {};
125124

@@ -142,115 +141,24 @@ AvisynthVideoSource::AvisynthVideoSource(const char *SourceFile, int Track, FFMS
142141

143142
const FFMS_VideoProperties *VP = FFMS_GetVideoProperties(V);
144143

145-
if (RFFMode > 0) {
146-
// This part assumes things, and so should you
147-
148-
FFMS_Track *VTrack = FFMS_GetTrackFromVideo(V);
149-
150-
if (FFMS_GetFrameInfo(VTrack, 0)->RepeatPict < 0) {
151-
FFMS_DestroyVideoSource(V);
152-
Env->ThrowError("FFVideoSource: No RFF flags present");
153-
}
154-
155-
int RepeatMin = FFMS_GetFrameInfo(VTrack, 0)->RepeatPict;
156-
int NumFields = 0;
157-
158-
for (int i = 0; i < VP->NumFrames; i++) {
159-
int RepeatPict = FFMS_GetFrameInfo(VTrack, i)->RepeatPict;
160-
NumFields += RepeatPict + 1;
161-
RepeatMin = std::min(RepeatMin, RepeatPict);
162-
}
163-
164-
for (int i = 0; i < VP->NumFrames; i++) {
165-
int RepeatPict = FFMS_GetFrameInfo(VTrack, i)->RepeatPict;
166-
167-
if (((RepeatPict + 1) * 2) % (RepeatMin + 1)) {
168-
FFMS_DestroyVideoSource(V);
169-
Env->ThrowError("FFVideoSource: Unsupported RFF flag pattern");
170-
}
171-
}
172-
173-
VI.fps_denominator = VP->RFFDenominator * (RepeatMin + 1);
174-
VI.fps_numerator = VP->RFFNumerator;
175-
VI.num_frames = (NumFields + RepeatMin) / (RepeatMin + 1);
176-
177-
int DestField = 0;
178-
FieldList.resize(VI.num_frames);
179-
for (int i = 0; i < VP->NumFrames; i++) {
180-
int RepeatPict = FFMS_GetFrameInfo(VTrack, i)->RepeatPict;
181-
int RepeatFields = ((RepeatPict + 1) * 2) / (RepeatMin + 1);
182-
183-
for (int j = 0; j < RepeatFields; j++) {
184-
if ((DestField + (VP->TopFieldFirst ? 0 : 1)) & 1)
185-
FieldList[DestField / 2].Top = i;
186-
else
187-
FieldList[DestField / 2].Bottom = i;
188-
DestField++;
189-
}
190-
}
191-
192-
if (RFFMode == 2) {
193-
if (VP->TopFieldFirst) {
194-
for (auto &iter : FieldList)
195-
std::swap(iter.Top, iter.Bottom);
196-
}
197-
198-
VI.num_frames = (VI.num_frames * 4) / 5;
199-
VI.fps_denominator *= 5;
200-
VI.fps_numerator *= 4;
201-
202-
int OutputFrames = 0;
203-
204-
for (int i = 0; i < VI.num_frames / 4; i++) {
205-
bool HasDropped = false;
206-
207-
FieldList[OutputFrames].Top = FieldList[i * 5].Top;
208-
FieldList[OutputFrames].Bottom = FieldList[i * 5].Top;
209-
OutputFrames++;
210-
211-
for (int j = 1; j < 5; j++) {
212-
if (!HasDropped && FieldList[i * 5 + j - 1].Top == FieldList[i * 5 + j].Top) {
213-
HasDropped = true;
214-
continue;
215-
}
216-
217-
FieldList[OutputFrames].Top = FieldList[i * 5 + j].Top;
218-
FieldList[OutputFrames].Bottom = FieldList[i * 5 + j].Top;
219-
OutputFrames++;
220-
}
221-
222-
if (!HasDropped)
223-
OutputFrames--;
224-
}
225-
226-
if (OutputFrames > 0)
227-
for (int i = OutputFrames - 1; i < static_cast<int>(FieldList.size()); i++) {
228-
FieldList[i].Top = FieldList[OutputFrames - 1].Top;
229-
FieldList[i].Bottom = FieldList[OutputFrames - 1].Top;
230-
}
231-
232-
FieldList.resize(VI.num_frames);
233-
}
234-
} else {
235-
VI.fps_denominator = VP->FPSDenominator;
236-
VI.fps_numerator = VP->FPSNumerator;
237-
VI.num_frames = VP->NumFrames;
238-
if (FPSNum > 0 && FPSDen > 0) {
239-
vsh::reduceRational(&FPSNum, &FPSDen);
240-
if (VI.fps_denominator != FPSDen || VI.fps_numerator != FPSNum) {
241-
VI.fps_denominator = FPSDen;
242-
VI.fps_numerator = FPSNum;
243-
if (VP->NumFrames > 1) {
244-
VI.num_frames = static_cast<int>((VP->LastTime - VP->FirstTime) * (1 + 1. / (VP->NumFrames - 1)) * FPSNum / FPSDen + 0.5);
245-
if (VI.num_frames < 1)
246-
VI.num_frames = 1;
247-
} else {
144+
VI.fps_denominator = VP->FPSDenominator;
145+
VI.fps_numerator = VP->FPSNumerator;
146+
VI.num_frames = VP->NumFrames;
147+
if (FPSNum > 0 && FPSDen > 0) {
148+
vsh::reduceRational(&FPSNum, &FPSDen);
149+
if (VI.fps_denominator != FPSDen || VI.fps_numerator != FPSNum) {
150+
VI.fps_denominator = FPSDen;
151+
VI.fps_numerator = FPSNum;
152+
if (VP->NumFrames > 1) {
153+
VI.num_frames = static_cast<int>((VP->LastTime - VP->FirstTime) * (1 + 1. / (VP->NumFrames - 1)) * FPSNum / FPSDen + 0.5);
154+
if (VI.num_frames < 1)
248155
VI.num_frames = 1;
249-
}
250156
} else {
251-
FPSNum = 0;
252-
FPSDen = 0;
157+
VI.num_frames = 1;
253158
}
159+
} else {
160+
FPSNum = 0;
161+
FPSDen = 0;
254162
}
255163
}
256164

@@ -461,12 +369,6 @@ void AvisynthVideoSource::InitOutputFormat(
461369
else
462370
Env->ThrowError("FFVideoSource: No suitable output format found");
463371

464-
if (RFFMode > 0 && ResizeToHeight != F->EncodedHeight)
465-
Env->ThrowError("FFVideoSource: Vertical scaling not allowed in RFF mode");
466-
467-
if (RFFMode > 0 && TargetPixelFormat != AV_PIX_FMT_NV21)
468-
Env->ThrowError("FFVideoSource: Only the default output colorspace can be used in RFF mode");
469-
470372
// set color information variables
471373
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFCOLOR_SPACE"), F->ColorSpace);
472374
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFCOLOR_RANGE"), F->ColorRange);
@@ -481,7 +383,7 @@ void AvisynthVideoSource::InitOutputFormat(
481383

482384
// Crop to obey subsampling width/height requirements
483385
VI.width -= VI.width % (1 << GetSubSamplingW(VI));
484-
VI.height -= VI.height % (1 << (GetSubSamplingH(VI) + (RFFMode > 0 ? 1 : 0)));
386+
VI.height -= VI.height % (1 << (GetSubSamplingH(VI)));
485387
}
486388

487389
static void BlitPlane(const FFMS_Frame *Frame, PVideoFrame &Dst, IScriptEnvironment *Env, int Plane, int PlaneId) {
@@ -547,67 +449,45 @@ PVideoFrame AvisynthVideoSource::GetFrame(int n, IScriptEnvironment *Env) {
547449
AVSMap *props = has_at_least_v8 ? Env->getFramePropsRW(Dst) : nullptr;
548450

549451
ErrorInfo E;
550-
const FFMS_Frame *Frame;
551-
if (RFFMode > 0) {
552-
Frame = FFMS_GetFrame(V, std::min(FieldList[n].Top, FieldList[n].Bottom), &E);
553-
if (Frame == nullptr)
554-
Env->ThrowError("FFVideoSource: %s", E.Buffer);
555-
if (FieldList[n].Top == FieldList[n].Bottom) {
556-
OutputFrame(Frame, Dst, Env);
557-
} else {
558-
int FirstField = std::min(FieldList[n].Top, FieldList[n].Bottom) == (FFMS_GetVideoProperties(V)->TopFieldFirst ? FieldList[n].Top : FieldList[n].Bottom);
559-
OutputField(Frame, Dst, FirstField, Env);
560-
Frame = FFMS_GetFrame(V, std::max(FieldList[n].Top, FieldList[n].Bottom), &E);
561-
if (Frame == nullptr)
562-
Env->ThrowError("FFVideoSource: %s", E.Buffer);
563-
OutputField(Frame, Dst, !FirstField, Env);
564-
}
452+
const FFMS_Frame *Frame = nullptr;
453+
454+
if (FPSNum > 0 && FPSDen > 0) {
455+
double currentTime = FFMS_GetVideoProperties(V)->FirstTime +
456+
(double)(n * (int64_t)FPSDen) / FPSNum;
457+
Frame = FFMS_GetFrameByTime(V, currentTime, &E);
565458
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFVFR_TIME"), -1);
566-
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFPICT_TYPE"), static_cast<int>('U'));
567459
if (has_at_least_v8) {
568-
Env->propSetInt(props, "_DurationNum", FPSNum, 0);
569-
Env->propSetInt(props, "_DurationDen", FPSDen, 0);
570-
// don't set absolute time since it's ill-defined
460+
Env->propSetInt(props, "_DurationNum", FPSDen, 0);
461+
Env->propSetInt(props, "_DurationDen", FPSNum, 0);
462+
Env->propSetFloat(props, "_AbsoluteTime", currentTime, 0);
571463
}
572464
} else {
573-
if (FPSNum > 0 && FPSDen > 0) {
574-
double currentTime = FFMS_GetVideoProperties(V)->FirstTime +
575-
(double)(n * (int64_t)FPSDen) / FPSNum;
576-
Frame = FFMS_GetFrameByTime(V, currentTime, &E);
577-
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFVFR_TIME"), -1);
578-
if (has_at_least_v8) {
579-
Env->propSetInt(props, "_DurationNum", FPSDen, 0);
580-
Env->propSetInt(props, "_DurationDen", FPSNum, 0);
581-
Env->propSetFloat(props, "_AbsoluteTime", currentTime, 0);
582-
}
583-
} else {
584-
Frame = FFMS_GetFrame(V, n, &E);
585-
FFMS_Track *T = FFMS_GetTrackFromVideo(V);
586-
const FFMS_TrackTimeBase *TB = FFMS_GetTimeBase(T);
587-
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFVFR_TIME"), static_cast<int>(FFMS_GetFrameInfo(T, n)->PTS * static_cast<double>(TB->Num) / TB->Den));
588-
if (has_at_least_v8) {
589-
int64_t num;
590-
if (n + 1 < VI.num_frames)
591-
num = FFMS_GetFrameInfo(T, n + 1)->PTS - FFMS_GetFrameInfo(T, n)->PTS;
592-
else if (n > 0) // simply use the second to last frame's duration for the last one, should be good enough
593-
num = FFMS_GetFrameInfo(T, n)->PTS - FFMS_GetFrameInfo(T, n - 1)->PTS;
594-
else // just make it one timebase if it's a single frame clip
595-
num = 1;
596-
int64_t DurNum = TB->Num * num;
597-
int64_t DurDen = TB->Den * 1000;
598-
vsh::reduceRational(&DurNum, &DurDen);
599-
Env->propSetInt(props, "_DurationNum", DurNum, 0);
600-
Env->propSetInt(props, "_DurationDen", DurDen, 0);
601-
Env->propSetFloat(props, "_AbsoluteTime", ((static_cast<double>(TB->Num) / 1000) * FFMS_GetFrameInfo(T, n)->PTS) / TB->Den, 0);
602-
}
465+
Frame = FFMS_GetFrame(V, n, &E);
466+
FFMS_Track *T = FFMS_GetTrackFromVideo(V);
467+
const FFMS_TrackTimeBase *TB = FFMS_GetTimeBase(T);
468+
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFVFR_TIME"), static_cast<int>(FFMS_GetFrameInfo(T, n)->PTS * static_cast<double>(TB->Num) / TB->Den));
469+
if (has_at_least_v8) {
470+
int64_t num;
471+
if (n + 1 < VI.num_frames)
472+
num = FFMS_GetFrameInfo(T, n + 1)->PTS - FFMS_GetFrameInfo(T, n)->PTS;
473+
else if (n > 0) // simply use the second to last frame's duration for the last one, should be good enough
474+
num = FFMS_GetFrameInfo(T, n)->PTS - FFMS_GetFrameInfo(T, n - 1)->PTS;
475+
else // just make it one timebase if it's a single frame clip
476+
num = 1;
477+
int64_t DurNum = TB->Num * num;
478+
int64_t DurDen = TB->Den * 1000;
479+
vsh::reduceRational(&DurNum, &DurDen);
480+
Env->propSetInt(props, "_DurationNum", DurNum, 0);
481+
Env->propSetInt(props, "_DurationDen", DurDen, 0);
482+
Env->propSetFloat(props, "_AbsoluteTime", ((static_cast<double>(TB->Num) / 1000) * FFMS_GetFrameInfo(T, n)->PTS) / TB->Den, 0);
603483
}
484+
}
604485

605-
if (Frame == nullptr)
606-
Env->ThrowError("FFVideoSource: %s", E.Buffer);
486+
if (Frame == nullptr)
487+
Env->ThrowError("FFVideoSource: %s", E.Buffer);
607488

608-
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFPICT_TYPE"), static_cast<int>(Frame->PictType));
609-
OutputFrame(Frame, Dst, Env);
610-
}
489+
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFPICT_TYPE"), static_cast<int>(Frame->PictType));
490+
OutputFrame(Frame, Dst, Env);
611491

612492
if (has_at_least_v8) {
613493
const FFMS_VideoProperties *VP = FFMS_GetVideoProperties(V);
@@ -626,8 +506,7 @@ PVideoFrame AvisynthVideoSource::GetFrame(int n, IScriptEnvironment *Env) {
626506
Env->propSetInt(props, "_ColorRange", 1, 0);
627507
else if (Frame->ColorRange == FFMS_CR_JPEG)
628508
Env->propSetInt(props, "_ColorRange", 0, 0);
629-
if (RFFMode == 0)
630-
Env->propSetData(props, "_PictType", &Frame->PictType, 1, 0);
509+
Env->propSetData(props, "_PictType", &Frame->PictType, 1, 0);
631510

632511
// Set field information
633512
int FieldBased = 0;

src/avisynth/avssources.h

+1-8
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,11 @@ struct ErrorInfo : FFMS_ErrorInfo {
3737
};
3838

3939
class AvisynthVideoSource : public IClip {
40-
struct FrameFields {
41-
int Top;
42-
int Bottom;
43-
};
44-
4540
VideoInfo VI;
4641
bool HighBitDepth;
4742
FFMS_VideoSource *V;
4843
int64_t FPSNum;
4944
int64_t FPSDen;
50-
int RFFMode;
51-
std::vector<FrameFields> FieldList;
5245
const char *VarPrefix;
5346
bool has_at_least_v8;
5447

@@ -58,7 +51,7 @@ class AvisynthVideoSource : public IClip {
5851
void OutputField(const FFMS_Frame *Frame, PVideoFrame &Dst, int Field, IScriptEnvironment *Env);
5952
public:
6053
AvisynthVideoSource(const char *SourceFile, int Track, FFMS_Index *Index,
61-
int FPSNum, int FPSDen, int Threads, int SeekMode, int RFFMode,
54+
int FPSNum, int FPSDen, int Threads, int SeekMode,
6255
int ResizeToWidth, int ResizeToHeight, const char *ResizerName,
6356
const char *ConvertToFormatName, const char *VarPrefix, IScriptEnvironment* Env);
6457
~AvisynthVideoSource();

0 commit comments

Comments
 (0)