RTSP streams that use Media Foundation stop loading.
MASAHIROTANAKA-1764
0
Reputation points
I'm writing an application that uses Media Foundation to read and parse RTSP streams.
The stream will be in H.264 codec at 25 fps.
I can get images using Media Foundation's SourceReader, but it stops at ReadSample() after about 1-2 minute.
There's no reception on Ethernet in Windows Task Manager, so I think it's disconnected.
Does anyone know why ReadSample() stops on its own?
// SourceReader.h
#pragma once
using namespace System;
using namespace System::Collections::Generic;
#using <system.drawing.dll>
using namespace System::Drawing::Imaging;
using namespace System::Threading;
namespace MediaFoundationCLILib
{
public ref class ReadSampleProcessParameter
{
public:
String^ Url;
};
public ref class SourceReaderSample
{
public:
array<Byte>^ Image;
Int32 Width;
Int32 Height;
Int32 Stride;
PixelFormat PixelFormat;
FLOAT Fps;
};
public ref class SourceReader
{
public:
SourceReader(String^ url);
~SourceReader();
!SourceReader();
void Start();
void Stop();
Action<SourceReaderSample^>^ ReadSample;
protected:
String^ Url = String::Empty;
private:
Thread^ ReadSampleThread = nullptr;
Boolean ReadSampleProcessFlag = false;
SourceReader() {};
void ReadSampleProcess(Object^ parameter);
};
}
// SourceReader.cpp
#include "pch.h"
#include <msclr\marshal.h>
#include "SourceReader.h"
using namespace System::Runtime::InteropServices;
using namespace msclr::interop;
using namespace MediaFoundationCLILib;
template <class T> void SafeRelease(T** ppT)
{
if (*ppT)
{
(*ppT)->Release();
*ppT = nullptr;
}
}
SourceReader::SourceReader(String^ url)
{
this->Url = url;
}
SourceReader::~SourceReader()
{
this->!SourceReader();
}
SourceReader::!SourceReader()
{
this->Stop();
}
void SourceReader::Start()
{
this->Stop();
auto readSampleProcessParameter = gcnew ReadSampleProcessParameter();
readSampleProcessParameter->Url = this->Url;
this->ReadSampleThread = gcnew Thread(gcnew ParameterizedThreadStart(this, &SourceReader::ReadSampleProcess));
this->ReadSampleThread->Start(readSampleProcessParameter);
}
void SourceReader::Stop()
{
this->ReadSampleProcessFlag = false;
if (this->ReadSampleThread != nullptr)
{
this->ReadSampleThread->Join();
this->ReadSampleThread = nullptr;
}
}
void SourceReader::ReadSampleProcess(Object^ parameter)
{
auto readSampleProcessParameter = (ReadSampleProcessParameter^)parameter;
marshal_context context;
auto pwszURL = context.marshal_as<const TCHAR*>(readSampleProcessParameter->Url);
HRESULT hr;
IMFAttributes* pAttributes = nullptr;
IMFSourceReader* pSourceReader = nullptr;
IMFMediaType* pNewMediaType = nullptr;
IMFMediaType* pMediaType = nullptr;
try
{
// Create output media type(RGB32bit)
hr = MFCreateAttributes(&pAttributes, 1);
if (FAILED(hr))
{
throw gcnew Exception(String::Format("SourceReader::ReadSampleProcess() step01,HRESULT:{0:X}", hr));
}
hr = pAttributes->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, TRUE);
if (FAILED(hr))
{
throw gcnew Exception(String::Format("SourceReader::ReadSampleProcess() step02,HRESULT:{0:X}", hr));
}
// Create SourceReader
hr = MFCreateSourceReaderFromURL(pwszURL, pAttributes, &pSourceReader);
if (FAILED(hr))
{
throw gcnew Exception(String::Format("SourceReader::ReadSampleProcess() step03,Exception:{0:X}", hr));
}
// Set output media type(RGB32bit)
hr = MFCreateMediaType(&pNewMediaType);
if (FAILED(hr))
{
throw gcnew Exception(String::Format("SourceReader::ReadSampleProcess() step04,Exception:{0:X}", hr));
}
hr = pNewMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
hr = pNewMediaType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);
hr = pSourceReader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, nullptr, pNewMediaType);
if (FAILED(hr))
{
throw gcnew Exception(String::Format("SourceReader::ReadSampleProcess() step05,Exception:{0:X}", hr));
}
SafeRelease(&pNewMediaType);
// Video Information
// stride:Bytes per image line
// width:Image width
// height:Image height
hr = pSourceReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, &pMediaType);
if (FAILED(hr))
{
throw gcnew Exception(String::Format("SourceReader::ReadSampleProcess() step06,Exception:{0:X}", hr));
}
auto stride = (INT32)MFGetAttributeUINT32(pMediaType, MF_MT_DEFAULT_STRIDE, 0);
UINT32 width = 0;
UINT32 height = 0;
hr = MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &width, &height);
if ((stride == 0) || FAILED(hr))
{
throw gcnew Exception(String::Format("SourceReader::ReadSampleProcess() step07,Exception:{0}", hr));
}
SafeRelease(&pMediaType);
// Get frame
DWORD dwActualStreamIndex;
DWORD dwStreamFlags;
LONGLONG llTimestamp;
IMFSample* pSample = nullptr;
IMFMediaBuffer* pMediaBuffer = nullptr;
auto frameCount = 0;
auto fps = 0.0f;
auto stopwatch = gcnew System::Diagnostics::Stopwatch();
stopwatch->Restart();
this->ReadSampleProcessFlag = true;
while (this->ReadSampleProcessFlag)
{
hr = pSourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, &dwActualStreamIndex, &dwStreamFlags, &llTimestamp, &pSample);
if (FAILED(hr))
{
break;
}
else if (dwStreamFlags & MF_SOURCE_READERF_ERROR)
{
break;
}
else if (dwStreamFlags & MF_SOURCE_READERF_ENDOFSTREAM)
{
break;
}
else if (pSample == nullptr)
{
continue;
}
// FPS
frameCount++;
if (frameCount >= 25)
{
stopwatch->Stop();
fps = (1000.0f / stopwatch->ElapsedMilliseconds) * frameCount;
stopwatch->Restart();
frameCount = 0;
}
if (ReadSample != nullptr)
{
DWORD cbCurrentLength = 0;
BYTE* pBuffer = nullptr;
hr = pSample->ConvertToContiguousBuffer(&pMediaBuffer);
hr = pMediaBuffer->Lock(&pBuffer, nullptr, &cbCurrentLength);
auto image = gcnew array<Byte>(stride * height);
Marshal::Copy((IntPtr)pBuffer, image, 0, stride * height);
hr = pMediaBuffer->Unlock();
SafeRelease(&pMediaBuffer);
SourceReaderSample^ sourceReaderSample = gcnew SourceReaderSample();
sourceReaderSample->Image = image;
sourceReaderSample->Width = width;
sourceReaderSample->Height = height;
sourceReaderSample->Stride = stride;
sourceReaderSample->PixelFormat = PixelFormat::Format32bppRgb;
sourceReaderSample->Fps = fps;
ReadSample(sourceReaderSample);
}
SafeRelease(&pSample);
Thread::Sleep(20);
}
}
catch (Exception^)
{
}
finally
{
SafeRelease(&pMediaType);
SafeRelease(&pNewMediaType);
SafeRelease(&pSourceReader);
SafeRelease(&pAttributes);
}
}
Sign in to answer