예제 #1
0
VSVideoSource::VSVideoSource(const char *SourceFile, int Track, FFMS_Index *Index,
		int AFPSNum, int AFPSDen, int Threads, int SeekMode, int /*RFFMode*/,
		int ResizeToWidth, int ResizeToHeight, const char *ResizerName,
		int Format, bool OutputAlpha, const VSAPI *vsapi, VSCore *core)
		: FPSNum(AFPSNum), FPSDen(AFPSDen), OutputAlpha(OutputAlpha) {

	VI[0] = {};
	VI[1] = {};

	char ErrorMsg[1024];
	FFMS_ErrorInfo E;
	E.Buffer = ErrorMsg;
	E.BufferSize = sizeof(ErrorMsg);

	V = FFMS_CreateVideoSource(SourceFile, Track, Index, Threads, SeekMode, &E);
	if (!V) {
		throw std::runtime_error(std::string("Source: ") + E.Buffer);
	}
	try {
		InitOutputFormat(ResizeToWidth, ResizeToHeight, ResizerName, Format, vsapi, core);
	} catch (std::exception &) {
		FFMS_DestroyVideoSource(V);
		throw;
	}

	const FFMS_VideoProperties *VP = FFMS_GetVideoProperties(V);

	if (FPSNum > 0 && FPSDen > 0) {
		muldivRational(&FPSNum, &FPSDen, 1, 1);
		VI[0].fpsDen = FPSDen;
		VI[0].fpsNum = FPSNum;
		if (VP->NumFrames > 1) {
			VI[0].numFrames = static_cast<int>((VP->LastTime - VP->FirstTime) * (1 + 1. / (VP->NumFrames - 1)) * FPSNum / FPSDen + 0.5);
			if (VI[0].numFrames < 1)
				VI[0].numFrames = 1;
		} else {
			VI[0].numFrames = 1;
		}
	} else {
		VI[0].fpsDen = VP->FPSDenominator;
		VI[0].fpsNum = VP->FPSNumerator;
		VI[0].numFrames = VP->NumFrames;
		muldivRational(&VI[0].fpsNum, &VI[0].fpsDen, 1, 1);
	}

	if (OutputAlpha) {
		VI[1] = VI[0];
		VI[1].format = vsapi->registerFormat(cmGray, VI[0].format->sampleType, VI[0].format->bitsPerSample, VI[0].format->subSamplingW, VI[0].format->subSamplingH, core);
	}

	SARNum = VP->SARNum;
	SARDen = VP->SARDen;
}
예제 #2
0
파일: vszimg.c 프로젝트: theomission/zimg
static void propagate_sar(const VSAPI *vsapi, const VSMap *src_props, VSMap *dst_props, const zimg_image_format *src_format, const zimg_image_format *dst_format)
{
	int64_t sar_num = 0;
	int64_t sar_den = 0;
	int err;

	if ((sar_num = vsapi->propGetInt(src_props, "_SARNum", 0, &err)), err)
		sar_num = 0;
	if ((sar_den = vsapi->propGetInt(src_props, "_SARDen", 0, &err)), err)
		sar_den = 0;

	if (sar_num <= 0 || sar_den <= 0) {
		vsapi->propDeleteKey(dst_props, "_SARNum");
		vsapi->propDeleteKey(dst_props, "_SARDen");
	} else {
		muldivRational(&sar_num, &sar_den, dst_format->width, src_format->width);
		muldivRational(&sar_num, &sar_den, src_format->height, dst_format->height);

		vsapi->propSetInt(dst_props, "_SARNum", sar_num, paReplace);
		vsapi->propSetInt(dst_props, "_SARDen", sar_den, paReplace);
	}
}
예제 #3
0
const VSFrameRef *VS_CC VSVideoSource::GetFrame(int n, int activationReason, void **instanceData, void **, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) {
	VSVideoSource *vs = static_cast<VSVideoSource *>(*instanceData);
	if (activationReason == arInitial) {

		char ErrorMsg[1024];
		FFMS_ErrorInfo E;
		E.Buffer = ErrorMsg;
		E.BufferSize = sizeof(ErrorMsg);
		std::string buf = "Source: ";

		int OutputIndex = vs->OutputAlpha ? vsapi->getOutputIndex(frameCtx) : 0;	

		VSFrameRef *Dst = vsapi->newVideoFrame(vs->VI[OutputIndex].format, vs->VI[OutputIndex].width, vs->VI[OutputIndex].height, nullptr, core);
		VSMap *Props = vsapi->getFramePropsRW(Dst);

		const FFMS_Frame *Frame;

		if (vs->FPSNum > 0 && vs->FPSDen > 0) {
			double currentTime = FFMS_GetVideoProperties(vs->V)->FirstTime +
				(double)(n * (int64_t)vs->FPSDen) / vs->FPSNum;
			Frame = FFMS_GetFrameByTime(vs->V, currentTime, &E);
			vsapi->propSetInt(Props, "_DurationNum", vs->FPSDen, paReplace);
			vsapi->propSetInt(Props, "_DurationDen", vs->FPSNum, paReplace);
			vsapi->propSetFloat(Props, "_AbsoluteTime", currentTime, paReplace);
		} else {
			Frame = FFMS_GetFrame(vs->V, n, &E);
			FFMS_Track *T = FFMS_GetTrackFromVideo(vs->V);
			const FFMS_TrackTimeBase *TB = FFMS_GetTimeBase(T);
			int64_t num;
			if (n + 1 < vs->VI[0].numFrames)
				num = FFMS_GetFrameInfo(T, n + 1)->PTS - FFMS_GetFrameInfo(T, n)->PTS;
			else if (n > 0) // simply use the second to last frame's duration for the last one, should be good enough
				num = FFMS_GetFrameInfo(T, n)->PTS - FFMS_GetFrameInfo(T, n - 1)->PTS;
			else // just make it one timebase if it's a single frame clip
				num = 1;
			int64_t DurNum = TB->Num * num;
			int64_t DurDen = TB->Den * 1000;
			muldivRational(&DurNum, &DurDen, 1, 1);
			vsapi->propSetInt(Props, "_DurationNum", DurNum, paReplace);
			vsapi->propSetInt(Props, "_DurationDen", DurDen, paReplace);
			vsapi->propSetFloat(Props, "_AbsoluteTime", ((static_cast<double>(TB->Num) / 1000) *  FFMS_GetFrameInfo(T, n)->PTS) / TB->Den, paReplace);
		}

		if (Frame == nullptr) {
			buf += E.Buffer;
			vsapi->setFilterError(buf.c_str(), frameCtx);
			return nullptr;
		}

		// Set AR variables
		if (vs->SARNum > 0 && vs->SARDen > 0) {
			vsapi->propSetInt(Props, "_SARNum", vs->SARNum, paReplace);
			vsapi->propSetInt(Props, "_SARDen", vs->SARDen, paReplace);
		}

		vsapi->propSetInt(Props, "_Matrix", Frame->ColorSpace, paReplace);
		vsapi->propSetInt(Props, "_Primaries", Frame->ColorPrimaries, paReplace);
		vsapi->propSetInt(Props, "_Transfer", Frame->TransferCharateristics, paReplace);
		if (Frame->ChromaLocation > 0)
			vsapi->propSetInt(Props, "_ChromaLocation", Frame->ChromaLocation - 1, paReplace);

		if (Frame->ColorRange == FFMS_CR_MPEG)
			vsapi->propSetInt(Props, "_ColorRange", 1, paReplace);
		else if (Frame->ColorRange == FFMS_CR_JPEG)
			vsapi->propSetInt(Props, "_ColorRange", 0, paReplace);
		vsapi->propSetData(Props, "_PictType", &Frame->PictType, 1, paReplace);

		// Set field information
		int FieldBased = 0;
		if (Frame->InterlacedFrame)
			FieldBased = (Frame->TopFieldFirst ? 2 : 1);
		vsapi->propSetInt(Props, "_FieldBased", FieldBased, paReplace);

		if (OutputIndex == 0)
			OutputFrame(Frame, Dst, vsapi);
		else
			OutputAlphaFrame(Frame, vs->VI[0].format->numPlanes, Dst, vsapi);

		return Dst;
	}

	return nullptr;
}