#include "CVrFFMediaPuller.h" #include "VrError.h" #include "VrLog.h" #if !defined(FFMEDIA_PLATFORM_DUMMY) #include #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 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 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 lk(m_mutex); if (m_bInited.load()) return SUCCESS; m_config = config; // 1) RTSP 拉流 m_rtspClient = std::make_shared( 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(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(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 buffer) { if (!ctx || !buffer) return; CVrFFMediaPuller* self = static_cast(ctx); FFPulledFrameCallback cb; { std::lock_guard lk(self->m_mutex); cb = self->m_callback; } if (!cb) return; VideoBuffer* vbuf = static_cast(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 lk(m_mutex); m_rga.reset(); m_decoder.reset(); m_rtspClient.reset(); m_bInited = false; return SUCCESS; } #endif // FFMEDIA_PLATFORM_DUMMY