GrabBag/Module/FFMediaStream/Src/CVrFFMediaPuller.cpp

204 lines
5.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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