⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 videosource.cpp

📁 VC++视频开发实例集锦(包括“远程视频监控”"语音识别系统"等13个经典例子)
💻 CPP
📖 第 1 页 / 共 3 页
字号:

		fUseGDI = true;

	} else if (!is_dib) {
		FOURCC fccOriginalCodec = bmih->biCompression;

		// 如果是老式的MPEG-4解码器,尝试所有的已知的老式解码器
		// 它们都是同种的解码器,因此互相兼容


		switch(bmih->biCompression) {
		case '34PM':		// Microsoft MPEG-4 V3
		case '3VID':		// "DivX Low-Motion" (4.10.0.3917)
		case '4VID':		// "DivX Fast-Motion" (4.10.0.3920)
		case '14PA':		// "AngelPotion Definitive" (4.0.00.3688)
			if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
			bmih->biCompression = '34PM';
			if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
			bmih->biCompression = '3VID';
			if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
			bmih->biCompression = '4VID';
			if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
			bmih->biCompression = '14PA';
		default:
			if (AttemptCodecNegotiation(bmih, is_mjpeg)) return;
			break;
		}


		const char *s = LookupVideoCodec(fccOriginalCodec);

		throw MyError("Couldn't locate decompressor for format '%c%c%c%c' (%s)\n"
						"\n"
						"VirtualDub requires a Video for Windows (VFW) compatible codec to decompress "
						"video. DirectShow codecs, such as those used by Windows Media Player, are not "
						"suitable."
					,(fccOriginalCodec    ) & 0xff
					,(fccOriginalCodec>> 8) & 0xff
					,(fccOriginalCodec>>16) & 0xff
					,(fccOriginalCodec>>24) & 0xff
					,s ? s : "unknown");
	}
}

bool VideoSourceAVI::AttemptCodecNegotiation(BITMAPINFOHEADER *bmih, bool is_mjpeg) {

	// VideoMatrix sets streamInfo.fccHandler to NULL.  Danger, Will Robinson.

	if (!use_internal) {

		// Try the handler specified in the file first.  In some cases, it'll
		// be wrong or missing.

		if (streamInfo.fccHandler)
			hicDecomp = ICOpen(ICTYPE_VIDEO, streamInfo.fccHandler, ICMODE_DECOMPRESS);

		if (!hicDecomp || ICERR_OK!=ICDecompressQuery(hicDecomp, bmih, NULL)) {
			if (hicDecomp)
				ICClose(hicDecomp);

			// Pick a handler based on the biCompression field instead.

			hicDecomp = ICOpen(ICTYPE_VIDEO, bmih->biCompression, ICMODE_DECOMPRESS);

			if (!hicDecomp || ICERR_OK!=ICDecompressQuery(hicDecomp, bmih, NULL)) {
				if (hicDecomp)
					ICClose(hicDecomp);

				// AngelPotion f*cks us over here and overwrites our format if we keep this in.
				// So let's write protect the format.  You'll see a nice C0000005 error when
				// the AP DLL tries to modify it.

//				hicDecomp = ICLocate(ICTYPE_VIDEO, NULL, getImageFormat(), NULL, ICMODE_DECOMPRESS);

				int siz = getFormatLen();

				BITMAPINFOHEADER *pbih_protected = (BITMAPINFOHEADER *)VirtualAlloc(NULL, siz, MEM_COMMIT, PAGE_READWRITE);

				if (pbih_protected) {
					DWORD dwOldProtect;

					memcpy(pbih_protected, bmih, siz);
					VirtualProtect(pbih_protected, siz, PAGE_READONLY, &dwOldProtect);

					hicDecomp = ICLocate(ICTYPE_VIDEO, NULL, pbih_protected, NULL, ICMODE_DECOMPRESS);

					VirtualFree(pbih_protected, 0, MEM_RELEASE);
				}
			}
		}
	}

	if (!hicDecomp) {

		// Is it MJPEG or I420?  Maybe we can do it ourselves.

		if (is_mjpeg) {
//			if (!(mdec = CreateMJPEGDecoder(getImageFormat()->biWidth, getImageFormat()->biHeight)))
//				throw MyMemoryError();

			return true;
		} else {
			return false;
		}
	} else {

		// check for bad MPEG-4 V2/V3 codec

		if (isEqualFOURCC(bmih->biCompression, '24PM'))
			return CheckMPEG4Codec(hicDecomp, false);
		else if (isEqualFOURCC(bmih->biCompression, '34PM'))
			return CheckMPEG4Codec(hicDecomp, true);
		else
			return true;
	}
}

///////////////////////////////////////////////////////////////////////////

void VideoSourceAVI::Reinit() {
	long nOldFrames, nNewFrames;

	nOldFrames = lSampleLast - lSampleFirst;
	nNewFrames = pAVIStream->End() - pAVIStream->Start();

	if (mjpeg_splits) {
		nOldFrames >>= 1;
	}

	if (nOldFrames != nNewFrames && (mjpeg_mode==IFMODE_SPLIT1 || mjpeg_mode==IFMODE_SPLIT2)) {
		// We have to resize the mjpeg_splits array.

		long *pNewSplits = new long[lSampleLast - lSampleFirst];

		if (!pNewSplits)
			throw MyMemoryError();

		int i;

		memcpy(pNewSplits, mjpeg_splits, sizeof(long)*nOldFrames);

		for(i=nOldFrames; i<nNewFrames; i++)
			pNewSplits[i] = -1;

		delete[] mjpeg_splits;

		mjpeg_splits = pNewSplits;
	}

	if (pAVIStream->Info(&streamInfo, sizeof streamInfo))
		throw MyError("Error obtaining video stream info.");

	lSampleFirst = pAVIStream->Start();

	if (mjpeg_splits) {
		streamInfo.dwRate *= 2;
		streamInfo.dwLength *= 2;
		lSampleLast = pAVIStream->End() * 2 - lSampleFirst;
	} else
		lSampleLast = pAVIStream->End();

	streamInfo.dwLength		= lSampleLast - lSampleFirst;
}

void VideoSourceAVI::redoKeyFlags() {
	long lSample;
	long lMaxFrame=0;
	long lActualBytes, lActualSamples;
	int err;
	void *lpInputBuffer = NULL;
	void *lpKeyBuffer = NULL;
	BOOL fStreamBegun = FALSE;
	int iBytes;
	long *pFrameSums;

	if (!hicDecomp)
		return;

	iBytes = (lSampleLast+7-lSampleFirst)>>3;

	if (!(key_flags = new char[iBytes]))
		throw MyMemoryError();

	memset(key_flags, 0, iBytes);

	// Find maximum frame

	lSample = lSampleFirst;
	while(lSample < lSampleLast) {
		err = _read(lSample, 1, NULL, 0, &lActualBytes, &lActualSamples);
		if (err == AVIERR_OK)
//			throw MyAVIError("VideoSource", err);

			if (lActualBytes > lMaxFrame) lMaxFrame = lActualBytes;

		++lSample;
	}

	if (!setDecompressedFormat(24))
		if (!setDecompressedFormat(32))
			if (!setDecompressedFormat(16))
				if (!setDecompressedFormat(8))
					throw MyError("Video decompressor is incapable of decompressing to an RGB format.");

	if (!(lpInputBuffer = new char[((lMaxFrame+7)&-8) + lMaxFrame]))
		throw MyMemoryError();

	if (!(pFrameSums = new long[lSampleLast - lSampleFirst])) {
		delete[] lpInputBuffer;
		throw MyMemoryError();
	}

	try {
//		ProgressDialog pd(NULL, "AVI Import Filter", "Rekeying video stream", (lSampleLast - lSampleFirst)*2, true);
//		pd.setValueFormat("Frame %ld of %ld");
		MessageBox( NULL, "AVI Import Filter", "Rekeying video stream", MB_OK);

		streamBegin(true);
		fStreamBegun = TRUE;

		lSample = lSampleFirst;
		while(lSample < lSampleLast) {
			long lBlackTotal=0, lWhiteTotal=0;
			long x, y;
			const long lWidth	= (bmihDecompressedFormat->biWidth * bmihDecompressedFormat->biBitCount + 7)/8;
			const long lModulo	= (4-lWidth)&3;
			const long lHeight	= bmihDecompressedFormat->biHeight;
			unsigned char *ptr;

			_RPT1(0,"Rekeying frame %ld\n", lSample);

			err = _read(lSample, 1, lpInputBuffer, lMaxFrame, &lActualBytes, &lActualSamples);
			if (err != AVIERR_OK)
//				throw MyAVIError("VideoSourceAVI", err);
				goto rekey_error;

#if 0
			// decompress frame with an all black background

			memset(lpvBuffer, 0, bmihDecompressedFormat->biSizeImage);
			streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);

			ptr = (unsigned char *)lpvBuffer;
			y = lHeight;
			do {
				x = lWidth;
				do {
					lBlackTotal += (long)*ptr++;
				} while(--x);

				ptr += lModulo;
			} while(--y);

			// decompress frame with an all white background

			memset(lpvBuffer, 0xff, bmihDecompressedFormat->biSizeImage);
			streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);

			ptr = (unsigned char *)lpvBuffer;
			y = lHeight;
			do {
				x = lWidth;
				do {
					lWhiteTotal += (long)*ptr++;
				} while(--x);

				ptr += lModulo;
			} while(--y);
#else

			streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);

			ptr = (unsigned char *)lpvBuffer;
			y = lHeight;
			do {
				x = lWidth;
				do {
					lWhiteTotal += (long)*ptr++;
					lWhiteTotal ^= 0xAAAAAAAA;
				} while(--x);

				ptr += lModulo;
			} while(--y);


			pFrameSums[lSample - lSampleFirst] = lWhiteTotal;
#endif

//			if (lBlackTotal == lWhiteTotal)
//				key_flags[(lSample - lSampleFirst)>>3] |= 1<<((lSample-lSampleFirst)&7);

rekey_error:
			++lSample;

//			pd.advance(lSample - lSampleFirst);
//			pd.check();
		}

		lSample = lSampleFirst;
		do {
			long lBlackTotal=0, lWhiteTotal=0;
			long x, y;
			const long lWidth	= (bmihDecompressedFormat->biWidth * bmihDecompressedFormat->biBitCount + 7)/8;
			const long lModulo	= (4-lWidth)&3;
			const long lHeight	= bmihDecompressedFormat->biHeight;
			unsigned char *ptr;

			_RPT1(0,"Rekeying frame %ld\n", lSample);

			err = _read(lSample, 1, lpInputBuffer, lMaxFrame, &lActualBytes, &lActualSamples);
			if (err != AVIERR_OK)
//				throw MyAVIError("VideoSourceAVI", err);
				goto rekey_error2;

			streamGetFrame(lpInputBuffer, lActualBytes, FALSE, FALSE, lSample);

			ptr = (unsigned char *)lpvBuffer;
			y = lHeight;
			do {
				x = lWidth;
				do {
					lWhiteTotal += (long)*ptr++;
					lWhiteTotal ^= 0xAAAAAAAA;
				} while(--x);

				ptr += lModulo;
			} while(--y);


			if (lWhiteTotal == pFrameSums[lSample - lSampleFirst])
				key_flags[(lSample - lSampleFirst)>>3] |= 1<<((lSample-lSampleFirst)&7);

rekey_error2:
			if (lSample == lSampleFirst)
				lSample = lSampleLast-1;
			else
				--lSample;

//			pd.advance(lSampleLast*2 - (lSample+lSampleFirst));
//			pd.check();
		} while(lSample >= lSampleFirst+1);

		streamEnd();
	} catch(...) {
		if (fStreamBegun) streamEnd();
		delete[] lpInputBuffer;
		delete[] pFrameSums;
		throw;
	}

	delete[] lpInputBuffer;
	delete[] pFrameSums;
}

int VideoSourceAVI::_read(LONG lStart, LONG lCount, LPVOID lpBuffer, LONG cbBuffer, LONG *lBytesRead, LONG *lSamplesRead) {
	IAVIReadStream *pSource = pAVIStream;
	bool phase = (lStart - lSampleFirst)&1;

	if (mjpeg_mode == IFMODE_SPLIT1 || mjpeg_mode == IFMODE_SPLIT2)
		lStart = lSampleFirst + (lStart - lSampleFirst)/2;

	// 如果被条纹化,那么寻找正确的条纹

	if (stripesys) {
		AVIStripeIndexEntry *asie;
		long offset;

		if (!(asie = stripe_index->lookup(lStart)))
			return AVIERR_FILEREAD;

		offset = lStart - asie->lSampleFirst;

		if (lCount > asie->lSampleCount-offset)
			lCount = asie->lSampleCount-offset;

		if (!stripe_streams[asie->lStripe])
			return AVIERR_FILEREAD;

		pSource = stripe_streams[asie->lStripe];
		lStart = asie->lStripeSample + offset;
	}

	// 是否为MJPEG修正模式?

	if (mjpeg_mode) {
		int res;
		LONG lBytes, lSamples;
		long lRealSample = lStart;
		long lOffset, lLength;

		// 是否和上次输入的sample相同?

		if (lStart == mjpeg_last) {
			lBytes = mjpeg_last_size;
			res = AVIERR_OK;
		} else {

			// 把sample读入内存。如果不知道放入的地址或者已经知道
			// 条纹在那里,仅仅返回sample的大小

			if (lpBuffer || mjpeg_splits[lStart - lSampleFirst]<0) {

				mjpeg_last = -1;

				if (mjpeg_reorder_buffer_size)
					res = pSource->Read(lStart, 1, mjpeg_reorder_buffer, mjpeg_reorder_buffer_size, &lBytes, &lSamples);

				if (res == AVIERR_BUFFERTOOSMALL || !mjpeg_reorder_buffer_size) {
					void *new_buffer;
					int new_size;

					res = pSource->Read(lStart, 1, NULL, 0, &lBytes, &lSamples);

					if (res == AVIERR_OK) {

						_ASSERT(lBytes != 0);

						new_size = (lBytes + 4095) & -4096;

						new_buffer = reallocmem(mjpeg_reorder_buffer, new_size);

						if (!new_buffer)
							return AVIERR_MEMORY;

						mjpeg_reorder_buffer = new_buffer;
						mjpeg_reorder_buffer_size = new_size;

						res = pSource->Read(lStart, 1, mjpeg_reorder_buffer, mjpeg_reorder_buffer_size, &lBytes, &lSamples);
					}
				}

				if (res == AVIERR_OK) {
					mjpeg_last = lStart;
					mjpeg_last_size = lBytes;
				}
			} else
				res = pSource->Read(lStart, 1, NULL, 0, &lBytes, &lSamples);
		}


		if (res != AVIERR_OK) {
			if (lBytesRead)
				*lBytesRead = 0;
			if (lSamplesRead)
				*lSamplesRead = 0;
			return res;
		} else if (!lBytes) {
			if (lBytesRead)
				*lBytesRead = 0;
			if (lSamplesRead)
				*lSamplesRead = 1;
			return AVIERR_OK;
		}

		// 在sample中寻找SOI标记

		lOffset = 0;
		lLength = lBytes;

		{
			int i;

			// 是否已经知道条纹在哪里?

			if (mjpeg_splits[lStart-lSampleFirst]<0) {
				for(i=2; i<lBytes-2; i++)
					if (((unsigned char *)mjpeg_reorder_buffer)[i] == (unsigned char)0xFF
							&& ((unsigned char *)mjpeg_reorder_buffer)[i+1] == (unsigned char)0xD8)
						break;

				mjpeg_splits[lStart - lSampleFirst] = i;
			} else {
				i = mjpeg_splits[lStart - lSampleFirst];
			}

			if (i<lBytes-2) {
				if (mjpeg_mode != IFMODE_SWAP) {
					switch(mjpeg_mode) {
					case IFMODE_SPLIT2:
						phase = !phase;
						break;
					case IFMODE_DISCARD1:
						phase = false;
						break;
					case IFMODE_DISCARD2:
						phase = true;
						break;
					}

					if (phase) {
						lOffset = i;
						lLength = lBytes - i;
					} else {
						lOffset = 0;
						lLength = i;
					}
				} else
					lOffset = i;
			}
		}

		if (lpBuffer) {
			if (lSamplesRead)
				*lSamplesRead = 1;
			if (lBytesRead)
				*lBytesRead = lLength;

			if (cbBuffer < lLength)
				return AVIERR_BUFFERTOOSMALL;

			if (mjpeg_mode == IFMODE_SWAP) {
				char *pp1 = (char *)lpBuffer;
				char *pp2 = (char *)lpBuffer + (lBytes - lOffset);

				memcpy(pp1, (char *)mjpeg_reorder_buffer+lOffset, lBytes - lOffset);
				if (lOffset)
					memcpy(pp2, mjpeg_reorder_buffer, lOffset);

				if (((short *)pp1)[1]==(short)0xE0FF)
					pp1[10] = 1;

				if (((short *)pp2)[1]==(short)0xE0FF)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -