예제 #1
0
//-------------------------------------------------------------------
// Write the sample 
//
HRESULT VidWriter::writeFrame(BYTE *pData)
{
	HRESULT hr;
    IMFSample *pSample = NULL;
    const DWORD cbBuffer = 4 * m_width * m_height;

	// Unlock the buffer
    if (m_pBuffer) m_pBuffer->Unlock();	

	// Set the data length of the buffer
    hr = m_pBuffer->SetCurrentLength(cbBuffer);
	if (FAILED(hr)) goto done;	

    // Create a media sample and add the buffer to it
    hr = MFCreateSample(&pSample);
	if (FAILED(hr)) goto done;
	hr = pSample->AddBuffer(m_pBuffer);
	if (FAILED(hr)) goto done;

    // Set the time stamp and the duration
    hr = pSample->SetSampleTime(m_rtStart);
	if (FAILED(hr)) goto done;
	hr = pSample->SetSampleDuration(m_frametime);
	if (FAILED(hr)) goto done;

	// increment the time stamp
	m_rtStart += m_frametime;

    // Send the sample to the Sink Writer
    hr = m_pWriter->WriteSample(m_streamIndex, pSample);

done:
    SafeRelease(&pSample);
    return hr;
}
예제 #2
0
IMFMediaBuffer * CDecWMV9MFT::CreateMediaBuffer(const BYTE * pData, DWORD dwDataLen)
{
  HRESULT hr;
  IMFMediaBuffer *pBuffer = nullptr;
  hr = MF.CreateAlignedMemoryBuffer(dwDataLen, MF_16_BYTE_ALIGNMENT, &pBuffer);
  if (FAILED(hr)) {
    DbgLog((LOG_ERROR, 10, L"Unable to allocate MF Media Buffer, hr: 0x%x", hr));
    goto done;
  }

  BYTE * pOutBuffer = nullptr;
  hr = pBuffer->Lock(&pOutBuffer, NULL, NULL);
  if (FAILED(hr)) {
    SafeRelease(&pBuffer);
    DbgLog((LOG_ERROR, 10, L"Unable to lock MF Media Buffer, hr: 0x%x", hr));
    goto done;
  }

  memcpy(pOutBuffer, pData, dwDataLen);

  pBuffer->Unlock();
  pBuffer->SetCurrentLength(dwDataLen);

done:
  return pBuffer;
}
예제 #3
0
HRESULT VideoEncoder::WriteTransitionSample(UINT64 sampleDuration, TransitionBase* pTransition, DWORD streamIndex, LONGLONG* startTime)
{
	HRESULT hr = S_OK;
	IMFMediaBuffer* pMediaBuffer = nullptr;
	BYTE* pFrameBuffer = nullptr;
	IMFSample* pSample = nullptr;
	BYTE* pOutputFrame = nullptr;

	for (DWORD i = 0; i < sampleDuration; i++)
    {
		CheckHR(MFCreateMemoryBuffer(this->m_frameBufferSize, &pMediaBuffer));
		pMediaBuffer->Lock(&pFrameBuffer, nullptr, nullptr);
		float time = (float)i / (float)sampleDuration;
		pOutputFrame = pTransition->GetOutputFrame(time);
		CheckHR(MFCopyImage(pFrameBuffer, this->m_frameStride, pOutputFrame, this->m_frameStride, this->m_frameStride, this->m_frameHeight));
		CheckHR(pMediaBuffer->Unlock());
		CheckHR(pMediaBuffer->SetCurrentLength(this->m_frameBufferSize));
		CheckHR(MFCreateSample(&pSample));
		CheckHR(pSample->AddBuffer(pMediaBuffer));
		CheckHR(pSample->SetSampleTime(*startTime));
		CheckHR(pSample->SetSampleDuration(this->GetFrameDuration()));
		CheckHR(this->m_pSinkWriter->WriteSample(streamIndex, pSample));
		(*startTime) += this->GetFrameDuration();

		// 释放示例资源.
		SafeRelease(&pMediaBuffer);
		SafeRelease(&pSample);
		if (pOutputFrame != nullptr)
		{
			delete pOutputFrame;
			pOutputFrame = nullptr;
		}
	}

cleanup:
	if (!SUCCEEDED(hr))
	{
		DWORD error = GetLastError();
		this->m_logFileStream << "意外错误: " << error << endl;
	}
	SafeRelease(&pMediaBuffer);
	SafeRelease(&pSample);
	if (pOutputFrame != nullptr)
	{
		delete pOutputFrame;
		pOutputFrame = nullptr;
	}
	return hr;
}
HRESULT CASFManager::ReadDataIntoBuffer(
    IMFByteStream *pStream,     // Pointer to the byte stream.
    DWORD cbOffset,             // Offset at which to start reading
    DWORD cbToRead,             // Number of bytes to read
    IMFMediaBuffer **ppBuffer   // Receives a pointer to the buffer.
    )
{
    HRESULT hr = S_OK;
    BYTE *pData = NULL;
    DWORD cbRead = 0;   // Actual amount of data read

    IMFMediaBuffer *pBuffer = NULL;

    // Create the media buffer. This function allocates the memory.
    CHECK_HR(hr = MFCreateMemoryBuffer(cbToRead, &pBuffer));

    // Access the buffer.
    CHECK_HR(hr = pBuffer->Lock(&pData, NULL, NULL));

    //Set the offset
    CHECK_HR(hr = pStream->SetCurrentPosition(cbOffset));

    // Read the data from the byte stream.
    CHECK_HR(hr = pStream->Read(pData, cbToRead, &cbRead));

    CHECK_HR(hr = pBuffer->Unlock());
    pData = NULL;

    // Update the size of the valid data.
    CHECK_HR(hr = pBuffer->SetCurrentLength(cbRead));

    // Return the pointer to the caller.
    *ppBuffer = pBuffer;
    (*ppBuffer)->AddRef();

    TRACE((L"Read data from the ASF file into a media buffer.\n"));

done:

    LOG_MSG_IF_FAILED(L"CASFManager::ReadDataIntoBuffer failed.\n", hr);
    
    if (pData)
    {
        pBuffer->Unlock();
    }
    SAFE_RELEASE(pBuffer);
    return hr;
}
예제 #5
0
IMFSample* create_sample(void *data, DWORD len, DWORD alignment, LONGLONG duration) {
	HRESULT hr = S_OK;
	IMFMediaBuffer *buf = NULL;
	IMFSample *sample = NULL;

	hr = MFCreateSample(&sample);
	if (FAILED(hr)) {
		ReportError(L"Unable to allocate a sample", hr);
		return NULL;
	}
	// Yes, the argument for alignment is the actual alignment - 1
	hr = MFCreateAlignedMemoryBuffer(len, alignment - 1, &buf);
	if (FAILED(hr)) { 
		ReportError(L"Unable to allocate a memory buffer for sample", hr);
		return NULL;
	}
	if (data)
	{
		BYTE *buffer;
		// lock the MediaBuffer
		// this is actually not a thread-safe lock
		hr = buf->Lock(&buffer, NULL, NULL);
		if (FAILED(hr))
		{
			SafeRelease(&sample);
			SafeRelease(&buf);
			return NULL;
		}

		memcpy(buffer, data, len);

		buf->SetCurrentLength(len);
		buf->Unlock();
	}

	sample->AddBuffer(buf);
	hr = sample->SetSampleDuration(duration);
	SafeRelease(&buf);
	return sample;
}
// Process any pending output from the decoder (until all output is
// processed).
//
// Thread context: decoder thread
bool DecoderMF::DoProcessOutput()
{
	bool						ret = false;
	HRESULT						hr;
	MFT_OUTPUT_DATA_BUFFER		mftDataBuffer;
	DWORD						mftStatus;
	bool						moreOutput;

	if (m_outputSample == NULL)
	{
		if (! CreateOutputSample())
			return false;
	}

	do
	{
		// Since we could be looping inside this method for a while,
		// if a whole stack of frames arrive at once, we want to exit
		// if the thread has been asked to die. So check on each
		// iteration of the loop.
		if (! m_decoderThreadRunning)
			return true;

		moreOutput = false;

		mftDataBuffer.dwStreamID = 0;
		mftDataBuffer.pSample = m_outputSample;
		mftDataBuffer.dwStatus = 0;
		mftDataBuffer.pEvents = NULL;
		mftStatus = 0;

		// Looks like we have to reset the sample before use:
		IMFMediaBuffer* mediaBuffer;
		hr = m_outputSample->GetBufferByIndex(0, &mediaBuffer);
		if (FAILED(hr))
			goto bail;

		hr = mediaBuffer->SetCurrentLength(0);
		if (FAILED(hr))
			goto bail;

		mediaBuffer->Release();

		hr = m_h264Decoder->ProcessOutput(0, 1, &mftDataBuffer, &mftStatus);

		// Check return code
		if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
			break;
		EnterCriticalSection(&m_criticalSection);
		if (hr == MF_E_TRANSFORM_STREAM_CHANGE || !m_previewConfigured)
		{
			// If the output format has changed, we need to handle
			// the stream change. This will happen after the first
			// few packets have been delivered.
			moreOutput = HandleStreamChange();
			LeaveCriticalSection(&m_criticalSection);
			if (!moreOutput)
				goto bail;
			continue;
		}
		LeaveCriticalSection(&m_criticalSection);
		if (FAILED(hr))
			goto bail;

		if (mftDataBuffer.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE)
			moreOutput = true;

		// Process each event:
		if (mftDataBuffer.pEvents != NULL)
		{
			DWORD numElements;
			hr = mftDataBuffer.pEvents->GetElementCount(&numElements);
			if (SUCCEEDED(hr))
			{
				for (DWORD i = 0; i < numElements; i++)
				{
					IUnknown* iunk = NULL;

					hr = mftDataBuffer.pEvents->GetElement(i, &iunk);
					if (SUCCEEDED(hr))
					{
						IMFMediaEvent* mediaEvent = NULL;
						hr = iunk->QueryInterface(IID_IMFMediaEvent, (void**)&mediaEvent);

						if (SUCCEEDED(hr))
						{
							OutputDebugString(_T("FIXME: process event!\n"));

							mediaEvent->Release();
						}

						iunk->Release();
					}
				}
			}

			mftDataBuffer.pEvents = NULL;
		}

		// Process sample:
		if (mftDataBuffer.pSample != NULL)
		{
			IMFMediaBuffer* mediaBuffer;
			hr = mftDataBuffer.pSample->GetBufferByIndex(0, &mediaBuffer);
			if (FAILED(hr))
				goto bail;

			EnterCriticalSection(&m_criticalSection);

				if (m_previewWindow != NULL && m_previewConfigured)
					m_previewWindow->DrawFrame(mediaBuffer);

			LeaveCriticalSection(&m_criticalSection);

			mediaBuffer->Release();
		}
	} while(moreOutput);

	ret = true;

bail:
	if (ret == false)
		OutputDebugString(_T("ERROR: failed to process output...\n"));

	return ret;
}
// Process the incomming NAL from the queue: wraps it up into a
// IMFMediaSample, sends it to the decoder.
//
// Thread context: decoder thread
bool DecoderMF::DoProcessInputNAL(IBMDStreamingH264NALPacket* nalPacket)
{
	bool				ret = false;
	HRESULT				hr;
	IMFMediaBuffer*		newBuffer = NULL;
	BYTE*				newBufferPtr;
	void*				nalPacketPtr;
	//
	IMFSample*			newSample = NULL;
	ULONGLONG			nalPresentationTime;
	const BYTE			nalPrefix[] = {0, 0, 0, 1};

	// Get a pointer to the NAL data
	hr = nalPacket->GetBytes(&nalPacketPtr);
	if (FAILED(hr))
		goto bail;

	// Create the MF media buffer (+ 4 bytes for the NAL Prefix (0x00 0x00 0x00 0x01)
	// which MF requires.
	hr = MFCreateMemoryBuffer(nalPacket->GetPayloadSize()+4, &newBuffer);
	if (FAILED(hr))
		goto bail;

	// Lock the MF media buffer
	hr = newBuffer->Lock(&newBufferPtr, NULL, NULL);
	if (FAILED(hr))
		goto bail;

	// Copy the prefix and the data
	memcpy(newBufferPtr, nalPrefix, 4);
	memcpy(newBufferPtr+4, nalPacketPtr, nalPacket->GetPayloadSize());

	// Unlock the MF media buffer
	hr = newBuffer->Unlock();
	if (FAILED(hr))
		goto bail;

	// Update the current length of the MF media buffer
	hr = newBuffer->SetCurrentLength(nalPacket->GetPayloadSize()+4);
	if (FAILED(hr))
		goto bail;

	// We now have a IMFMediaBuffer with the contents of the NAL
	// packet. We now construct a IMFSample with the buffer
	hr = MFCreateSample(&newSample);
	if (FAILED(hr))
		goto bail;

	hr = newSample->AddBuffer(newBuffer);
	if (FAILED(hr))
		goto bail;

	// Get the presentation (display) time in 100-nanosecond units
	// TODO: this is pretty meaningless without setting the start time.
	hr = nalPacket->GetDisplayTime(1000 * 1000 * 10, &nalPresentationTime);
	if (FAILED(hr))
		goto bail;

	// Set presentation time on the sample
	hr = newSample->SetSampleTime(nalPresentationTime);
	if (FAILED(hr))
		goto bail;

	// Now parse it to the decoder
	for (;;)
	{
		hr = m_h264Decoder->ProcessInput(0, newSample, 0);
		if (hr == S_OK)
			break;
		if (hr != MF_E_NOTACCEPTING || DoProcessOutput() == false)
			goto bail;
	}

	ret = true;

bail:
	if (newBuffer != NULL)
		newBuffer->Release();

	if (newSample != NULL)
		newSample->Release();

	return ret;
}
예제 #8
0
HRESULT WavStream::CreateAudioSample(IMFSample **ppSample)
{
    HRESULT hr = S_OK;

    IMFMediaBuffer *pBuffer = NULL;
    IMFSample *pSample = NULL;

    DWORD       cbBuffer = 0;
    BYTE        *pData = NULL;
    LONGLONG    duration = 0;

    // Start with one second of data, rounded up to the nearest block.
    cbBuffer = AlignUp<DWORD>(m_pRiff->Format()->nAvgBytesPerSec, m_pRiff->Format()->nBlockAlign);

    // Don't request any more than what's left.
    cbBuffer = min(cbBuffer, m_pRiff->BytesRemainingInChunk());

    // Create the buffer.
    hr = MFCreateMemoryBuffer(cbBuffer, &pBuffer);

    // Get a pointer to the buffer memory.
    if (SUCCEEDED(hr))
    {   
        hr = pBuffer->Lock(&pData, NULL, NULL);
    }

    // Fill the buffer
    if (SUCCEEDED(hr))
    {   
        hr = m_pRiff->ReadDataFromChunk(pData, cbBuffer);
    }

    // Unlock the buffer.
    if (SUCCEEDED(hr))
    {   
        hr = pBuffer->Unlock();
        pData = NULL;
    }

    // Set the size of the valid data in the buffer.
    if (SUCCEEDED(hr))
    {   
        hr = pBuffer->SetCurrentLength(cbBuffer);
    }

    // Create a new sample and add the buffer to it.
    if (SUCCEEDED(hr))
    {   
        hr = MFCreateSample(&pSample);
    }

    if (SUCCEEDED(hr))
    {   
        hr = pSample->AddBuffer(pBuffer);
    }

    // Set the time stamps, duration, and sample flags.
    if (SUCCEEDED(hr))
    {   
        hr = pSample->SetSampleTime(m_rtCurrentPosition);
    }

    if (SUCCEEDED(hr))
    {   
        duration = AudioDurationFromBufferSize(m_pRiff->Format(), cbBuffer);
        hr = pSample->SetSampleDuration(duration);
    }

    // Set the discontinuity flag.
    if (SUCCEEDED(hr))
    {   
        if (m_discontinuity)
        {
            hr = pSample->SetUINT32(MFSampleExtension_Discontinuity, TRUE);
        }
    }

    if (SUCCEEDED(hr))
    {   
        // Update our current position.
        m_rtCurrentPosition += duration;

        // Give the pointer to the caller.
        *ppSample = pSample;
        (*ppSample)->AddRef();
    }

    if (pData && pBuffer)
    {
        hr = pBuffer->Unlock();
    }

    SafeRelease(&pBuffer);
    SafeRelease(&pSample);
    return hr;
}
예제 #9
0
void VideoCompressor::AudioSample32Bit2Channel(float *Samples, UINT FrameCount, UINT64 CaptureStartTime)
{
    //double TimeInSeconds = _Clock->Elapsed();

    const UINT SamplesPerSecond = 44100;
    const UINT ChannelCount = 2;
    const UINT SampleCount = FrameCount * ChannelCount;
    const UINT BitsPerSample = 16;
    const UINT BufferLength = BitsPerSample / 8 * ChannelCount * FrameCount;
    const LONGLONG SampleDuration = LONGLONG(FrameCount) * LONGLONG(10000000) / SamplesPerSecond; // in hns
    
    //
    // Write some data
    //
    IMFSample *spSample;
    IMFMediaBuffer *spBuffer;
    BYTE *pbBuffer = NULL;

    //
    // Create a media sample
    //

    HRESULT hr = MFCreateSample( &spSample );
    hr = spSample->SetSampleDuration( SampleDuration );
    
    //hr = spSample->SetSampleTime( LONGLONG( TimeInSeconds * 10000000.0 ) );
    
    //CaptureStartTime = 10,000,000 * t / f;
    //t = CaptureStartTime * f / 10,000,000
    LONGLONG FileStartCounter = _Clock->StartTime();
    LONGLONG CaptureStartCounter = CaptureStartTime * _Clock->TicksPerSecond() / LONGLONG(10000000);
    hr = spSample->SetSampleTime( ( CaptureStartCounter - FileStartCounter ) * LONGLONG(10000000) / _Clock->TicksPerSecond() );

    //
    // Add a media buffer filled with random data
    //

    hr = MFCreateMemoryBuffer( BufferLength, &spBuffer );
    hr = spBuffer->SetCurrentLength( BufferLength );
    hr = spSample->AddBuffer( spBuffer );

    hr = spBuffer->Lock( &pbBuffer, NULL, NULL );
    __int16 *OutputAudioBuffer = (__int16 *)pbBuffer;
    for(UINT SampleIndex = 0; SampleIndex < SampleCount; SampleIndex++)
    {
        //
        // Floats are in the range -1 to 1
        //
        OutputAudioBuffer[SampleIndex] = int(Samples[SampleIndex] * 32768.0f);
    }
    hr = spBuffer->Unlock();

    //
    // Write the media sample
    //
    hr = _Writer->WriteSample( 1, spSample );
    PersistentAssert(SUCCEEDED(hr), "WriteSample failed");

    spSample->Release();
    spBuffer->Release();
}