| 438 | } |
| 439 | |
| 440 | PVideoFrame AvisynthVideoSource::GetFrame(int n, IScriptEnvironment *Env) { |
| 441 | n = std::min(std::max(n, 0), VI.num_frames - 1); |
| 442 | |
| 443 | PVideoFrame Dst = Env->NewVideoFrame(VI); |
| 444 | AVSMap *props = has_at_least_v8 ? Env->getFramePropsRW(Dst) : nullptr; |
| 445 | |
| 446 | ErrorInfo E; |
| 447 | const FFMS_Frame *Frame = nullptr; |
| 448 | |
| 449 | if (FPSNum > 0 && FPSDen > 0) { |
| 450 | double currentTime = FFMS_GetVideoProperties(V)->FirstTime + |
| 451 | (double)(n * (int64_t)FPSDen) / FPSNum; |
| 452 | Frame = FFMS_GetFrameByTime(V, currentTime, &E); |
| 453 | Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFVFR_TIME"), -1); |
| 454 | if (has_at_least_v8) { |
| 455 | Env->propSetInt(props, "_DurationNum", FPSDen, 0); |
| 456 | Env->propSetInt(props, "_DurationDen", FPSNum, 0); |
| 457 | Env->propSetFloat(props, "_AbsoluteTime", currentTime, 0); |
| 458 | } |
| 459 | } else { |
| 460 | Frame = FFMS_GetFrame(V, n, &E); |
| 461 | FFMS_Track *T = FFMS_GetTrackFromVideo(V); |
| 462 | const FFMS_TrackTimeBase *TB = FFMS_GetTimeBase(T); |
| 463 | 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)); |
| 464 | if (has_at_least_v8) { |
| 465 | int64_t num; |
| 466 | if (n + 1 < VI.num_frames) |
| 467 | num = FFMS_GetFrameInfo(T, n + 1)->PTS - FFMS_GetFrameInfo(T, n)->PTS; |
| 468 | else if (n > 0) // simply use the second to last frame's duration for the last one, should be good enough |
| 469 | num = FFMS_GetFrameInfo(T, n)->PTS - FFMS_GetFrameInfo(T, n - 1)->PTS; |
| 470 | else // just make it one timebase if it's a single frame clip |
| 471 | num = 1; |
| 472 | int64_t DurNum = TB->Num * num; |
| 473 | int64_t DurDen = TB->Den * 1000; |
| 474 | vsh::reduceRational(&DurNum, &DurDen); |
| 475 | Env->propSetInt(props, "_DurationNum", DurNum, 0); |
| 476 | Env->propSetInt(props, "_DurationDen", DurDen, 0); |
| 477 | Env->propSetFloat(props, "_AbsoluteTime", ((static_cast<double>(TB->Num) / 1000) * FFMS_GetFrameInfo(T, n)->PTS) / TB->Den, 0); |
| 478 | } |
| 479 | } |
| 480 | |
| 481 | if (Frame == nullptr) |
| 482 | Env->ThrowError("FFVideoSource: %s", E.Buffer); |
| 483 | |
| 484 | Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFPICT_TYPE"), static_cast<int>(Frame->PictType)); |
| 485 | OutputFrame(Frame, Dst, Env); |
| 486 | |
| 487 | if (has_at_least_v8) { |
| 488 | const FFMS_VideoProperties *VP = FFMS_GetVideoProperties(V); |
| 489 | if (VP->SARNum > 0 && VP->SARDen > 0) { |
| 490 | Env->propSetInt(props, "_SARNum", VP->SARNum, 0); |
| 491 | Env->propSetInt(props, "_SARDen", VP->SARDen, 0); |
| 492 | } |
| 493 | |
| 494 | Env->propSetInt(props, "_Matrix", Frame->ColorSpace, 0); |
| 495 | Env->propSetInt(props, "_Primaries", Frame->ColorPrimaries, 0); |
| 496 | Env->propSetInt(props, "_Transfer", Frame->TransferCharateristics, 0); |
| 497 | if (Frame->ChromaLocation > 0) |
nothing calls this directly
no test coverage detected