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

📄 theoradecodefilter.cpp

📁 Window Mobile Capture with DirectDraw
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	//Create the structures for setproperties to use
	ALLOCATOR_PROPERTIES locReqAlloc;
	ALLOCATOR_PROPERTIES locActualAlloc;

	//MTS::: Maybe this needs to be reconsidered for other output types... ie rgb32 will be much bigger

	const unsigned long MIN_BUFFER_SIZE = 16*16;			//What should this be ????
	const unsigned long DEFAULT_BUFFER_SIZE = 1024*1024 * 2;
	const unsigned long MIN_NUM_BUFFERS = 1;
	const unsigned long DEFAULT_NUM_BUFFERS = 1;

	
	//Validate and change what we have been requested to do.
	//Allignment of data
	if (inPropertyRequest->cbAlign <= 0) {
		locReqAlloc.cbAlign = 1;
	} else {
		locReqAlloc.cbAlign = inPropertyRequest->cbAlign;
	}

	//Size of each buffer
	if (inPropertyRequest->cbBuffer < MIN_BUFFER_SIZE) {
		locReqAlloc.cbBuffer = DEFAULT_BUFFER_SIZE;
	} else {
		locReqAlloc.cbBuffer = inPropertyRequest->cbBuffer;
	}

	//How many prefeixed bytes
	if (inPropertyRequest->cbPrefix < 0) {
			locReqAlloc.cbPrefix = 0;
	} else {
		locReqAlloc.cbPrefix = inPropertyRequest->cbPrefix;
	}

	//Number of buffers in the allcoator
	if (inPropertyRequest->cBuffers < MIN_NUM_BUFFERS) {
		locReqAlloc.cBuffers = DEFAULT_NUM_BUFFERS;
	} else {

		locReqAlloc.cBuffers = inPropertyRequest->cBuffers;
	}

	//Set the properties in the allocator
	locHR = inAllocator->SetProperties(&locReqAlloc, &locActualAlloc);

	//Check the response
	switch (locHR) {
		case E_POINTER:
			//debugLog<<"DecideBufferSize : SetProperties - NULL POINTER"<<endl;
			return locHR;
		case VFW_E_ALREADY_COMMITTED:
			//debugLog<<"DecideBufferSize : SetProperties - Already COMMITED"<<endl;
			return locHR;
		case VFW_E_BADALIGN:
			//debugLog<<"DecideBufferSize : SetProperties - Bad ALIGN"<<endl;
			return locHR;
		case VFW_E_BUFFERS_OUTSTANDING:
			//debugLog<<"DecideBufferSize : SetProperties - BUFFS OUTSTANDING"<<endl;
			return locHR;
		case S_OK:
			break;
		default:
			//debugLog<<"DecideBufferSize : SetProperties - UNKNOWN ERROR"<<endl;
			break;
	}

	locHR = inAllocator->Commit();
	//debugLog<<"DecideBufferSize : Commit Returned "<<locHR<<endl;

	switch (locHR) {
		case E_FAIL:
			//debugLog<<"DecideBufferSize : Commit - FAILED "<<endl;
			return locHR;
		case E_POINTER:
			//debugLog<<"DecideBufferSize : Commit - NULL POINTER "<<endl;
			return locHR;
		case E_INVALIDARG:
			//debugLog<<"DecideBufferSize : Commit - INVALID ARG "<<endl;
			return locHR;
		case E_NOTIMPL:
			//debugLog<<"DecideBufferSize : Commit - NOT IMPL"<<endl;
			return locHR;
		case S_OK:
			//debugLog<<"DecideBufferSize : Commit - ** SUCCESS **"<<endl;
			break;
		default:
			//debugLog<<"DecideBufferSize : Commit - UNKNOWN ERROR "<<endl;
			return locHR;
	}

	debugLog<<"Buffer allocated"<<endl;

	return S_OK;
}
HRESULT TheoraDecodeFilter::GetMediaType(int inPosition, CMediaType* outOutputMediaType) 
{
	if (inPosition < 0) {
		return E_INVALIDARG;
	} else if (inPosition < mOutputMediaTypes.size()) {
		
		VIDEOINFOHEADER2* locVideoFormat = (VIDEOINFOHEADER2*)outOutputMediaType->AllocFormatBuffer(sizeof(VIDEOINFOHEADER2));
		FillVideoInfoHeader2(inPosition, locVideoFormat);
		FillMediaType(inPosition, outOutputMediaType, locVideoFormat->bmiHeader.biSizeImage);

		debugLog<<"Get Media Type"<<endl;
		return S_OK;
	} else {
		return VFW_S_NO_MORE_ITEMS;
	}
}

void TheoraDecodeFilter::ResetFrameCount() 
{
	//XTODO::: Maybe not needed
	mFrameCount = 0;
	
}

HRESULT TheoraDecodeFilter::NewSegment(REFERENCE_TIME inStart, REFERENCE_TIME inEnd, double inRate) 
{
	debugLog<<"Resetting frame count"<<endl;
	ResetFrameCount();
	mSegStart = inStart;
	mSegEnd = inEnd;
	mPlaybackRate = inRate;
	return CTransformFilter::NewSegment(inStart, inEnd, inRate);

}

HRESULT TheoraDecodeFilter::Receive(IMediaSample* inInputSample)
{
	BYTE* locBuff = NULL;
	//Get a source poitner into the input buffer
	HRESULT locHR = inInputSample->GetPointer(&locBuff);

	if (locHR != S_OK) {
		//debugLog<<"Receive : Get pointer failed..."<<locHR<<endl;	
		return S_FALSE;
	} else {

		if ((inInputSample->GetActualDataLength() > 0) && ((locBuff[0] & 128) != 0)) {
			//inInputSample->Release();

			//This is a header, so ignore it
			return S_OK;
		}
		//Make a copy of the packet buffer
		BYTE* locNewBuff = new unsigned char[inInputSample->GetActualDataLength()];		//This gets put into a packet.
		memcpy((void*)locNewBuff, (const void*)locBuff, inInputSample->GetActualDataLength());


		REFERENCE_TIME locStart = 0;
		REFERENCE_TIME locEnd = 0;
		inInputSample->GetTime(&locStart, &locEnd);

		debugLog<<"Theora::Receive - Sample: Size = "<<inInputSample->GetActualDataLength()<<" Time: "<<locStart<<" - "<<locEnd<<endl;

		//This packet is given to the decoder or buffered for later
		StampedOggPacket* locPacket = new StampedOggPacket(locNewBuff, inInputSample->GetActualDataLength(), false, false, locStart, locEnd, StampedOggPacket::OGG_END_ONLY);

		//Buffer all packets, even if we are about to send them anyway
		mBufferedPackets.push_back(locPacket);

		if (locEnd < 0) {

			//The packet was ok, but we just aren't going to deliver it yet
			return S_OK;
		} else {
			//Now we have one with a stamp, we can send all the previous ones.
			TheoraDecodeInputPin* locInputPin = (TheoraDecodeInputPin*)m_pInput;
			REFERENCE_TIME locGlobalEnd = locInputPin->convertGranuleToTime(locEnd);
			unsigned long locNumBufferedFrames = mBufferedPackets.size();
			REFERENCE_TIME locGlobalStart = locGlobalEnd - (locNumBufferedFrames * mFrameDuration);

			locStart = locGlobalStart;


			//Offsetting
			REFERENCE_TIME locGlobalOffset = 0;
			//Handle stream offsetting
			if (!locInputPin->getSentStreamOffset() && (locInputPin->getOutputPinInterface() != NULL)) {
				locInputPin->getOutputPinInterface()->notifyStreamBaseTime(locStart);
				locInputPin->setSentStreamOffset(true);
				
			}

			if (locInputPin->getOutputPinInterface() != NULL) {
				locGlobalOffset = locInputPin->getOutputPinInterface()->getGlobalBaseTime();
			}
			
			debugLog<<"Theora::Receive - "<<locNumBufferedFrames<<" frames buffered"<<endl;
			for (unsigned long i = 0; i < locNumBufferedFrames; i++) {
				debugLog<<"Theora::Receive - Processing buffered frame "<<i<<endl;
				bool locIsKeyFrame = mTheoraDecoder->isKeyFrame(mBufferedPackets[i]);
				debugLog<<"Pre theora decode"<<endl;
				yuv_buffer* locYUV = mTheoraDecoder->decodeTheora(mBufferedPackets[i]);		//This accept the packet and deletes it
				debugLog<<"Post theora decode"<<endl;
				locEnd = locStart + mFrameDuration;
				REFERENCE_TIME locAdjustedStart = locStart - mSegStart - locGlobalOffset;
				REFERENCE_TIME locAdjustedEnd = locEnd - mSegStart - locGlobalOffset;

				if (locAdjustedStart < 0) {
					locAdjustedStart = 0;
				}

				if (locAdjustedEnd >= 0) { 
					if (locYUV != NULL) {
						IMediaSample* locOutSample = NULL;
						debugLog<<"Theora::Receive - Pre output sample initialisation"<<endl;
						locHR = InitializeOutputSample(inInputSample, &locOutSample);
						if (locHR != S_OK) {
							//XTODO::: We need to trash our buffered packets
							debugLog<<"Theora::Receive - Output sample initialisation failed"<<endl;
							
							deleteBufferedPacketsAfter(i);
							
							return S_FALSE;
						}
						debugLog<<"Theora::Receive - Output sample initialisation suceeded"<<endl;

						//REFERENCE_TIME locAdjustedStart = (locStart * RATE_DENOMINATOR) / mRateNumerator;
						//REFERENCE_TIME locAdjustedEnd = (locEnd * RATE_DENOMINATOR) / mRateNumerator;


						//Fill the sample info
						if (TheoraDecoded(locYUV, locOutSample, locIsKeyFrame, locAdjustedStart, locAdjustedEnd) != S_OK) {
							
							//XTODO::: We need to trash our buffered packets
							locOutSample->Release();
							deleteBufferedPacketsAfter(i);
							return S_FALSE;
						} else {
							//Deliver the sample
							debugLog<<"Theora::Receive - Delivering: "<<locAdjustedStart<<" to "<<locAdjustedEnd<<(locIsKeyFrame ? "KEYFRAME": " ")<<endl;
							
							locHR = m_pOutput->Deliver(locOutSample);
							ULONG locTempRefCount = locOutSample->Release();
							debugLog<<"Theora::Receive - After deliver refcount = "<<locTempRefCount<<endl;
							debugLog<<"Theora::Receive - Post delivery"<<endl;
							if (locHR != S_OK) {
								//XTODO::: We need to trash our buffered packets
								debugLog<<"Theora::Receive - Delivery failed"<<endl;
								debugLog<<"Theora::Receive - locHR = "<<locHR<<endl;
								//locOutSample->Release();
								deleteBufferedPacketsAfter(i);
								return S_FALSE;
							}
							debugLog<<"Theora::Receive - Delivery Suceeded"<<endl;

						}
					} else {
						//XTODO::: We need to trash our buffered packets
						debugLog<<"locYUV == NULL"<<endl;
						deleteBufferedPacketsAfter(i);
						return S_FALSE;
					}
				}
				locStart = locEnd;
			}

			mBufferedPackets.clear();

			debugLog<<"Leaving receive method with S_OK"<<endl;
			return S_OK;
		}
	}
}

void TheoraDecodeFilter::deleteBufferedPacketsAfter(unsigned long inPacketIndex)
{
	for (size_t i = inPacketIndex + 1; i < mBufferedPackets.size(); i++) {
		delete mBufferedPackets[i];
	}

	mBufferedPackets.clear();
}
HRESULT TheoraDecodeFilter::Transform(IMediaSample* inInputSample, IMediaSample* outOutputSample) 
{
	//debugLog<<"Theora::Transform NOT IMPLEMENTED"<<endl;
	return E_NOTIMPL;
}

HRESULT TheoraDecodeFilter::DecodeToRGB565(yuv_buffer* inYUVBuffer, IMediaSample* outSample, bool inIsKeyFrame, REFERENCE_TIME inStart, REFERENCE_TIME inEnd)
{
	//TODO::: This ineeds to be implemented correctly, currently just outputs a single colour
	BYTE* locBuffer = NULL;
	outSample->GetPointer(&locBuffer);

	const unsigned short RED_SHIFT = 11;
	const unsigned short GREEN_SHIFT = 6;
	const unsigned short BLUE_SHIFT = 0;


	unsigned short* locShortBuffer = (unsigned short*)locBuffer;
	for (unsigned int i = 0; i < mBMIWidth*mBMIHeight; i++) {
		locShortBuffer[i] = (31 << RED_SHIFT);
	}

	REFERENCE_TIME locStart = inStart;
	REFERENCE_TIME locEnd = inEnd;

	BOOL locIsKeyFrame = FALSE;
	if (inIsKeyFrame) {
		locIsKeyFrame = TRUE;
	};
	SetSampleParams(outSample, mBMIFrameSize, &locStart, &locEnd, locIsKeyFrame);

	return S_OK;
}

HRESULT TheoraDecodeFilter::DecodeToRGB24(yuv_buffer* inYUVBuffer, IMediaSample* outSample, bool inIsKeyFrame, REFERENCE_TIME inStart, REFERENCE_TIME inEnd)
{
	//TODO::: This ineeds to be implemented correctly, currently just outputs a single colour
	BYTE* locBuffer = NULL;
	outSample->GetPointer(&locBuffer);

	const unsigned short RED_SHIFT = 16;
	const unsigned short GREEN_SHIFT = 8;
	const unsigned short BLUE_SHIFT = 0;


	unsigned long* locLongBuffer = (unsigned long*)locBuffer;
	for (unsigned int i = 0; i < mBMIWidth*mBMIHeight; i++) {
		locLongBuffer[i] = (255 << RED_SHIFT);
	}

	REFERENCE_TIME locStart = inStart;
	REFERENCE_TIME locEnd = inEnd;

	BOOL locIsKeyFrame = FALSE;
	if (inIsKeyFrame) {
		locIsKeyFrame = TRUE;
	};
	SetSampleParams(outSample, mBMIFrameSize, &locStart, &locEnd, locIsKeyFrame);

	return S_OK;
}

HRESULT TheoraDecodeFilter::DecodeToYUY2(yuv_buffer* inYUVBuffer, IMediaSample* outSample, bool inIsKeyFrame, REFERENCE_TIME inStart, REFERENCE_TIME inEnd) 
{
	BYTE* locBuffer = NULL;
	outSample->GetPointer(&locBuffer);

	//Get the stride values and offsets
	long locYStride = inYUVBuffer->y_stride;
	long locUVStride = inYUVBuffer->uv_stride;

⌨️ 快捷键说明

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