printf ("YouTube Profile\n");

Elgato_ParamsFromTurbo 	= Elgato_ParamsFromTurbo or 0;

if (Elgato_ParamsFromTurbo == 0)
then
	printf ("using default parameters\n");
	
	Elgato_InFile = INFILE or "test.mpg";
	Elgato_OutFile = OUTFILE or "test.h4v";
	Elgato_InFileType = "dump";
	Elgato_OutFileType = OUTFORMAT or "h4v";
	
	Elgato_InWidth = InWidth or 320;
	Elgato_InHeight = InHeight or 240;
	Elgato_OutWidth = OutWidth or Elgato_InWidth;
	Elgato_OutHeight = OutHeight or Elgato_InHeight;
	Elgato_VBitrate = VBitrate or 1000000;
	Elgato_AvcProfile = AvcProfile or "baseline";
	Elgato_LevelValue = 22;
	Elgato_GopStructure = Q_AVCENC_CFP_GOP_STRUCTURE_IP;
	Elgato_ClosedGop = 1;
	Elgato_InterlaceMode = "frame";
	Elgato_FeedAsTS = 0;
	Elgato_VideoPID = 17;
	Elgato_VPP_INTERLACED = 0;
	Elgato_VPP_PME_HS = 2;
	Elgato_VPP_PME_VS = 4;
	Elgato_DstFrameDuration = TicksPerFrm or 3003;
	Elgato_PixWidth = 1;
	Elgato_PixHeight = 1;
	Elgato_GopSize = 60;
	Elgato_PframeDistance = 1;
	Elgato_EntropyCoding = 0;
	Elgato_UseNumerDenom = Elgato_UseNumerDenom or 0;
	Elgato_Numer = VUITimeScale or 2997;
	Elgato_Denom = VUITicksPerFrm or 100;
end

printf ("======== Input Parameters: ========\n");
printf ("Elgato_InFile           = \"%s\"\n", Elgato_InFile);
printf ("Elgato_OutFile          = \"%s\"\n", Elgato_OutFile);
printf ("Elgato_InFileType       = \"%s\"\n", Elgato_InFileType);
printf ("Elgato_OutFileType      = \"%s\"\n", Elgato_OutFileType);
printf ("Elgato_InWidth          = %d\n", Elgato_InWidth);
printf ("Elgato_InHeight         = %d\n", Elgato_InHeight);
printf ("Elgato_OutWidth         = %d\n", Elgato_OutWidth);
printf ("Elgato_OutHeight        = %d\n", Elgato_OutHeight);
printf ("Elgato_VBitrate         = %d\n", Elgato_VBitrate);
printf ("Elgato_AvcProfile       = \"%s\"\n", Elgato_AvcProfile);
printf ("Elgato_LevelValue       = %d\n", Elgato_LevelValue);
printf ("Elgato_GopStructure     = %d\n", Elgato_GopStructure);
printf ("Elgato_ClosedGop        = %d\n", Elgato_ClosedGop);
printf ("Elgato_InterlaceMode    = \"%s\"\n", Elgato_InterlaceMode);
printf ("Elgato_FeedAsTS         = %d\n", Elgato_FeedAsTS);
printf ("Elgato_VideoPID         = %d\n", Elgato_VideoPID);
printf ("Elgato_VPP_INTERLACED   = %d\n", Elgato_VPP_INTERLACED);
printf ("Elgato_VPP_PME_HS       = %d\n", Elgato_VPP_PME_HS);
printf ("Elgato_VPP_PME_VS       = %d\n", Elgato_VPP_PME_VS);
printf ("Elgato_DstFrameDuration = %d\n", Elgato_DstFrameDuration);
printf ("Elgato_PixWidth         = %d\n", Elgato_PixWidth);
printf ("Elgato_PixHeight        = %d\n", Elgato_PixHeight);
printf ("Elgato_GopSize          = %d\n", Elgato_GopSize);
printf ("Elgato_PframeDistance   = %d\n", Elgato_PframeDistance);
printf ("Elgato_EntropyCoding    = %d\n", Elgato_EntropyCoding);
printf ("Elgato_UseNumerDenom    = %d\n", Elgato_UseNumerDenom);
printf ("Elgato_Numer            = %d\n", Elgato_Numer);
printf ("Elgato_Denom            = %d\n", Elgato_Denom);
printf ("====================================\n");

AudStreamId = AudStreamId or 1;
VidStreamId = VidStreamId or 0;

ENC_OUTPUT_BUFFER = 8388608;
NUM_AVC_REFERENCES = 8;
	 
sysctl0:setVPortMode({port=1, live=0});

rs0 = sysctl0:createReadStreamer({name="rs0"});
if (Elgato_FeedAsTS > 0) then
	avdec0 = sysctl0:avdecCreate({name="avdec0", atype=Q_AVDEC_CFP_AUDIO_CODEC_QMA, vtype=Q_AVDEC_CFP_VIDEO_CODEC_M2V, vstream=Q_AVDEC_CFP_VIDEO_STREAM_TS, audioBufferSize=100000, videoBufferSize=4000000, maxWidth=Elgato_InWidth, maxHeight=Elgato_InHeight, numoutputframes=6, videoAUs=128});
else
	avdec0 = sysctl0:avdecCreate({name="avdec0", atype=Q_AVDEC_CFP_AUDIO_CODEC_QMA, vtype=Q_AVDEC_CFP_VIDEO_CODEC_M2V, vstream=Q_AVDEC_CFP_VIDEO_STREAM_PS, audioBufferSize=100000, videoBufferSize=4000000, maxWidth=Elgato_InWidth, maxHeight=Elgato_InHeight, numoutputframes=6, videoAUs=128});
end

nvpp0 = sysctl0:nvppCreate({name="nvpp0", maxWidth=Elgato_OutWidth, maxHeight=Elgato_OutHeight});
ws = sysctl0:createWriteStreamer({name="ws0", queuesize=1024});
avcenc0 = sysctl0:avcencCreate({name="avcenc0", ws=ws, maxwidth=Elgato_OutWidth, maxheight=Elgato_OutHeight, numreferenceframes=NUM_AVC_REFERENCES, outputbuffersize=ENC_OUTPUT_BUFFER});

avdec0:setParam({param=Q_AVDEC_CMP_AUDIO_STREAM_ID, value=AudStreamId});
avdec0:setParam({param=Q_AVDEC_CMP_VIDEO_STREAM_ID, value=VidStreamId});

avdec0:setParam({param=Q_AVDEC_CMP_VIDEO_DISABLE_OUTPUT, value=Q_AVDEC_CFP_TRUE});
avdec0:setParam({param=Q_AVDEC_CMP_VIDEO_UNDERFLOW_THRESHOLD, value=1000000});
avdec0:setParam({param=Q_AVDEC_CMP_VIDEO_UNDERFLOW_MARGIN, value=50000});
avdec0:setParam({param=Q_AVDEC_CMP_VIDEO_INITIAL_BUFFER_LEVEL, value=0});
avdec0:setParam({param=Q_AVDEC_CMP_VIDEO_INPUT, value=Q_AVDEC_CFP_VIDEO_STREAM_FILE});

if (Elgato_InterlaceMode == "frame")
then
	avdec0:setParam({param=Q_AVDEC_CMP_VIDEO_PROG_OVERRIDE, value=1});
	avdec0:setParam({param=Q_AVDEC_CMP_VIDEO_PROG_DEFAULT, value=1});
else
	avdec0:setParam({param=Q_AVDEC_CMP_VIDEO_PROG_OVERRIDE, value=0});
	avdec0:setParam({param=Q_AVDEC_CMP_VIDEO_PROG_DEFAULT, value=0});
end

if (Elgato_FeedAsTS > 0) 
then
	avdec0:setParam({param=Q_AVDEC_CMP_VIDEO_TS_PID, value=Elgato_VideoPID});
end

avdec0:activateCfg();

Setup_VPP(nvpp0, Elgato_OutWidth, Elgato_OutHeight, Elgato_VPP_INTERLACED, 1, Elgato_VPP_PME_HS, Elgato_VPP_PME_VS);
		
nvpp0:setParam({param=Q_NVPP_CMP_STC_PER_FRAME, value= Elgato_DstFrameDuration});
nvpp0:setParam({param=Q_NVPP_CMP_STC_PER_OUTPUT_FRAME, value= Elgato_DstFrameDuration});
		
-------------------------------------------------------------------------------------------------
		
nvpp0:activateCfg();

nvpp0:crop({cropWidth=Elgato_OutWidth, cropHeight=Elgato_OutHeight, horzOffset=0, vertOffset=0});
nvpp0:size({outputWidth=Elgato_OutWidth, outputHeight=Elgato_OutHeight});

nvpp0:bindInput({src=avdec0});

avcenc_480i_highquality(avcenc0, Elgato_AvcProfile, Elgato_LevelValue, Elgato_VBitrate, Elgato_GopStructure, Elgato_InterlaceMode);
		
if (Elgato_AvcProfile == "baseline") 
then
	avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_PROFILE_BASELINE_COMPATIBLE, value=1});
	avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_PROFILE_MAIN_COMPATIBLE, value=1});
	avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_ENABLE_8X8_TRANSFORM, value=0});
	for i = 0, 7, 1 do																								
		avcenc0:setVideoEncRegionParam({region=i,param=Q_AVCENC_REG_CMP_INTRAMODES_INTERTRANS_ISLICE, value=0});	
		avcenc0:setVideoEncRegionParam({region=i,param=Q_AVCENC_REG_CMP_INTRAMODES_I_8X8_ISLICE, value=0});			
		avcenc0:setVideoEncRegionParam({region=i,param=Q_AVCENC_REG_CMP_INTRAMODES_INTERTRANS_PSLICE, value=0});	
		avcenc0:setVideoEncRegionParam({region=i,param=Q_AVCENC_REG_CMP_INTRAMODES_I_8X8_PSLICE, value=0});			
	end
elseif (Elgato_AvcProfile == "main") 
then
	avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_PROFILE_MAIN_COMPATIBLE, value=1});
end
		
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_VUI_NUM_UNITS_IN_TICK, value=Elgato_DstFrameDuration});
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_SCENE_CHANGE_ENABLE, value=1});
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_SCENE_CHANGE_NEW_GOP, value=0});
		
-----------------------------------------------------------------------------------------------

---  Start of Elgato additions
		
nvpp0:setParam({param=Q_NVPP_CMP_PIXEL_AR_X, value= Elgato_PixWidth});
nvpp0:setParam({param=Q_NVPP_CMP_PIXEL_AR_Y, value= Elgato_PixHeight});
nvpp0:setParam({param=Q_NVPP_CMP_PIXEL_AR_FIXED, value= 1});
		
-- nvpp0:setParam({param=Q_NVPP_CMP_HW_BYPASS_HSCALE, value= 1});
-- nvpp0:setParam({param=Q_NVPP_CMP_HW_BYPASS_VSCALE, value= 1});
		
-- nvpp0:setParam({param=Q_NVPP_CMP_HINR_THRESHOLD_Y, value= 0});
-- nvpp0:setParam({param=Q_NVPP_CMP_HINR_THRESHOLD_C, value= 0});
		
-- nvpp0:setParam({param=Q_NVPP_CMP_DEINT_MODE, value= 0});
-- nvpp0:setParam({param=Q_NVPP_CMP_DEST_PROG, value= 1});
-- nvpp0:setParam({param=Q_NVPP_CMP_SCALE_FIELD_MODE, value= 0});
		
nvpp0:setParam({param=Q_NVPP_CMP_EDGE_ENHANCE_THRESHOLD, value= 31});
		
nvpp0:activateCfg();
		
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_GOP_SIZE, value=Elgato_GopSize});
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_NEW_SPS_EACH_IDR, value=1});
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_AU_DELIMITERS, value=1});
		
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_MAX_REFERENCE_FRAMES, value=Elgato_PframeDistance});
		
if (Elgato_EntropyCoding >= 0) 
then
	avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_CABAC, value=Elgato_EntropyCoding});
end
		
-- avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_PME_ENABLE, value=0});
-- avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_VA_OT_ENABLE, value=0});
-- avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_VA_OT_MOTION_VECTOR_ENABLE, value=0});
-- avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_VA_OT_MEDIAN_FILTER_ENABLE, value=0});
		
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_DEBLOCK_ENABLE, value=1});
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_DEBLOCK_OFFSET_ALPHA, value=0});
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_DEBLOCK_OFFSET_BETA, value=0});
		
if (Elgato_UseNumerDenom > 0)
then
	avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_RESERVED_PARAM_0, value=Elgato_Numer*2});		-- VUITimeScale
	avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_RESERVED_PARAM_1, value=Elgato_Denom});		-- VUITicksPerFrm
end

avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_SEI_PICT_TIMING_ENABLE, value=1});			-- enable SEI messages
		
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_SEI_BUFFERING_PERIOD, value=64});			-- buffering period
		
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_QPMOD_DCEN, value=0});
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_QPMOD_HFEN, value=0});
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_QPMOD_MOTEN, value=0});
 
avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_ENCODED_FRAME_DROPS, value=0});			-- do not drop frames

avcenc0:setVideoEncParam({param=Q_AVCENC_CMP_CLOSED_GOP, value=Elgato_ClosedGop});			-- open/closed gop
		
avcenc0:activateVideoEncCfg();
		
--- End of Elgato additions
		
-----------------------------------------------------------------------------------------------
		
avcenc0:activateVideoEncCfg();

avcenc0:setAckInterval({interval=4});
avcenc0:setTransferSize({size=4});

ws:open({type=Elgato_OutFileType, file=Elgato_OutFile, sid = {VidStreamId}});
ws:showrate({enable=1});
avcenc0:setStreamID({streamid=VidStreamId});
avcenc0:bindVideoInput({src=nvpp0});

---- overclocking MG3500 ----
sysctl0:configure({param=Q_SYS_CFG_AVC_CLOCK_HZ,   value=216000000});
sysctl0:configure({param=Q_SYS_CFG_PME_CLOCK_HZ,   value=216000000});
sysctl0:configure({param=Q_SYS_CFG_QMM_CLOCK_HZ,   value=216000000});
sysctl0:configure({param=Q_SYS_CFG_MPEG2_CLOCK_HZ, value=216000000});

rs0:bindDecoder({dec=avdec0});

bsr0 = rs0:open({type=Elgato_InFileType, file=Elgato_InFile, srcId={VidStreamId}});
rs0:setReaderParam({bsr=bsr0, param=Q_RS_CFG_BSR_LOOPMODE, value=0});

ws:start();
avcenc0:record();
nvpp0:start();

avdec0:start();
rs0:play({bsr=bsr0});

