Пример #1
0
void guiPositionInitFromStream(IVDPositionControl *pc) {
	if (!inputVideoAVI) return;

	const VDFraction videoRate(inputVideoAVI->getRate());

	pc->SetRange(inputVideoAVI->getStart(), inputVideoAVI->getEnd());
	pc->SetFrameRate(videoRate);
}
Пример #2
0
VDPosition guiPositionHandleCommand(WPARAM wParam, IVDPositionControl *pc) {
	if (!inputVideo)
		return -1;

	IVDStreamSource *pVSS = inputVideo->asStream();
	switch(HIWORD(wParam)) {
		case PCN_START:
			pc->SetPosition(pVSS->getStart());
			return pVSS->getStart();
		case PCN_BACKWARD:
			{
				VDPosition pos = pc->GetPosition();

				if (pos > pVSS->getStart()) {
					pc->SetPosition(pos - 1);
					return pos - 1;
				}
			}
			break;
		case PCN_FORWARD:
			{
				VDPosition pos = pc->GetPosition();

				if (pos < pVSS->getEnd()) {
					pc->SetPosition(pos + 1);
					return pos + 1;
				}
			}
			break;
		case PCN_END:
			pc->SetPosition(pVSS->getEnd());
			return pVSS->getEnd();

		case PCN_KEYPREV:
			{
				VDPosition lSample = inputVideo->prevKey(pc->GetPosition());

				if (lSample < 0) lSample = pVSS->getStart();

				pc->SetPosition(lSample);
				return lSample;
			}
			break;
		case PCN_KEYNEXT:
			{
				VDPosition lSample = inputVideo->nextKey(pc->GetPosition());

				if (lSample < 0) lSample = pVSS->getEnd();

				pc->SetPosition(lSample);
				return lSample;
			}
			break;
	}

	return -1;
}
Пример #3
0
void AppendAVI(const wchar_t *pszFile) {
	if (inputAVI) {
		IVDStreamSource *pVSS = inputVideo->asStream();
		VDPosition lTail = pVSS->getEnd();

		if (inputAVI->Append(pszFile)) {
			g_project->BeginTimelineUpdate();
			FrameSubset& s = g_project->GetTimeline().GetSubset();

			s.insert(s.end(), FrameSubsetNode(lTail, pVSS->getEnd() - lTail, false, 0));
			g_project->EndTimelineUpdate();
		}
	}
}
Пример #4
0
void guiPositionInitFromStream(IVDPositionControl *pc) {
	if (!inputVideo) return;

	IVDStreamSource *pVSS = inputVideo->asStream();
	const VDFraction videoRate(pVSS->getRate());

	pc->SetRange(pVSS->getStart(), pVSS->getEnd());
	pc->SetFrameRate(videoRate);
}
Пример #5
0
int VideoSourceImages::_read(VDPosition lStart, uint32 lCount, void *lpBuffer, uint32 cbBuffer, uint32 *plBytesRead, uint32 *plSamplesRead) {
	if (plBytesRead)
		*plBytesRead = 0;

	if (plSamplesRead)
		*plSamplesRead = 0;

	const wchar_t *buf = mpParent->ComputeFilename(mPathBuf, lStart);

	// Check if we already have the file handle cached.  If not, open the file.
	
	if (lStart == mCachedHandleFrame) {
		mCachedFile.seek(0);
	} else{
		mCachedHandleFrame = -1;
		mCachedFile.closeNT();
		mCachedFile.open(buf, nsVDFile::kRead | nsVDFile::kDenyWrite | nsVDFile::kOpenExisting);
		mCachedHandleFrame = lStart;
	}

	// Replace

	uint32 size = (uint32)mCachedFile.size();

	if (size > 0x3fffffff)
		throw MyError("VideoSourceImages: File \"%s\" is too large (>1GB).", VDTextWToA(buf).c_str());

	if (!lpBuffer) {
		if (plBytesRead)
			*plBytesRead = size;

		if (plSamplesRead)
			*plSamplesRead = 1;

		return 0;
	}

	if (size > cbBuffer) {
		if (plBytesRead)
			*plBytesRead = size;

		return IVDStreamSource::kBufferTooSmall;
	}

	mCachedFile.read(lpBuffer, size);
	
	if (plBytesRead)
		*plBytesRead = size;

	if (plSamplesRead)
		*plSamplesRead = 1;

	return 0;
}
Пример #6
0
void guiPositionBlit(HWND hWndClipping, VDPosition lFrame, int w, int h) {
	if (lFrame<0) return;
	try {
		BITMAPINFOHEADER *dcf;

		if (!inputVideo)
			SendMessage(hWndClipping, CCM_BLITFRAME2, 0, (LPARAM)NULL);
		else {
			dcf = (BITMAPINFOHEADER *)inputVideo->getDecompressedFormat();

			IVDStreamSource *pVSS = inputVideo->asStream();
			if (lFrame < pVSS->getStart() || lFrame >= pVSS->getEnd())
				SendMessage(hWndClipping, CCM_BLITFRAME2, 0, (LPARAM)NULL);
			else {
				Pixel32 *tmpmem;
				const void *pFrame = inputVideo->getFrame(lFrame);

				int dch = abs(dcf->biHeight);

				if (w>0 && h>0 && w!=dcf->biWidth && h != dch && (tmpmem = new Pixel32[((w+1)&~1)*h + ((dcf->biWidth+1)&~1)*dch])) {
					VBitmap vbt(tmpmem, w, h, 32);
					VBitmap vbs(tmpmem+((w+1)&~1)*h, dcf->biWidth, dch, 32);

					VBitmap srcbm((void *)pFrame, dcf);
					vbs.BitBlt(0, 0, &srcbm, 0, 0, -1, -1);
					vbt.StretchBltBilinearFast(0, 0, w, h, &vbs, 0, 0, vbs.w, vbs.h);

					VDPixmap px(VDAsPixmap(vbt));

					SendMessage(hWndClipping, CCM_BLITFRAME2, 0, (LPARAM)&px);

					delete[] tmpmem;
				} else
					SendMessage(hWndClipping, CCM_BLITFRAME2, 0, (LPARAM)&inputVideo->getTargetFormat());
			}
		}

	} catch(const MyError&) {
		_RPT0(0,"Exception!!!\n");
	}
}
Пример #7
0
void AppendAVI(const wchar_t *pszFile) {
	if (inputAVI) {
		VDPosition lTail = inputAVI->videoSrc->getEnd();

		if (inputAVI->Append(pszFile)) {
			g_project->BeginTimelineUpdate();
			FrameSubset& s = g_project->GetTimeline().GetSubset();

			s.insert(s.end(), FrameSubsetNode(lTail, inputAVI->videoSrc->getEnd() - lTail, false, 0));
			g_project->EndTimelineUpdate();
		}
	}
}
Пример #8
0
LRESULT Frameserver::SessionFrame(LPARAM lParam, WPARAM original_frame) {
	FrameserverSession *fs = SessionLookup(lParam);

	if (!fs)
		return VDSRVERR_BADSESSION;

	try {
		const VDPixmapLayout& output = filters.GetOutputLayout();
		if (fs->arena_size < ((output.w*3+3)&-4)*output.h)
			return VDSRVERR_TOOBIG;

		VDPosition pos = mVideoFrameMap[original_frame].mSourceFrame;

		if (pos < 0)
			return VDSRVERR_FAILED;

		vdrefptr<IVDFilterFrameClientRequest> creq;
		filters.RequestFrame(pos, 0, ~creq);

		while(!creq->IsCompleted()) {
			if (filters.Run(NULL, false) == FilterSystem::kRunResult_Running)
				continue;

			switch(mpVideoFrameSource->RunRequests(NULL)) {
				case IVDFilterFrameSource::kRunResult_Running:
				case IVDFilterFrameSource::kRunResult_IdleWasActive:
				case IVDFilterFrameSource::kRunResult_BlockedWasActive:
					continue;
			}

			filters.Block();
		}

		VDPixmap pxdst(VDPixmapFromLayout(mFrameLayout, fs->arena));

		VDFilterFrameBuffer *buf = creq->GetResultBuffer();
		VDPixmapBlt(pxdst, VDPixmapFromLayout(filters.GetOutputLayout(), (void *)buf->LockRead()));
		buf->Unlock();
	} catch(const MyError&) {
		return VDSRVERR_FAILED;
	}

	return VDSRVERR_OK;
}
Пример #9
0
bool VDDialogEditAccelerators::OnLoaded() {
	VDSetDialogDefaultIcons(mhdlg);

	GetWindowRect(mhdlg, &mrInitial);

	mpHotKeyControl = VDGetUIHotKeyExControl((VDGUIHandle)GetControl(IDC_HOTKEY));
	if (mpHotKeyControl)
		mpHotKeyControl->OnChange() += mDelegateHotKeyChanged(this, &VDDialogEditAccelerators::OnHotKeyChanged);

	mResizer.Init(mhdlg);
	mResizer.Add(IDOK, VDDialogResizerW32::kBR);
	mResizer.Add(IDCANCEL, VDDialogResizerW32::kBR);
	mResizer.Add(IDC_ADD, VDDialogResizerW32::kBR);
	mResizer.Add(IDC_REMOVE, VDDialogResizerW32::kBR);
	mResizer.Add(IDC_RESET, VDDialogResizerW32::kBL);
	mResizer.Add(IDC_HOTKEY, VDDialogResizerW32::kBC);
	mResizer.Add(IDC_STATIC_QUICKSEARCH, VDDialogResizerW32::kBL);
	mResizer.Add(IDC_STATIC_SHORTCUT, VDDialogResizerW32::kBL);
	mResizer.Add(IDC_STATIC_AVAILABLECOMMANDS, VDDialogResizerW32::kAnchorX2_C);
	mResizer.Add(IDC_STATIC_BOUNDCOMMANDS, VDDialogResizerW32::kAnchorX1_C | VDDialogResizerW32::kAnchorX2_R);
	mResizer.Add(IDC_AVAILCOMMANDS, VDDialogResizerW32::kAnchorX2_C | VDDialogResizerW32::kAnchorY2_B);
	mResizer.Add(IDC_BOUNDCOMMANDS, VDDialogResizerW32::kAnchorX1_C
		| VDDialogResizerW32::kAnchorX2_R
		| VDDialogResizerW32::kAnchorY2_B
		);
	mResizer.Add(IDC_FILTER, VDDialogResizerW32::kAnchorY1_B | VDDialogResizerW32::kAnchorX2_C | VDDialogResizerW32::kAnchorY2_B);
	mResizer.Add(IDC_HOTKEY, VDDialogResizerW32::kBC);

	AddProxy(&mListViewBoundCommands, IDC_BOUNDCOMMANDS);

	mListViewBoundCommands.SetFullRowSelectEnabled(true);
	mListViewBoundCommands.InsertColumn(0, L"Command", 50);
	mListViewBoundCommands.InsertColumn(1, L"Shortcut", 50);
	mListViewBoundCommands.AutoSizeColumns();

	RefilterCommands("*");

	VDDialogFrameW32::OnLoaded();

	SetFocusToControl(IDC_FILTER);
	return true;
}
Пример #10
0
void VDDialogEditAccelerators::OnItemSelectionChanged(VDUIProxyListView *source, int index) {
	if (index < 0 || mbBlockCommandUpdate)
		return;

	const BoundCommand& bcmd = *mBoundCommands[index];

	if (mpHotKeyControl)
		mpHotKeyControl->SetAccelerator(bcmd.mAccel);

	uint32 n = mFilteredCommands.size();
	int cmdSelIndex = -1;

	for(uint32 i=0; i<n; ++i) {
		const VDAccelToCommandEntry& cent = *mFilteredCommands[i];

		if (!_stricmp(cent.mpName, bcmd.mpCommand)) {
			cmdSelIndex = i;
			break;
		}
	}

	LBSetSelectedIndex(IDC_AVAILCOMMANDS, cmdSelIndex);
}
Пример #11
0
int VDVideoSourceFLM::_read(VDPosition lStart, uint32 lCount, void *lpBuffer, uint32 cbBuffer, uint32 *lBytesRead, uint32 *lSamplesRead) {
	if (lCount > 1)
		lCount = 1;

	int ret = 0;

	if (lCount > 0) {
		if (lpBuffer) {
			if (mVisibleFrameSize > cbBuffer)
				ret = IVDStreamSource::kBufferTooSmall;
			else {
				mpParent->ReadSpan((uint64)mFrameSize * lStart, lpBuffer, mVisibleFrameSize);

				// Swizzle the frame now. Easier this way. We need to go from RGBA to BGRA.
				uint8 *p = (uint8 *)lpBuffer;
				uint32 count = mVisibleFrameSize >> 2;

				do {
					uint8 r = p[0];
					uint8 b = p[2];

					p[0] = b;
					p[2] = r;
					p += 4;
				} while(--count);
			}
		}
	}

	if (lBytesRead)
		*lBytesRead = mVisibleFrameSize;
	if (lSamplesRead)
		*lSamplesRead = lCount;

	return ret;
}
Пример #12
0
void AppendAVIAutoscan(const wchar_t *pszFile) {
	wchar_t buf[MAX_PATH];
	wchar_t *s = buf, *t;
	int count = 0;

	if (!inputAVI)
		return;

	IVDStreamSource *pVSS = inputVideo->asStream();
	VDPosition originalCount = pVSS->getEnd();

	wcscpy(buf, pszFile);

	t = VDFileSplitExt(VDFileSplitPath(s));

	if (t>buf)
		--t;

	try {
		for(;;) {
			if (!VDDoesPathExist(buf))
				break;
			
			if (!inputAVI->Append(buf))
				break;

			++count;

			s = t;

			for(;;) {
				if (s<buf || !isdigit(*s)) {
					memmove(s+2, s+1, sizeof(wchar_t) * wcslen(s));
					s[1] = L'1';
					++t;
				} else {
					if (*s == L'9') {
						*s-- = L'0';
						continue;
					}
					++*s;
				}
				break;
			}
		}
	} catch(const MyError& e) {
		// if the first segment failed, turn the warning into an error
		if (!count)
			throw;

		// log append errors, but otherwise eat them
		VDLog(kVDLogWarning, VDTextAToW(e.gets()));
	}

	guiSetStatus("Appended %d segments (stopped at \"%s\")", 255, count, VDTextWToA(buf).c_str());

	if (count) {
		FrameSubset& s = g_project->GetTimeline().GetSubset();
		g_project->BeginTimelineUpdate();
		s.insert(s.end(), FrameSubsetNode(originalCount, pVSS->getEnd() - originalCount, false, 0));
		g_project->EndTimelineUpdate();
	}
}
Пример #13
0
void SetSelectionEnd(long ms) {
	if (!inputVideoAVI)
		return;

	g_project->SetSelectionEnd(g_project->GetFrameCount() - inputVideoAVI->msToSamples(ms));
}
Пример #14
0
void SetSelectionStart(long ms) {
	if (!inputVideoAVI)
		return;

	g_project->SetSelectionStart(inputVideoAVI->msToSamples(ms));
}
Пример #15
0
const void *VideoSourceImages::streamGetFrame(const void *inputBuffer, uint32 data_len, bool is_preroll, VDPosition frame_num, VDPosition target_sample) {
	// We may get a zero-byte frame if we already have the image.

	if (!data_len)
		return getFrameBuffer();

	int w, h;
	bool bHasAlpha;

	bool bIsPNG = false;
	bool bIsJPG = false;
	bool bIsBMP = false;
	bool bIsIFF = false;
	bool bIsTGA = false;

	bIsPNG = VDDecodePNGHeader(inputBuffer, data_len, w, h, bHasAlpha);
	if (!bIsPNG) {
		bIsJPG = VDIsJPEGHeader(inputBuffer, data_len);
		if (!bIsJPG) {
			bIsBMP = DecodeBMPHeader(inputBuffer, data_len, w, h, bHasAlpha);
			if (!bIsBMP) {
				bIsIFF = VDIsMayaIFFHeader(inputBuffer, data_len);
				if (!bIsIFF)
					bIsTGA = DecodeTGAHeader(inputBuffer, data_len, w, h, bHasAlpha);
			}
		}
	}

	if (!bIsBMP && !bIsTGA && !bIsJPG && !bIsPNG && !bIsIFF)
		throw MyError("Image file must be in PNG, Windows BMP, truecolor TARGA format, MayaIFF, or sequential JPEG format.");

	if (bIsJPG) {
		if (!mpJPEGDecoder)
			mpJPEGDecoder = VDCreateJPEGDecoder();
		mpJPEGDecoder->Begin(inputBuffer, data_len);
		mpJPEGDecoder->DecodeHeader(w, h);
	}

	VDPixmap pxIFF;
	if (bIsIFF) {
		if (!mpIFFDecoder)
			mpIFFDecoder = VDCreateImageDecoderIFF();
		pxIFF = mpIFFDecoder->Decode(inputBuffer, data_len);
		w = pxIFF.w;
		h = pxIFF.h;
	}

	// Check image header.

	VDAVIBitmapInfoHeader *pFormat = getImageFormat();

	if (getFrameBuffer()) {
		if (w != pFormat->biWidth || h != pFormat->biHeight) {
			vdfastvector<wchar_t> errBuf;

			throw MyError("Image \"%ls\" (%dx%d) doesn't match the image dimensions of the first image (%dx%d)."
					, mpParent->ComputeFilename(errBuf, frame_num), w, h, pFormat->biWidth, pFormat->biHeight);
		}

	} else {
		if (!AllocFrameBuffer(w * h * 4))
			throw MyMemoryError();

		pFormat->biSize				= sizeof(BITMAPINFOHEADER);
		pFormat->biWidth			= w;
		pFormat->biHeight			= h;
		pFormat->biPlanes			= 1;
		pFormat->biCompression		= 0xFFFFFFFFUL;
		pFormat->biBitCount			= 0;
		pFormat->biSizeImage		= 0;
		pFormat->biXPelsPerMeter	= 0;
		pFormat->biYPelsPerMeter	= 0;
		pFormat->biClrUsed			= 0;
		pFormat->biClrImportant		= 0;

		// special case for initial read in constructor

		return NULL;
	}

	if (bIsJPG) {
		int format;

		switch(mvbFrameBuffer.depth) {
		case 16:	format = IVDJPEGDecoder::kFormatXRGB1555;	break;
		case 24:	format = IVDJPEGDecoder::kFormatRGB888;		break;
		case 32:	format = IVDJPEGDecoder::kFormatXRGB8888;	break;
		}

		mpJPEGDecoder->DecodeImage((char *)mvbFrameBuffer.data + mvbFrameBuffer.pitch * (mvbFrameBuffer.h - 1), -mvbFrameBuffer.pitch, format);
		mpJPEGDecoder->End();
	}

	if (bIsIFF)
		VDPixmapBlt(getTargetFormat(), pxIFF);

	if (bIsBMP)
		DecodeBMP(inputBuffer, data_len, mvbFrameBuffer);
	if (bIsTGA)
		DecodeTGA(inputBuffer, data_len, mvbFrameBuffer);
	if (bIsPNG) {
		if (!mpPNGDecoder)
			mpPNGDecoder = VDCreateImageDecoderPNG();

		PNGDecodeError err = mpPNGDecoder->Decode(inputBuffer, data_len);

		if (err) {
			if (err == kPNGDecodeOutOfMemory)
				throw MyMemoryError();

			vdfastvector<wchar_t> errBuf;

			throw MyError("Error decoding \"%ls\": %ls\n", mpParent->ComputeFilename(errBuf, frame_num), VDLoadString(0, kVDST_PNGDecodeErrors, err));
		}

		VDPixmapBlt(VDAsPixmap(mvbFrameBuffer), mpPNGDecoder->GetFrameBuffer());
	}

	mCachedFrame = frame_num;

	return mpFrameBuffer;
}
Пример #16
0
bool VDDialogEditAccelerators::OnCommand(uint32 id, uint32 extcode) {
	if (id == IDC_FILTER) {
		if (extcode == EN_CHANGE) {
			VDStringA s("*");
			s += VDTextWToA(GetControlValueString(id)).c_str();
			s += '*';

			RefilterCommands(s.c_str());
			return true;
		}
	} else if (id == IDC_ADD) {
		VDUIAccelerator accel;

		int selIdx = LBGetSelectedIndex(IDC_AVAILCOMMANDS);

		if ((size_t)selIdx < mFilteredCommands.size()) {
			const VDAccelToCommandEntry *ace = mFilteredCommands[selIdx];

			if (mpHotKeyControl) {
				mpHotKeyControl->GetAccelerator(accel);

				// Look for a conflicting command.
				for(BoundCommands::iterator it(mBoundCommands.begin()), itEnd(mBoundCommands.end()); it != itEnd; ++it) {
					BoundCommand *obc = *it;

					if (obc->mAccel == accel) {
						VDStringW keyName;
						VDUIGetAcceleratorString(accel, keyName);

						VDStringA msg;
						msg.sprintf("The key %ls is already bound to %hs. Rebind it to %hs?", keyName.c_str(), obc->mpCommand, ace->mpName);

						if (IDOK != MessageBox(mhdlg, msg.c_str(), g_szWarning, MB_OKCANCEL | MB_ICONEXCLAMATION))
							return true;

						mBoundCommands.erase(it);
						obc->Release();
					}
				}

				vdrefptr<BoundCommand> bc(new_nothrow BoundCommand);
				
				if (bc) {
					bc->mpCommand = ace->mpName;
					bc->mCommandId = ace->mId;
					bc->mAccel = accel;

					mBoundCommands.push_back(bc.release());
					RefreshBoundList();
				}
			}
		}

		return true;
	} else if (id == IDC_REMOVE) {
		int selIdx = mListViewBoundCommands.GetSelectedIndex();

		if ((unsigned)selIdx < mBoundCommands.size()) {
			BoundCommand *bc = mBoundCommands[selIdx];

			mBoundCommands.erase(mBoundCommands.begin() + selIdx);

			bc->Release();

			RefreshBoundList();
		}

		return true;
	} else if (id == IDC_RESET) {
		if (IDOK == MessageBox(mhdlg, "Really reset?", g_szWarning, MB_OKCANCEL | MB_ICONEXCLAMATION))
			LoadTable(mBoundCommandsDefault);

		return true;
	}

	return false;
}
Пример #17
0
void Frameserver::Go(IVDubServerLink *ivdsl, char *name) {
	int server_index = -1;

	lpszFsname = name;
	
	// prepare the sources...
	if (!vSrc->setTargetFormat(g_dubOpts.video.mInputFormat))
		if (!vSrc->setTargetFormat(nsVDPixmap::kPixFormat_XRGB8888))
			if (!vSrc->setTargetFormat(nsVDPixmap::kPixFormat_RGB888))
				if (!vSrc->setTargetFormat(nsVDPixmap::kPixFormat_XRGB1555))
					if (!vSrc->setTargetFormat(nsVDPixmap::kPixFormat_Pal8))
						throw MyError("The decompression codec cannot decompress to an RGB format. This is very unusual. Check that any \"Force YUY2\" options are not enabled in the codec's properties.");

	IVDStreamSource *pVSS = vSrc->asStream();
	FrameSubset videoset(mSubset);

	const VDFraction frameRateTimeline(g_project->GetTimelineFrameRate());
	VDPosition startFrame;
	VDPosition endFrame;
	VDConvertSelectionTimesToFrames(*opt, mSubset, frameRateTimeline, startFrame, endFrame);
	InitVideoStreamValuesStatic(vInfo, vSrc, aSrc, opt, &mSubset, &startFrame, &endFrame);

	const VDPixmap& px = vSrc->getTargetFormat();

	const VDFraction& srcFAR = vSrc->getPixelAspectRatio();
	filters.prepareLinearChain(&g_filterChain, px.w, px.h, px.format, vInfo.mFrameRatePreFilter, -1, srcFAR);

	mpVideoFrameSource = new VDFilterFrameVideoSource;
	mpVideoFrameSource->Init(vSrc, filters.GetInputLayout());

	filters.SetVisualAccelDebugEnabled(false);
	filters.SetAccelEnabled(VDPreferencesGetFilterAccelEnabled());
	filters.SetAsyncThreadCount(VDPreferencesGetFilterThreadCount());
	filters.initLinearChain(NULL, 0, &g_filterChain, mpVideoFrameSource, px.w, px.h, px.format, px.palette, vInfo.mFrameRatePreFilter, -1, srcFAR);

	filters.ReadyFilters();

	InitVideoStreamValuesStatic2(vInfo, opt, &filters, frameRateTimeline);

	InitAudioStreamValuesStatic(aInfo, aSrc, opt);

	vdfastvector<IVDVideoSource *> vsrcs(1, vSrc);
	mVideoFrameMap.Init(vsrcs, vInfo.start_src, vInfo.mFrameRateTimeline / vInfo.mFrameRate, &mSubset, vInfo.end_dst, opt->video.mbUseSmartRendering, opt->video.mode == DubVideoOptions::M_NONE, opt->video.mbPreserveEmptyFrames, &filters, false, false);

	if (opt->audio.fEndAudio)
		videoset.deleteRange(endFrame, videoset.getTotalFrames());

	if (opt->audio.fStartAudio)
		videoset.deleteRange(0, startFrame);

	VDDEBUG("Video subset:\n");
	videoset.dump();

	if (aSrc)
		AudioTranslateVideoSubset(audioset, videoset, vInfo.mFrameRateTimeline, aSrc->getWaveFormat(), !opt->audio.fEndAudio && (videoset.empty() || videoset.back().end() == pVSS->getEnd()) ? aSrc->getEnd() : 0, NULL);

	VDDEBUG("Audio subset:\n");
	audioset.dump();

	if (aSrc) {
		audioset.offset(aSrc->msToSamples(-opt->audio.offset));
		lAudioSamples = VDClampToUint32(audioset.getTotalFrames());
	} else
		lAudioSamples = 0;

	lVideoSamples = VDClampToUint32(mVideoFrameMap.size());

	vSrc->streamBegin(true, false);

	const VDPixmapLayout& outputLayout = filters.GetOutputLayout();

	mFrameSize = VDPixmapCreateLinearLayout(mFrameLayout, nsVDPixmap::kPixFormat_RGB888, outputLayout.w, outputLayout.h, 4);
	VDPixmapLayoutFlipV(mFrameLayout);

	if (aSrc)
		aSrc->streamBegin(true, false);

	// usurp the window

	VDUIFrame *pFrame = VDUIFrame::GetFrame(hwnd);
	mpUIFrame = pFrame;
	pFrame->Attach(this);

	guiSetTitle(hwnd, IDS_TITLE_FRAMESERVER);

	// create dialog box

	mbExit = false;

	if (hwndStatus = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_SERVER), hwnd, Frameserver::StatusDlgProc, (LPARAM)this)) {

		// hide the main window

		ShowWindow(hwnd, SW_HIDE);

		// create the frameserver

		server_index = ivdsl->CreateFrameServer(name, hwnd);

		if (server_index>=0) {

			// kick us into high priority

			SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);

			// enter window loop

			{
				MSG msg;

				while(!mbExit) {
					BOOL result = GetMessage(&msg, NULL, 0, 0);

					if (result == (BOOL)-1)
						break;

					if (!result) {
						PostQuitMessage(msg.wParam);
						break;
					}

					TranslateMessage(&msg);
					DispatchMessage(&msg);
				}
			}

			// return to normal priority

			SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);

			ivdsl->DestroyFrameServer(server_index);
		}

		if (IsWindow(hwndStatus)) DestroyWindow(hwndStatus);

		// show the main window

		ShowWindow(hwnd, SW_SHOW);
	}

	// unsubclass
	pFrame->Detach();

	if (vSrc) {
		IVDStreamSource *pVSS = vSrc->asStream();
		pVSS->streamEnd();
	}

	if (server_index<0) throw MyError("Couldn't create frameserver");
}