Skip to content

Commit

Permalink
Allow mv-hevc viewid to be passed into the source
Browse files Browse the repository at this point in the history
  • Loading branch information
myrsloik committed Dec 10, 2024
1 parent 543ec1e commit 633d6e8
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 23 deletions.
4 changes: 2 additions & 2 deletions src/audiosource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ void BestAudioSource::InitializeFormatSets() {
double BestAudioSource::GetRelativeStartTime(int Track) const {
if (Track < 0) {
try {
std::unique_ptr<LWVideoDecoder> Dec(new LWVideoDecoder(Source, "", 0, Track, 0, LAVFOptions));
std::unique_ptr<LWVideoDecoder> Dec(new LWVideoDecoder(Source, "", 0, Track, 0, 0, LAVFOptions));
BSVideoProperties VP;
Dec->GetVideoProperties(VP);
return AP.StartTime - VP.StartTime;
Expand All @@ -503,7 +503,7 @@ double BestAudioSource::GetRelativeStartTime(int Track) const {
return 0;
} else {
try {
std::unique_ptr<LWVideoDecoder> Dec(new LWVideoDecoder(Source, "", 0, Track, 0, LAVFOptions));
std::unique_ptr<LWVideoDecoder> Dec(new LWVideoDecoder(Source, "", 0, Track, 0, 0, LAVFOptions));
BSVideoProperties VP;
Dec->GetVideoProperties(VP);
return AP.StartTime - VP.StartTime;
Expand Down
11 changes: 6 additions & 5 deletions src/avisynth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class AvisynthVideoSource : public IClip {
int64_t FPSDen;
bool RFF;
public:
AvisynthVideoSource(const char *Source, int Track,
AvisynthVideoSource(const char *Source, int Track, int ViewID,
int AFPSNum, int AFPSDen, bool RFF, int Threads, int SeekPreRoll, bool EnableDrefs, bool UseAbsolutePath,
int CacheMode, const char *CachePath, int CacheSize, const char *HWDevice, int ExtraHWFrames,
const char *Timecodes, int StartNumber, int VariableFormat, IScriptEnvironment *Env)
Expand All @@ -95,7 +95,7 @@ class AvisynthVideoSource : public IClip {
if (StartNumber >= 0)
Opts["start_number"] = std::to_string(StartNumber);

V.reset(new BestVideoSource(CreateProbablyUTF8Path(Source), HWDevice ? HWDevice : "", ExtraHWFrames, Track, Threads, CacheMode, CachePath, &Opts));
V.reset(new BestVideoSource(CreateProbablyUTF8Path(Source), HWDevice ? HWDevice : "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath, &Opts));

V->SelectFormatSet(VariableFormat);

Expand Down Expand Up @@ -286,8 +286,9 @@ static AVSValue __cdecl CreateBSVideoSource(AVSValue Args, void *UserData, IScri
const char *Timecodes = Args[14].AsString(nullptr);
int StartNumber = Args[15].AsInt(-1);
int VariableFormat = Args[16].AsInt(0);
int ViewID = Args[17].AsInt(0);

return new AvisynthVideoSource(Source, Track, FPSNum, FPSDen, RFF, Threads, SeekPreroll, EnableDrefs, UseAbsolutePath, CacheMode, CachePath, CacheSize, HWDevice, ExtraHWFrames, Timecodes, StartNumber, VariableFormat, Env);
return new AvisynthVideoSource(Source, Track, ViewID, FPSNum, FPSDen, RFF, Threads, SeekPreroll, EnableDrefs, UseAbsolutePath, CacheMode, CachePath, CacheSize, HWDevice, ExtraHWFrames, Timecodes, StartNumber, VariableFormat, Env);
}

class AvisynthAudioSource : public IClip {
Expand Down Expand Up @@ -430,9 +431,9 @@ static constexpr auto PopulateArgNames() {
return Result;
}

static constexpr char BSVideoSourceAvsArgs[] = "[source]s[track]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachemode]i[cachepath]s[cachesize]i[hwdevice]s[extrahwframes]i[timecodes]s[start_number]i[variableformat]i";
static constexpr char BSVideoSourceAvsArgs[] = "[source]s[track]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachemode]i[cachepath]s[cachesize]i[hwdevice]s[extrahwframes]i[timecodes]s[start_number]i[variableformat]i[viewid]i";
static constexpr char BSAudioSourceAvsArgs[] = "[source]s[track]i[adjustdelay]i[threads]i[enable_drefs]b[use_absolute_path]b[drc_scale]f[cachemode]i[cachepath]s[cachesize]i";
static constexpr char BSSourceAvsArgs[] = "[source]s[atrack]i[vtrack]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachemode]i[cachepath]s[acachesize]i[vcachesize]i[hwdevice]s[extrahwframes]i[timecodes]s[start_number]i[variableformat]i[adjustdelay]i[drc_scale]f";
static constexpr char BSSourceAvsArgs[] = "[source]s[atrack]i[vtrack]i[fpsnum]i[fpsden]i[rff]b[threads]i[seekpreroll]i[enable_drefs]b[use_absolute_path]b[cachemode]i[cachepath]s[acachesize]i[vcachesize]i[hwdevice]s[extrahwframes]i[timecodes]s[start_number]i[variableformat]i[adjustdelay]i[drc_scale]f[viewid]i";

static constexpr std::array BSVArgNames = PopulateArgNames<BSVideoSourceAvsArgs>();
static constexpr std::array BSAArgNames = PopulateArgNames<BSAudioSourceAvsArgs>();
Expand Down
7 changes: 4 additions & 3 deletions src/vapoursynth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ static void VS_CC CreateBestVideoSource(const VSMap *In, VSMap *Out, void *, VSC
int Track = vsapi->mapGetIntSaturated(In, "track", 0, &err);
if (err)
Track = -1;
int ViewID = vsapi->mapGetIntSaturated(In, "viewid", 0, &err);
int VariableFormat = vsapi->mapGetIntSaturated(In, "variableformat", 0, &err);
if (err)
VariableFormat = -1;
Expand Down Expand Up @@ -182,7 +183,7 @@ static void VS_CC CreateBestVideoSource(const VSMap *In, VSMap *Out, void *, VSC
if (ShowProgress) {
auto NextUpdate = std::chrono::high_resolution_clock::now();
int LastValue = -1;
D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, Threads, CacheMode, CachePath ? CachePath : "", &Opts,
D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath ? CachePath : "", &Opts,
[vsapi, Core, &NextUpdate, &LastValue](int Track, int64_t Cur, int64_t Total) {
if (NextUpdate < std::chrono::high_resolution_clock::now()) {
if (Total == INT64_MAX && Cur == Total) {
Expand All @@ -200,7 +201,7 @@ static void VS_CC CreateBestVideoSource(const VSMap *In, VSMap *Out, void *, VSC
}));

} else {
D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, Threads, CacheMode, CachePath ? CachePath : "", &Opts));
D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath ? CachePath : "", &Opts));
}

D->V->SelectFormatSet(VariableFormat);
Expand Down Expand Up @@ -437,7 +438,7 @@ static void VS_CC SetLogLevel(const VSMap *In, VSMap *Out, void *, VSCore *, con

VS_EXTERNAL_API(void) VapourSynthPluginInit2(VSPlugin *plugin, const VSPLUGINAPI *vspapi) {
vspapi->configPlugin("com.vapoursynth.bestsource", "bs", "Best Source 2", VS_MAKE_VERSION(BEST_SOURCE_VERSION_MAJOR, BEST_SOURCE_VERSION_MINOR), VS_MAKE_VERSION(VAPOURSYNTH_API_MAJOR, 0), 0, plugin);
vspapi->registerFunction("VideoSource", "source:data;track:int:opt;variableformat:int:opt;fpsnum:int:opt;fpsden:int:opt;rff:int:opt;threads:int:opt;seekpreroll:int:opt;enable_drefs:int:opt;use_absolute_path:int:opt;cachemode:int:opt;cachepath:data:opt;cachesize:int:opt;hwdevice:data:opt;extrahwframes:int:opt;timecodes:data:opt;start_number:int:opt;showprogress:int:opt;", "clip:vnode;", CreateBestVideoSource, nullptr, plugin);
vspapi->registerFunction("VideoSource", "source:data;track:int:opt;variableformat:int:opt;fpsnum:int:opt;fpsden:int:opt;rff:int:opt;viewid:int:opt;threads:int:opt;seekpreroll:int:opt;enable_drefs:int:opt;use_absolute_path:int:opt;cachemode:int:opt;cachepath:data:opt;cachesize:int:opt;hwdevice:data:opt;extrahwframes:int:opt;timecodes:data:opt;start_number:int:opt;showprogress:int:opt;", "clip:vnode;", CreateBestVideoSource, nullptr, plugin);
vspapi->registerFunction("AudioSource", "source:data;track:int:opt;adjustdelay:int:opt;threads:int:opt;enable_drefs:int:opt;use_absolute_path:int:opt;drc_scale:float:opt;cachemode:int:opt;cachepath:data:opt;cachesize:int:opt;showprogress:int:opt;", "clip:anode;", CreateBestAudioSource, nullptr, plugin);
vspapi->registerFunction("TrackInfo", "source:data;enable_drefs:int:opt;use_absolute_path:int:opt;", "mediatype:int;mediatypestr:data;codec:int;codecstr:data;disposition:int;dispositionstr:data;", GetTrackInfo, nullptr, plugin);
vspapi->registerFunction("Metadata", "source:data;track:int:opt;enable_drefs:int:opt;use_absolute_path:int:opt;", "any", GetMetadata, nullptr, plugin);
Expand Down
29 changes: 19 additions & 10 deletions src/videosource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ bool LWVideoDecoder::DecodeNextFrame(bool SkipOutput) {
return false;
}

void LWVideoDecoder::OpenFile(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int Threads, const std::map<std::string, std::string> &LAVFOpts) {
void LWVideoDecoder::OpenFile(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int ViewID, int Threads, const std::map<std::string, std::string> &LAVFOpts) {
TrackNumber = Track;

AVHWDeviceType Type = AV_HWDEVICE_TYPE_NONE;
Expand Down Expand Up @@ -232,14 +232,20 @@ void LWVideoDecoder::OpenFile(const std::filesystem::path &SourceFile, const std
throw BestSourceException("Couldn't allocate frame");
}

if (avcodec_open2(CodecContext, Codec, nullptr) < 0)
AVDictionary *CodecDict = nullptr;
if (ViewID >= 0)
av_dict_set(&CodecDict, "view_ids", std::to_string(ViewID).c_str(), 0);

if (avcodec_open2(CodecContext, Codec, &CodecDict) < 0)
throw BestSourceException("Could not open video codec");

av_dict_free(&CodecDict);
}

LWVideoDecoder::LWVideoDecoder(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int Threads, const std::map<std::string, std::string> &LAVFOpts) {
LWVideoDecoder::LWVideoDecoder(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int ViewID, int Threads, const std::map<std::string, std::string> &LAVFOpts) {
try {
Packet = av_packet_alloc();
OpenFile(SourceFile, HWDeviceName, ExtraHWFrames, Track, Threads, LAVFOpts);
OpenFile(SourceFile, HWDeviceName, ExtraHWFrames, Track, ViewID, Threads, LAVFOpts);
} catch (...) {
Free();
throw;
Expand Down Expand Up @@ -868,8 +874,8 @@ bool BestVideoSource::NearestCommonFrameRate(BSRational &FPS) {
return false;
}

BestVideoSource::BestVideoSource(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int Threads, int CacheMode, const std::filesystem::path &CachePath, const std::map<std::string, std::string> *LAVFOpts, const ProgressFunction &Progress)
: Source(SourceFile), HWDevice(HWDeviceName), ExtraHWFrames(!HWDeviceName.empty() ? ExtraHWFrames : 0), VideoTrack(Track), Threads(Threads) {
BestVideoSource::BestVideoSource(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int ViewID, int Threads, int CacheMode, const std::filesystem::path &CachePath, const std::map<std::string, std::string> *LAVFOpts, const ProgressFunction &Progress)
: Source(SourceFile), HWDevice(HWDeviceName), ExtraHWFrames(!HWDeviceName.empty() ? ExtraHWFrames : 0), VideoTrack(Track), ViewID(ViewID), Threads(Threads) {
// Only make file path absolute if it exists to pass through special protocol paths
std::error_code ec;
if (std::filesystem::exists(SourceFile, ec))
Expand All @@ -884,7 +890,7 @@ BestVideoSource::BestVideoSource(const std::filesystem::path &SourceFile, const
if (CacheMode < 0 || CacheMode > 4)
throw BestSourceException("CacheMode must be between 0 and 4");

std::unique_ptr<LWVideoDecoder> Decoder(new LWVideoDecoder(Source, HWDevice, ExtraHWFrames, VideoTrack, Threads, LAVFOptions));
std::unique_ptr<LWVideoDecoder> Decoder(new LWVideoDecoder(Source, HWDevice, ExtraHWFrames, VideoTrack, ViewID, Threads, LAVFOptions));

Decoder->GetVideoProperties(VP);
VideoTrack = Decoder->GetTrack();
Expand Down Expand Up @@ -986,7 +992,7 @@ void BestVideoSource::SetSeekPreRoll(int64_t Frames) {
}

bool BestVideoSource::IndexTrack(const ProgressFunction &Progress) {
std::unique_ptr<LWVideoDecoder> Decoder(new LWVideoDecoder(Source, HWDevice, ExtraHWFrames, VideoTrack, Threads, LAVFOptions));
std::unique_ptr<LWVideoDecoder> Decoder(new LWVideoDecoder(Source, HWDevice, ExtraHWFrames, VideoTrack, ViewID, Threads, LAVFOptions));

int64_t FileSize = Progress ? Decoder->GetSourceSize() : -1;

Expand Down Expand Up @@ -1274,7 +1280,7 @@ BestVideoFrame *BestVideoSource::GetFrameInternal(int64_t N) {

int Index = (EmptySlot >= 0) ? EmptySlot : LeastRecentlyUsed;
if (!Decoders[Index])
Decoders[Index].reset(new LWVideoDecoder(Source, HWDevice, ExtraHWFrames, VideoTrack, Threads, LAVFOptions));
Decoders[Index].reset(new LWVideoDecoder(Source, HWDevice, ExtraHWFrames, VideoTrack, ViewID, Threads, LAVFOptions));

DecoderLastUse[Index] = DecoderSequenceNum++;

Expand All @@ -1299,7 +1305,7 @@ BestVideoFrame *BestVideoSource::GetFrameLinearInternal(int64_t N, int64_t SeekF
// If an empty slot exists simply spawn a new decoder there or reuse the least recently used decoder slot if no free ones exist
if (Index < 0) {
Index = (EmptySlot >= 0) ? EmptySlot : LeastRecentlyUsed;
Decoders[Index].reset(new LWVideoDecoder(Source, HWDevice, ExtraHWFrames, VideoTrack, Threads, LAVFOptions));
Decoders[Index].reset(new LWVideoDecoder(Source, HWDevice, ExtraHWFrames, VideoTrack, ViewID, Threads, LAVFOptions));
}

std::unique_ptr<LWVideoDecoder> &Decoder = Decoders[Index];
Expand Down Expand Up @@ -1541,6 +1547,7 @@ bool BestVideoSource::WriteVideoTrackIndex(bool AbsolutePath, const std::filesys
WriteBSHeader(F, true);
WriteInt64(F, FileSize);
WriteInt(F, VideoTrack);
WriteInt(F, ViewID);
WriteString(F, HWDevice);
WriteInt(F, ExtraHWFrames);

Expand Down Expand Up @@ -1623,6 +1630,8 @@ bool BestVideoSource::ReadVideoTrackIndex(bool AbsolutePath, const std::filesyst
return false;
if (!ReadCompareInt(F, VideoTrack))
return false;
if (!ReadCompareInt(F, ViewID))
return false;
if (!ReadCompareString(F, HWDevice))
return false;
if (!ReadCompareInt(F, ExtraHWFrames))
Expand Down
7 changes: 4 additions & 3 deletions src/videosource.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ class LWVideoDecoder {
AVPacket *Packet = nullptr;
bool Seeked = false;

void OpenFile(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int Threads, const std::map<std::string, std::string> &LAVFOpts);
void OpenFile(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int ViewID, int Threads, const std::map<std::string, std::string> &LAVFOpts);
bool ReadPacket();
bool DecodeNextFrame(bool SkipOutput = false);
void Free();
public:
LWVideoDecoder(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int Threads, const std::map<std::string, std::string> &LAVFOpts); // Positive track numbers are absolute. Negative track numbers mean nth audio track to simplify things.
LWVideoDecoder(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int ViewID, int Threads, const std::map<std::string, std::string> &LAVFOpts); // Positive track numbers are absolute. Negative track numbers mean nth audio track to simplify things.
~LWVideoDecoder();
[[nodiscard]] int64_t GetSourceSize() const;
[[nodiscard]] int64_t GetSourcePostion() const;
Expand Down Expand Up @@ -273,6 +273,7 @@ class BestVideoSource {
int ExtraHWFrames;
int VideoTrack;
int VariableFormat = -1;
int ViewID;
int Threads;
bool LinearMode = false;
uint64_t DecoderSequenceNum = 0;
Expand All @@ -292,7 +293,7 @@ class BestVideoSource {
bool NearestCommonFrameRate(BSRational &FPS);
void InitializeFormatSets();
public:
BestVideoSource(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int Threads, int CacheMode, const std::filesystem::path &CachePath, const std::map<std::string, std::string> *LAVFOpts, const ProgressFunction &Progress = nullptr);
BestVideoSource(const std::filesystem::path &SourceFile, const std::string &HWDeviceName, int ExtraHWFrames, int Track, int ViewID, int Threads, int CacheMode, const std::filesystem::path &CachePath, const std::map<std::string, std::string> *LAVFOpts, const ProgressFunction &Progress = nullptr);
[[nodiscard]] int GetTrack() const; // Useful when opening nth video track to get the actual number
void SetMaxCacheSize(size_t Bytes); /* Default max size is 1GB */
void SetSeekPreRoll(int64_t Frames); /* The number of frames to cache before the position being fast forwarded to */
Expand Down

0 comments on commit 633d6e8

Please sign in to comment.