/// @brief Constructor /// @param filename The filename to open YUV4MPEGVideoProvider::YUV4MPEGVideoProvider(agi::fs::path const& filename, std::string const&) { fps_rat.num = -1; fps_rat.den = 1; try { #ifdef WIN32 sf = _wfopen(filename.c_str(), L"rb"); #else sf = fopen(filename.c_str(), "rb"); #endif if (!sf) throw agi::fs::FileNotFound(filename); CheckFileFormat(); ParseFileHeader(ReadHeader(0)); if (w <= 0 || h <= 0) throw VideoOpenError("Invalid resolution"); if (fps_rat.num <= 0 || fps_rat.den <= 0) { fps_rat.num = 25; fps_rat.den = 1; LOG_D("provider/video/yuv4mpeg") << "framerate info unavailable, assuming 25fps"; } if (pixfmt == Y4M_PIXFMT_NONE) pixfmt = Y4M_PIXFMT_420JPEG; if (imode == Y4M_ILACE_NOTSET) imode = Y4M_ILACE_UNKNOWN; luma_sz = w * h; switch (pixfmt) { case Y4M_PIXFMT_420JPEG: case Y4M_PIXFMT_420MPEG2: case Y4M_PIXFMT_420PALDV: chroma_sz = (w * h) >> 2; break; case Y4M_PIXFMT_422: chroma_sz = (w * h) >> 1; break; /// @todo add support for more pixel formats default: throw VideoOpenError("Unsupported pixel format"); } frame_sz = luma_sz + chroma_sz*2; num_frames = IndexFile(); if (num_frames <= 0 || seek_table.empty()) throw VideoOpenError("Unable to determine file length"); fseeko(sf, 0, SEEK_SET); } catch (...) { if (sf) fclose(sf); throw; } }
AvisynthVideoProvider::AvisynthVideoProvider(agi::fs::path const& filename, std::string const& colormatrix) { agi::acs::CheckFileRead(filename); std::lock_guard<std::mutex> lock(avs.GetMutex()); #ifdef _WIN32 if (agi::fs::HasExtension(filename, "avi")) { // Try to read the keyframes before actually opening the file as trying // to open the file while it's already open can cause problems with // badly written VFW decoders AVIFileInit(); PAVIFILE pfile; long hr = AVIFileOpen(&pfile, filename.c_str(), OF_SHARE_DENY_WRITE, 0); if (hr) { warning = "Unable to open AVI file for reading keyframes:\n"; switch (hr) { case AVIERR_BADFORMAT: warning += "The file is corrupted, incomplete or has an otherwise bad format."; break; case AVIERR_MEMORY: warning += "The file could not be opened because of insufficient memory."; break; case AVIERR_FILEREAD: warning += "An error occurred reading the file. There might be a problem with the storage media."; break; case AVIERR_FILEOPEN: warning += "The file could not be opened. It might be in use by another application, or you do not have permission to access it."; break; case REGDB_E_CLASSNOTREG: warning += "There is no handler installed for the file extension. This might indicate a fundamental problem in your Video for Windows installation, and can be caused by extremely stripped Windows installations."; break; default: warning += "Unknown error."; break; } goto file_exit; } PAVISTREAM ppavi; if (hr = AVIFileGetStream(pfile, &ppavi, streamtypeVIDEO, 0)) { warning = "Unable to open AVI video stream for reading keyframes:\n"; switch (hr) { case AVIERR_NODATA: warning += "The file does not contain a usable video stream."; break; case AVIERR_MEMORY: warning += "Not enough memory."; break; default: warning += "Unknown error."; break; } goto file_release; } AVISTREAMINFO avis; if (FAILED(AVIStreamInfo(ppavi,&avis,sizeof(avis)))) { warning = "Unable to read keyframes from AVI file:\nCould not get stream information."; goto stream_release; } for (size_t i = 0; i < avis.dwLength; i++) { if (AVIStreamIsKeyFrame(ppavi, i)) keyframes.push_back(i); } // If every frame is a keyframe then just discard the keyframe data as it's useless if (keyframes.size() == (size_t)avis.dwLength) keyframes.clear(); // Clean up stream_release: AVIStreamRelease(ppavi); file_release: AVIFileRelease(pfile); file_exit: AVIFileExit(); } #endif try { auto script = Open(filename); // Check if video was loaded properly if (!script.IsClip() || !script.AsClip()->GetVideoInfo().HasVideo()) throw VideoNotSupported("No usable video found"); vi = script.AsClip()->GetVideoInfo(); if (!vi.IsRGB()) { /// @todo maybe read ColorMatrix hints for d2v files? AVSValue args[2] = { script, "Rec601" }; bool force_bt601 = OPT_GET("Video/Force BT.601")->GetBool() || colormatrix == "TV.601"; bool bt709 = vi.width > 1024 || vi.height >= 600; if (bt709 && (!force_bt601 || colormatrix == "TV.709")) { args[1] = "Rec709"; colorspace = "TV.709"; } else colorspace = "TV.601"; const char *argnames[2] = { 0, "matrix" }; script = avs.GetEnv()->Invoke("ConvertToRGB32", AVSValue(args, 2), argnames); } else colorspace = "None"; RGB32Video = avs.GetEnv()->Invoke("Cache", script).AsClip(); vi = RGB32Video->GetVideoInfo(); fps = (double)vi.fps_numerator / vi.fps_denominator; } catch (AvisynthError const& err) { throw VideoOpenError("Avisynth error: " + std::string(err.msg)); } }