Esempio n. 1
0
HRESULT
WWMFResampler::GetSampleDataFromMFTransform(WWMFSampleData *sampleData_return)
{
    HRESULT hr = S_OK;
    IMFMediaBuffer *pBuffer = NULL;
    MFT_OUTPUT_STREAM_INFO streamInfo;
    MFT_OUTPUT_DATA_BUFFER outputDataBuffer;
    DWORD dwStatus;
    memset(&streamInfo, 0, sizeof streamInfo);
    memset(&outputDataBuffer, 0, sizeof outputDataBuffer);

    assert(sampleData_return);
    assert(NULL == sampleData_return->data);

    HRG(MFCreateSample(&(outputDataBuffer.pSample)));
    HRG(MFCreateMemoryBuffer(sampleData_return->bytes, &pBuffer));
    HRG(outputDataBuffer.pSample->AddBuffer(pBuffer));
    outputDataBuffer.dwStreamID = 0;
    outputDataBuffer.dwStatus = 0;
    outputDataBuffer.pEvents = NULL;

    hr = m_pTransform->ProcessOutput(0, 1, &outputDataBuffer, &dwStatus);
    if (FAILED(hr)) {
        goto end;
    }

    HRG(ConvertMFSampleToWWSampleData(outputDataBuffer.pSample, sampleData_return));

end:
    SafeRelease(&pBuffer);
    SafeRelease(&outputDataBuffer.pSample);
    return hr;
}
HRESULT CMediaController::AddToAudioTestSample (IMFSample *pSample)
{
    if(!pSample)
    {
        return E_INVALIDARG;
    }

    HRESULT hr = S_OK;

    IMFMediaBuffer* pBuffer = NULL;

    if (! m_pAudioTestSample)
    {
        CHECK_HR ( hr = MFCreateSample(&m_pAudioTestSample));
    }
    
    CHECK_HR (hr = pSample->ConvertToContiguousBuffer(&pBuffer)); 

    CHECK_HR (hr =  m_pAudioTestSample->AddBuffer(pBuffer));

    this->m_fHasTestMedia = TRUE;

done:

    SAFE_RELEASE (pBuffer);
    return hr;
}
Esempio n. 3
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;
}
Esempio n. 4
0
HRESULT
WWMFResampler::ConvertWWSampleDataToMFSample(WWMFSampleData &sampleData, IMFSample **ppSample)
{
    HRESULT hr = S_OK;
    IMFSample *pSample = NULL;
#ifdef USE_ATL
    CComPtr<IMFMediaBuffer> spBuffer;
#else // USE_ATL
    IMFMediaBuffer *spBuffer = NULL;
#endif // USE_ATL
    BYTE  *pByteBufferTo = NULL;
    //LONGLONG hnsSampleDuration;
    //LONGLONG hnsSampleTime;
    int frameCount;

    assert(ppSample);
    *ppSample = NULL;

    HRG(MFCreateMemoryBuffer(sampleData.bytes, &spBuffer));
    HRG(spBuffer->Lock(&pByteBufferTo, NULL, NULL));

    memcpy(pByteBufferTo, sampleData.data, sampleData.bytes);

    pByteBufferTo = NULL;
    HRG(spBuffer->Unlock());
    HRG(spBuffer->SetCurrentLength(sampleData.bytes));

    HRG(MFCreateSample(&pSample));
    HRG(pSample->AddBuffer(spBuffer));

    frameCount = sampleData.bytes / m_inputFormat.FrameBytes();
    /*
    hnsSampleDuration = (LONGLONG)(10.0 * 1000 * 1000 * frameCount        / m_inputFormat.sampleRate);
    hnsSampleTime     = (LONGLONG)(10.0 * 1000 * 1000 * m_inputFrameTotal / m_inputFormat.sampleRate);
    HRG(pSample->SetSampleDuration(hnsSampleDuration));
    HRG(pSample->SetSampleTime(hnsSampleTime));
    */

    m_inputFrameTotal += frameCount;

    // succeeded.

    *ppSample = pSample;
    pSample = NULL; //< prevent release

end:
    SafeRelease(&pSample);
#ifndef USE_ATL
    SafeRelease(&spBuffer);
#endif // uSE_ATL
    return hr;
}
Esempio n. 5
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;
}
// This is called each time the stream format has changed, and
// deletes and then re-creates the output sample (IMFSample*),
// according to the required format.
//
// Thread context: decoder thread
bool DecoderMF::CreateOutputSample()
{
	bool				ret = false;
	HRESULT				hr;
	MFT_OUTPUT_STREAM_INFO outputStreamInfo;
	IMFMediaBuffer*		mediaBuffer = NULL;

	if (m_outputSample != NULL)
	{
		m_outputSample->Release();
		m_outputSample = NULL;
	}

	hr = MFCreateSample(&m_outputSample);
	if (FAILED(hr))
		goto bail;

	hr = m_h264Decoder->GetOutputStreamInfo(0, &outputStreamInfo);
	if (FAILED(hr))
		goto bail;

	hr = MFCreateAlignedMemoryBuffer(outputStreamInfo.cbSize, MF_16_BYTE_ALIGNMENT, &mediaBuffer);
	if (FAILED(hr))
		goto bail;

	hr = m_outputSample->AddBuffer(mediaBuffer);
	if (FAILED(hr))
		goto bail;

	ret = true;
	
bail:
	if (ret == false)
	{
		if (m_outputSample != NULL)
		{
			m_outputSample->Release();
			m_outputSample = NULL;
		}
	}

	if (mediaBuffer)
		mediaBuffer->Release();

	return ret;
}
Esempio n. 7
0
HRESULT
WMFAACDecoder::CreateInputSample(const uint8_t* aData,
                                 uint32_t aDataSize,
                                 Microseconds aTimestamp,
                                 IMFSample** aOutSample)
{
  HRESULT hr;
  CComPtr<IMFSample> sample = nullptr;
  hr = MFCreateSample(&sample);
  ENSURE(SUCCEEDED(hr), hr);

  CComPtr<IMFMediaBuffer> buffer = nullptr;
  int32_t bufferSize = std::max<uint32_t>(uint32_t(mInputStreamInfo.cbSize), aDataSize);
  UINT32 alignment = (mInputStreamInfo.cbAlignment > 1) ? mInputStreamInfo.cbAlignment - 1 : 0;
  hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer);
  ENSURE(SUCCEEDED(hr), hr);

  DWORD maxLength = 0;
  DWORD currentLength = 0;
  BYTE* dst = nullptr;
  hr = buffer->Lock(&dst, &maxLength, &currentLength);
  ENSURE(SUCCEEDED(hr), hr);

  // Copy data into sample's buffer.
  memcpy(dst, aData, aDataSize);

  hr = buffer->Unlock();
  ENSURE(SUCCEEDED(hr), hr);

  hr = buffer->SetCurrentLength(aDataSize);
  ENSURE(SUCCEEDED(hr), hr);

  hr = sample->AddBuffer(buffer);
  ENSURE(SUCCEEDED(hr), hr);

  hr = sample->SetSampleTime(UsecsToHNs(aTimestamp));
  ENSURE(SUCCEEDED(hr), hr);

  *aOutSample = sample.Detach();

  return S_OK;
}
Esempio n. 8
0
HRESULT
WMFAACDecoder::CreateOutputSample(IMFSample** aOutSample)
{
  HRESULT hr;
  CComPtr<IMFSample> sample = nullptr;
  hr = MFCreateSample(&sample);
  ENSURE(SUCCEEDED(hr), hr);

  CComPtr<IMFMediaBuffer> buffer = nullptr;
  int32_t bufferSize = mOutputStreamInfo.cbSize;
  UINT32 alignment = (mOutputStreamInfo.cbAlignment > 1) ? mOutputStreamInfo.cbAlignment - 1 : 0;
  hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer);
  ENSURE(SUCCEEDED(hr), hr);

  hr = sample->AddBuffer(buffer);
  ENSURE(SUCCEEDED(hr), hr);

  *aOutSample = sample.Detach();

  return S_OK;
}
Esempio n. 9
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 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;
}
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;
}
Esempio n. 12
0
void MfVideoEncoder::WriteFrame(uint8_t* data, int stride) {
	CComPtr<IMFSample> pSample;
	CComPtr<IMFMediaBuffer> pBuffer;

	const LONG cbWidth = 4 * mWidth;
	const DWORD cbBuffer = cbWidth * mHeight;

	BYTE *pData = NULL;

	// Create a new memory buffer.
	HRESULT hr = MFCreateMemoryBuffer(cbBuffer, &pBuffer);

	// Lock the buffer and copy the video frame to the buffer.
	if (SUCCEEDED(hr))
	{
		hr = pBuffer->Lock(&pData, NULL, NULL);
	}
	if (SUCCEEDED(hr))
	{
		hr = MFCopyImage(
			pData,                      // Destination buffer.
			cbWidth,                    // Destination stride.
			(BYTE*)data,    // First row in source image.
			stride,                    // Source stride.
			cbWidth,                    // Image width in bytes.
			mHeight                // Image height in pixels.
			);
	}
	if (pBuffer)
	{
		pBuffer->Unlock();
	}

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

	// Create a media sample and add the buffer to the sample.
	if (SUCCEEDED(hr))
	{
		hr = MFCreateSample(&pSample);
	}
	if (SUCCEEDED(hr))
	{
		hr = pSample->AddBuffer(pBuffer);
	}

	// Set the time stamp and the duration.
	if (SUCCEEDED(hr))
	{
		hr = pSample->SetSampleTime(mCurrentTime);
	}
	if (SUCCEEDED(hr))
	{
		hr = pSample->SetSampleDuration(mFrameTime);
	}

	// Send the sample to the Sink Writer.
	if (SUCCEEDED(hr))
	{
		hr = mSinkWriter->WriteSample(mStreamIndex, pSample);
	}

	if (!SUCCEEDED(hr)) {
		throw TempleException("Unable to write video frame: {}", hr);
	}

	mCurrentTime += mFrameTime;

}
Esempio n. 13
0
	video_writer::video_writer(
		std::wstring& target_path, IMFMediaTypePtr& audio_media_type, ID3D11DeviceContext2Ptr& context, ID3D11Texture2DPtr& texture
		/*, unsigned int width, unsigned int height*/) : target_path_(target_path), audio_media_type_(audio_media_type), context_(context), texture_(texture)
	{
		D3D11_TEXTURE2D_DESC desc = {};
		texture->GetDesc(&desc);
		width_ = desc.Width;
		height_ = desc.Height;

		const unsigned int WIDTH = width_;
		const unsigned int HEIGHT = height_;
		const unsigned int BITRATE = 3000000;
		const unsigned int ASPECT_NUM = 1;
		const unsigned int ASPECT_DENOM = 1;
		const unsigned long  BPP_IN = 32;
		const unsigned long cbMaxLength = WIDTH * HEIGHT * BPP_IN / 8;
		const unsigned int ONE_SECOND = RATE_NUM / RATE_DENOM;
		const unsigned int FRAME_NUM = 10 * ONE_SECOND;

		samples_per_second = 44100;
		average_bytes_per_second = 24000;
		channel_count = 2;
		bits_per_sample = 16;

		// 入力ストリームから SinkWriterを生成する

		CHK(MFCreateFile(MF_FILE_ACCESSMODE::MF_ACCESSMODE_WRITE, MF_FILE_OPENMODE::MF_OPENMODE_DELETE_IF_EXIST, MF_FILE_FLAGS::MF_FILEFLAGS_NONE, target_path.c_str(), &byte_stream_));

		CHK(MFCreateAttributes(&attr_, 10));
		CHK(attr_->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, true));
		CHK(attr_->SetUINT32(MF_READWRITE_DISABLE_CONVERTERS, false));
		CHK(attr_->SetUINT32(MF_SINK_WRITER_DISABLE_THROTTLING, true));




		IMFSinkWriterPtr sinkWriter;

		CHK(MFCreateSinkWriterFromURL(L".mp4", byte_stream_.Get(), attr_.Get(), &sinkWriter));
		CHK(sinkWriter.As(&sink_writer_));
		//CHK(MFCreateSinkWriterFromURL(L".mp4", byte_stream_.Get(), attr_.Get(), &sink_writer_));



		//   
		// 出力メディアタイプのセットアップ   
		//   

		// ビデオ

		CHK(MFCreateMediaType(&media_type_out_));
		CHK(media_type_out_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
		CHK(media_type_out_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264));
		CHK(media_type_out_->SetUINT32(MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_Main));
		//CHK(media_type_out_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32));   
		CHK(media_type_out_->SetUINT32(MF_MT_AVG_BITRATE, BITRATE));
		CHK(media_type_out_->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive));
		CHK(MFSetAttributeSize(media_type_out_.Get(), MF_MT_FRAME_SIZE, WIDTH, HEIGHT));
		CHK(MFSetAttributeRatio(media_type_out_.Get(), MF_MT_FRAME_RATE, RATE_NUM, RATE_DENOM));
		CHK(MFSetAttributeRatio(media_type_out_.Get(), MF_MT_PIXEL_ASPECT_RATIO, ASPECT_NUM, ASPECT_DENOM));

		CHK(sink_writer_->AddStream(media_type_out_.Get(), &stream_index_));




		IMFTransformPtr mft;
		//IMFRateSupportPtr ptr;

		//CHK(sink_writer_->GetServiceForStream(stream_index_, MF_RATE_CONTROL_SERVICE, __uuidof(IMFRateSupport), &ptr));

		// オーディオ

		CHK(MFCreateMediaType(&media_type_out_audio_));
		CHK(media_type_out_audio_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio));
		CHK(media_type_out_audio_->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC));
		CHK(media_type_out_audio_->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, samples_per_second));
		CHK(media_type_out_audio_->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, bits_per_sample));
		CHK(media_type_out_audio_->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, channel_count));
		CHK(media_type_out_audio_->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, average_bytes_per_second));
		CHK(media_type_out_audio_->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1));
		CHK(sink_writer_->AddStream(media_type_out_audio_.Get(), &stream_index_audio_));

		//   
		// 入力メディアタイプのセットアップ  
		//   

		// ビデオ

		CHK(MFCreateMediaType(&media_type_in_));
		CHK(media_type_in_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video));
		CHK(media_type_in_->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32));
		CHK(media_type_in_->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive));
		CHK(MFSetAttributeSize(media_type_in_.Get(), MF_MT_FRAME_SIZE, WIDTH, HEIGHT));
		CHK(MFSetAttributeRatio(media_type_in_.Get(), MF_MT_FRAME_RATE, RATE_NUM, RATE_DENOM));
		CHK(MFSetAttributeRatio(media_type_in_.Get(), MF_MT_PIXEL_ASPECT_RATIO, ASPECT_NUM, ASPECT_DENOM));

		// エンコーダーのセットアップ
		//prop_variant prop;
		//IPropertyStorePtr pPropertyStore;
		//IMFAttributesPtr pEncoderParameters;

		//CHK(PSCreateMemoryPropertyStore(__uuidof(IPropertyStore), (void**) &pPropertyStore));

		//prop.value().vt = VT_BOOL;
		//prop.value().boolVal = VARIANT_FALSE;
		//CHK(pPropertyStore->SetValue(MFPKEY_VBRENABLED, prop.value()));
		//prop.value().vt = VT_I4;
		//prop.value().lVal = 100;
		//CHK(pPropertyStore->SetValue(MFPKEY_VBRQUALITY, prop.value()));

		//CHK(MFCreateAttributes(&pEncoderParameters, 5));
		//CHK(attr_->SetUnknown(MF_SINK_WRITER_ENCODER_CONFIG, pPropertyStore.Get()));

		CHK(sink_writer_->SetInputMediaType(stream_index_, media_type_in_.Get(), nullptr /*pEncoderParameters.Get()*/));

		// オーディオ

		CHK(MFCreateMediaType(&media_type_in_audio_));
		//CHK(media_type_in_audio_->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio));
		//CHK(media_type_in_audio_->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM));
		//CHK(media_type_in_audio_->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, bits_per_sample));
		//CHK(media_type_in_audio_->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, samples_per_second));
		//CHK(media_type_in_audio_->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, channel_count));
		audio_media_type_->CopyAllItems(media_type_in_audio_.Get());
		CHK(sink_writer_->SetInputMediaType(stream_index_audio_, media_type_in_audio_.Get(), NULL));

		// ハードウェアエンコーダが使われているかの確認

		{
			IMFTransformPtr transform;
			ICodecAPIPtr codec;
			GUID guid;

			CHK(sink_writer_->GetServiceForStream(stream_index_, GUID_NULL, IID_IMFTransform, &transform));

			IMFAttributesPtr attributes;
			CHK(transform->GetAttributes(&attributes));
			UINT32 l = 0;
			std::wstring str;
			bool use_hw = false;
			HRESULT hr = attributes->GetStringLength(MFT_ENUM_HARDWARE_URL_Attribute, &l);
			if (SUCCEEDED(hr))
			{
				str.reserve(l + 1);
				hr = attributes->GetString(MFT_ENUM_HARDWARE_URL_Attribute, (LPWSTR) str.data(), l + 1, &l);
				if (SUCCEEDED(hr)){
					use_hw = true;
					DOUT2(L"/////// HARDWARE ENCODE IS USED. ////\n");
				}
			}
		}

		//   
		// 出力開始  
		//   

		CHK(sink_writer_->BeginWriting());

		//   
		// メディア・サンプルの作成   
		//   

		CHK(MFCreateSample(&sample_));
		video_sample_time_ = 0;
		CHK(sample_->SetSampleDuration(hnsSampleDuration));

		//   
		// メディア・バッファの生成と、メディア・サンプルへの追加    
		//   

		CHK(MFCreateAlignedMemoryBuffer(cbMaxLength, MF_16_BYTE_ALIGNMENT, &buffer_));// 16 byteアラインメント
		CHK(buffer_->SetCurrentLength(cbMaxLength));
		CHK(sample_->AddBuffer(buffer_.Get()));

		//
		// 読み込みテクスチャをマップ
		sf::map<> map(context,texture, 0, D3D11_MAP_READ, 0);
		copy_image_.reset(new video_writer::copy_image(width_, height_, map.row_pitch()));
		copy_func_ = (copy_func_t)copy_image_->getCode();

	}
Esempio n. 14
0
void EncodeTransform::Init(int width, int height)
{
	VTUNE_TASK(g_pDomain, "Encoder Init");

	mStreamHeight = height;
	mStreamWidth = width;
	mCompressedBuffer = new DWORD[(width*height) / 2];

	HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
	if (SUCCEEDED(hr) || (FAILED(hr) && hr == RPC_E_CHANGED_MODE))
	{
		hr = FindEncoder(MFVideoFormat_H264);
		if (FAILED(hr))
		{
			std::cout << "failed to find/Create specified encoder mft" << std::endl;
		}

		// set the media output info
		hr = SetOutputMediaType();
		if (FAILED(hr))
		{
			std::cout << "failed to SetOutputMediaType " << std::endl;
		}

		// set the media input info
		hr = SetInputMediaType();
		if (FAILED(hr))
		{
			std::cout << "failed to SetInputMediaType" << std::endl;
		}

		// query media input stream info
		hr = QueryInputStreamInfo();
		if (FAILED(hr))
		{
			std::cout << "failed to QueryInputStreamInfo" << std::endl;
		}

		{  //used to be NUM_PIXELS_YUY2 * 4
			HRESULT hr = MFCreateMemoryBuffer((mStreamWidth*mStreamHeight) * 2, &mpInputBuffer);
			if (FAILED(hr))
			{
				std::cout << "Failed to MFCreateMemoryBuffer" << std::endl;
			}

			hr = MFCreateSample(&pSampleProcIn);
			if (FAILED(hr))
			{
				std::cout << "Failed to MFCreateSample" << std::endl;
			}
			hr = pSampleProcIn->AddBuffer(mpInputBuffer);
			if (FAILED(hr))
			{
				std::cout << "Failed to AddBuffer to sample" << std::endl;
			}
		}

		{   //used to be NUM_PIXELS_YUY2 * 4
			hr = MFCreateMemoryBuffer(mStreamWidth * mStreamWidth * 2, &mpEncodedBuffer);
			if (FAILED(hr))
			{
				std::cout << "Failed to MFCreateMemoryBuffer" << std::endl;
			}

			hr = MFCreateSample(&pSampleProcOut);
			if (FAILED(hr))
			{
				std::cout << "Failed to MFCreateSample" << std::endl;
			}

			hr = pSampleProcOut->AddBuffer(mpEncodedBuffer);
			if (FAILED(hr))
			{
				std::cout << "Failed to AddBuffer to sample" << std::endl;
			}
		}
	}
}
Esempio n. 15
0
VideoCompressorResult VideoCompressor::OpenFile(const String &Filename, UINT Width, UINT Height, UINT BitRate, UINT FrameRate, UINT AudioDeviceIndex, Clock *Timer)
{
    VideoCompressorResult Result = VideoCompressorResultSuccess;
    _Width = Width;
    _Height = Height;
    _CapturingAudio = (AudioDeviceIndex != 0xFFFFFFFF);
    _Clock = Timer;
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
    //PersistentAssert(SUCCEEDED(hr), "CoInitializeEx failed");

    hr = MFStartup(MF_VERSION);
    PersistentAssert(SUCCEEDED(hr), "MFStartup failed");
    
    hr = MFCreateSinkWriterFromURL(
            UnicodeString(Filename).CString(),
            NULL,
            NULL,
            &_Writer
            );
    PersistentAssert(SUCCEEDED(hr), "MFCreateSinkWriterFromURL failed");

    const UINT RawBufferSize = Width * Height * 4;
    
    IMFMediaType *OutputMediaType;
    MFCreateMediaType(&OutputMediaType);
    InitMediaType(OutputMediaType, MFVideoFormat_H264, BitRate, Width, Height, FrameRate);

    IMFMediaType *InputMediaType;
    MFCreateMediaType(&InputMediaType);
    InitMediaType(InputMediaType, MFVideoFormat_RGB32, RawBufferSize, Width, Height, FrameRate);

    DWORD VideoStreamIndex;
    hr = _Writer->AddStream(OutputMediaType, &VideoStreamIndex);
    PersistentAssert(SUCCEEDED(hr), "AddStream failed");
    OutputMediaType->Release();
    
    /*hr = MFTRegisterLocalByCLSID(
            __uuidof(CColorConvertDMO),
            MFT_CATEGORY_VIDEO_PROCESSOR,
            L"",
            MFT_ENUM_FLAG_SYNCMFT,
            0,
            NULL,
            0,
            NULL
            );
    PersistentAssert(SUCCEEDED(hr), "MFTRegisterLocalByCLSID failed");*/

    hr = _Writer->SetInputMediaType(VideoStreamIndex, InputMediaType, NULL);
    InputMediaType->Release();
    if(FAILED(hr))
    {
        if(Width > 1920 || Height > 1080)
        {
            MessageBox(NULL, "The maximum resolution for H.264 video is 1920x1080.", "Invalid Window Dimensions", MB_OK | MB_ICONERROR);
        }
        else
        {
            MessageBox(NULL, "There was an error when attempting to initialize video capture.  The maximum resolution for H.264 video is 1920x1080.", "Invalid Window Dimensions", MB_OK | MB_ICONERROR);
        }
        _Writer->Release();
        _Writer = NULL;
        _Clock = NULL;
        return VideoCompressorResultFailure;
    }
    
    if(_CapturingAudio)
    {
        //
        // Setup the output media type
        //
        IMFMediaType *OutputAudioType;
        hr = MFCreateMediaType( &OutputAudioType );
        PersistentAssert(SUCCEEDED(hr), "MFCreateMediaType failed");

        const UINT SamplesPerSecond = 44100;
        const UINT AverageBytesPerSecond = 24000;
        const UINT ChannelCount = 2;
        const UINT BitsPerSample = 16;
        
        OutputAudioType->SetGUID( MF_MT_MAJOR_TYPE, MFMediaType_Audio ) ;  
        OutputAudioType->SetGUID( MF_MT_SUBTYPE, MFAudioFormat_AAC ) ;
        OutputAudioType->SetUINT32( MF_MT_AUDIO_SAMPLES_PER_SECOND, SamplesPerSecond ) ;
        OutputAudioType->SetUINT32( MF_MT_AUDIO_BITS_PER_SAMPLE, BitsPerSample ) ;
        OutputAudioType->SetUINT32( MF_MT_AUDIO_NUM_CHANNELS, ChannelCount ) ;
        OutputAudioType->SetUINT32( MF_MT_AUDIO_AVG_BYTES_PER_SECOND, AverageBytesPerSecond ) ;
        OutputAudioType->SetUINT32( MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 ) ;
        //OutputAudioType->SetUINT32( MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0x29 ) ;

        DWORD AudioStreamIndex;
        hr = _Writer->AddStream( OutputAudioType, &AudioStreamIndex );
        PersistentAssert(SUCCEEDED(hr), "AddStream failed");

        //
        // Setup the input media type
        //

        IMFMediaType *InputAudioType;
        MFCreateMediaType( &InputAudioType );
        InputAudioType->SetGUID( MF_MT_MAJOR_TYPE, MFMediaType_Audio );
        InputAudioType->SetGUID( MF_MT_SUBTYPE, MFAudioFormat_PCM );
        InputAudioType->SetUINT32( MF_MT_AUDIO_BITS_PER_SAMPLE, BitsPerSample );
        InputAudioType->SetUINT32( MF_MT_AUDIO_SAMPLES_PER_SECOND, SamplesPerSecond );
        InputAudioType->SetUINT32( MF_MT_AUDIO_NUM_CHANNELS, ChannelCount );

        hr = _Writer->SetInputMediaType( AudioStreamIndex, InputAudioType, NULL );
        PersistentAssert(SUCCEEDED(hr), "SetInputMediaType failed");

        _AudioCapture.StartCapture(this, AudioDeviceIndex);
    }

    hr = _Writer->BeginWriting();
    PersistentAssert(SUCCEEDED(hr), "BeginWriting failed");

    
    hr = MFCreateSample(&_Sample);
    PersistentAssert(SUCCEEDED(hr), "MFCreateSample failed");

    hr = MFCreateMemoryBuffer(RawBufferSize, &_Buffer);
    _Buffer->SetCurrentLength(RawBufferSize);
    _Sample->AddBuffer(_Buffer);

    return Result;
}
Esempio n. 16
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();
}
	virtual void doGetNextFrame()
	{
		if (!_isInitialised)
		{
			_isInitialised = true;
			if (!initialise())
			{
				printf("Video device initialisation failed, stopping.");
				return;
			}
		}

		if (!isCurrentlyAwaitingData()) return;

		DWORD processOutputStatus = 0;
		IMFSample *videoSample = NULL;
		DWORD streamIndex, flags;
		LONGLONG llVideoTimeStamp, llSampleDuration;
		HRESULT mftProcessInput = S_OK;
		HRESULT mftProcessOutput = S_OK;
		MFT_OUTPUT_STREAM_INFO StreamInfo;
		IMFMediaBuffer *pBuffer = NULL;
		IMFSample *mftOutSample = NULL;
		DWORD mftOutFlags;
		bool frameSent = false;

		CHECK_HR(_videoReader->ReadSample(
			MF_SOURCE_READER_FIRST_VIDEO_STREAM,
			0,                              // Flags.
			&streamIndex,                   // Receives the actual stream index. 
			&flags,                         // Receives status flags.
			&llVideoTimeStamp,              // Receives the time stamp.
			&videoSample                    // Receives the sample or NULL.
			), "Error reading video sample.");

		if (videoSample)
		{
			_frameCount++;

			CHECK_HR(videoSample->SetSampleTime(llVideoTimeStamp), "Error setting the video sample time.\n");
			CHECK_HR(videoSample->GetSampleDuration(&llSampleDuration), "Error getting video sample duration.\n");

			// Pass the video sample to the H.264 transform.

			CHECK_HR(_pTransform->ProcessInput(0, videoSample, 0), "The resampler H264 ProcessInput call failed.\n");

			CHECK_HR(_pTransform->GetOutputStatus(&mftOutFlags), "H264 MFT GetOutputStatus failed.\n");

			if (mftOutFlags == MFT_OUTPUT_STATUS_SAMPLE_READY)
			{
				printf("Sample ready.\n");

				CHECK_HR(_pTransform->GetOutputStreamInfo(0, &StreamInfo), "Failed to get output stream info from H264 MFT.\n");

				CHECK_HR(MFCreateSample(&mftOutSample), "Failed to create MF sample.\n");
				CHECK_HR(MFCreateMemoryBuffer(StreamInfo.cbSize, &pBuffer), "Failed to create memory buffer.\n");
				CHECK_HR(mftOutSample->AddBuffer(pBuffer), "Failed to add sample to buffer.\n");

				while (true)
				{
					_outputDataBuffer.dwStreamID = 0;
					_outputDataBuffer.dwStatus = 0;
					_outputDataBuffer.pEvents = NULL;
					_outputDataBuffer.pSample = mftOutSample;

					mftProcessOutput = _pTransform->ProcessOutput(0, 1, &_outputDataBuffer, &processOutputStatus);

					if (mftProcessOutput != MF_E_TRANSFORM_NEED_MORE_INPUT)
					{
						CHECK_HR(_outputDataBuffer.pSample->SetSampleTime(llVideoTimeStamp), "Error setting MFT sample time.\n");
						CHECK_HR(_outputDataBuffer.pSample->SetSampleDuration(llSampleDuration), "Error setting MFT sample duration.\n");

						IMFMediaBuffer *buf = NULL;
						DWORD bufLength;
						CHECK_HR(_outputDataBuffer.pSample->ConvertToContiguousBuffer(&buf), "ConvertToContiguousBuffer failed.\n");
						CHECK_HR(buf->GetCurrentLength(&bufLength), "Get buffer length failed.\n");
						BYTE * rawBuffer = NULL;

						auto now = GetTickCount();

						printf("Writing sample %i, spacing %I64dms, sample time %I64d, sample duration %I64d, sample size %i.\n", _frameCount, now - _lastSendAt, llVideoTimeStamp, llSampleDuration, bufLength);

						fFrameSize = bufLength;
						fDurationInMicroseconds = 0;
						gettimeofday(&fPresentationTime, NULL);

						buf->Lock(&rawBuffer, NULL, NULL);
						memmove(fTo, rawBuffer, fFrameSize);

						FramedSource::afterGetting(this);

						buf->Unlock();
						SafeRelease(&buf);

						frameSent = true;
						_lastSendAt = GetTickCount();
					}

					SafeRelease(&pBuffer);
					SafeRelease(&mftOutSample);

					break;
				}
			}
			else {
				printf("No sample.\n");
			}

			SafeRelease(&videoSample);
		}

		if (!frameSent)
		{
			envir().taskScheduler().triggerEvent(eventTriggerId, this);
		}

		return;

	done:

		printf("MediaFoundationH264LiveSource doGetNextFrame failed.\n");
	}