204 lines
5.3 KiB
C++
204 lines
5.3 KiB
C++
|
|
#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
|