GrabBag/Module/FFMediaStream/Src/CVrFFMediaPuller.cpp

204 lines
5.3 KiB
C++
Raw Normal View History

#include "CVrFFMediaPuller.h"
#include "VrError.h"
#include "VrLog.h"
#if !defined(FFMEDIA_PLATFORM_DUMMY)
#include <linux/videodev2.h>
#endif
bool IVrFFMediaPuller::CreateObject(IVrFFMediaPuller** ppPuller)
{
if (!ppPuller) return false;
try { *ppPuller = new CVrFFMediaPuller(); return true; }
catch (...) { return false; }
}
CVrFFMediaPuller::CVrFFMediaPuller() = default;
CVrFFMediaPuller::~CVrFFMediaPuller()
{
try { UnInit(); } catch (...) {}
}
void CVrFFMediaPuller::SetFrameCallback(FFPulledFrameCallback callback)
{
std::lock_guard<std::mutex> lk(m_mutex);
m_callback = std::move(callback);
}
bool CVrFFMediaPuller::IsStreaming() const
{
return m_bStarted.load();
}
#if defined(FFMEDIA_PLATFORM_DUMMY)
// =================== Windows / 非 RK3588 占位实现 ===================
int CVrFFMediaPuller::Init(const VrFFPullConfig& config)
{
std::lock_guard<std::mutex> lk(m_mutex);
m_config = config;
m_bInited = true;
LOG_INFO("FFMediaPuller: Init (dummy)\n");
return SUCCESS;
}
int CVrFFMediaPuller::Start()
{
if (!m_bInited.load()) return ERR_CODE(DEV_NO_OPEN);
m_bStarted = true;
LOG_INFO("FFMediaPuller: Start (dummy)\n");
return SUCCESS;
}
int CVrFFMediaPuller::Stop()
{
m_bStarted = false;
return SUCCESS;
}
int CVrFFMediaPuller::UnInit()
{
Stop();
m_bInited = false;
return SUCCESS;
}
#else
// =================== RK3588 真正实现 ===================
static uint32_t ToV4l2OutPix(EFFPullPixelFormat fmt)
{
switch (fmt)
{
case EFFPullPixelFormat::NV12: return V4L2_PIX_FMT_NV12;
case EFFPullPixelFormat::RGBA32: return V4L2_PIX_FMT_RGBA32;
case EFFPullPixelFormat::BGR24: return V4L2_PIX_FMT_BGR24;
}
return V4L2_PIX_FMT_RGBA32;
}
static unsigned int PixelBpp(EFFPullPixelFormat fmt)
{
switch (fmt)
{
case EFFPullPixelFormat::NV12: return 1; // 平均 1.5 byte/px但 stride 用 width
case EFFPullPixelFormat::RGBA32: return 4;
case EFFPullPixelFormat::BGR24: return 3;
}
return 4;
}
int CVrFFMediaPuller::Init(const VrFFPullConfig& config)
{
std::lock_guard<std::mutex> lk(m_mutex);
if (m_bInited.load()) return SUCCESS;
m_config = config;
// 1) RTSP 拉流
m_rtspClient = std::make_shared<ModuleRtspClient>(
config.rtspUrl.c_str(),
config.useTcp ? RTSP_STREAM_TYPE_TCP : RTSP_STREAM_TYPE_UDP,
config.enableVideo,
config.enableAudio
);
if (m_rtspClient->init() != 0)
{
LOG_ERROR("FFMediaPuller: rtspClient init fail (%s)\n", config.rtspUrl.c_str());
return ERR_CODE(DEV_OPEN_ERR);
}
// 2) MPP 解码
ImagePara inPara = m_rtspClient->getOutputImagePara();
m_decoder = std::make_shared<ModuleMppDec>(inPara);
m_decoder->setProductor(m_rtspClient);
if (m_decoder->init() != 0)
{
LOG_ERROR("FFMediaPuller: mppdec init fail\n");
return ERR_CODE(DEV_OPEN_ERR);
}
// 3) RGA 转目标格式
ImagePara decOut = m_decoder->getOutputImagePara();
const uint32_t outFmt = ToV4l2OutPix(config.outputFormat);
const unsigned int outW = config.outputWidth ? config.outputWidth : decOut.width;
const unsigned int outH = config.outputHeight ? config.outputHeight : decOut.height;
ImagePara outPara(outW, outH, outW, outH, outFmt);
m_rga = std::make_shared<ModuleRga>(decOut, outPara, RGA_ROTATE_NONE);
m_rga->setBufferType(VideoBuffer::MALLOC_BUFFER);
m_rga->setProductor(m_decoder);
// 注册输出回调
m_rga->setOutputDataCallback(
this,
[](void* ctx, std::shared_ptr<MediaBuffer> buffer) {
if (!ctx || !buffer) return;
CVrFFMediaPuller* self = static_cast<CVrFFMediaPuller*>(ctx);
FFPulledFrameCallback cb;
{
std::lock_guard<std::mutex> lk(self->m_mutex);
cb = self->m_callback;
}
if (!cb) return;
VideoBuffer* vbuf = static_cast<VideoBuffer*>(buffer.get());
ImagePara para = vbuf->getImagePara();
VrFFPulledFrame frame;
frame.data = vbuf->getData();
frame.size = vbuf->getActiveSize();
frame.width = para.width;
frame.height = para.height;
frame.stride = para.hstride * PixelBpp(self->m_config.outputFormat);
frame.format = self->m_config.outputFormat;
frame.ptsUs = vbuf->getPUstimestamp();
try { cb(frame); } catch (...) {}
}
);
if (m_rga->init() != 0)
{
LOG_ERROR("FFMediaPuller: rga init fail\n");
return ERR_CODE(DEV_OPEN_ERR);
}
m_bInited = true;
return SUCCESS;
}
int CVrFFMediaPuller::Start()
{
if (!m_bInited.load()) return ERR_CODE(DEV_NO_OPEN);
if (m_bStarted.load()) return SUCCESS;
if (!m_rtspClient) return ERR_CODE(DEV_CTRL_ERR);
m_rtspClient->start();
m_bStarted = true;
return SUCCESS;
}
int CVrFFMediaPuller::Stop()
{
if (!m_bStarted.load()) return SUCCESS;
if (m_rtspClient) m_rtspClient->stop();
m_bStarted = false;
return SUCCESS;
}
int CVrFFMediaPuller::UnInit()
{
Stop();
std::lock_guard<std::mutex> lk(m_mutex);
m_rga.reset();
m_decoder.reset();
m_rtspClient.reset();
m_bInited = false;
return SUCCESS;
}
#endif // FFMEDIA_PLATFORM_DUMMY