ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Live555推流H264裸流实战

2026/8/3 3:56:16 拓冰建站 浏览量
Live555推流H264裸流实战 使用 Live555 实现 RTSP 推流程序,核心在于继承并实现FramedSource类以提供视频数据,并将其集成到 Live555 的OnDemandServerMediaSubsession框架中。以下是一个从内存缓冲区(如 FIFO 或环形队列)读取 H.264 裸流并进行 RTSP 推流的完整示例。1. 核心类:H.264 视频帧源首先,创建一个从FramedSource派生的类,负责从指定数据源(如 FIFO 文件)读取 H.264 数据。// H264FramedSource.h #ifndef _H264_FRAMED_SOURCE_H_ #define _H264_FRAMED_SOURCE_H_ #include liveMedia.hh #include GroupsockHelper.hh class H264FramedSource : public FramedSource { public: static H264FramedSource* createNew(UsageEnvironment env, const char* fifoFileName); // 设置事件触发器,当有数据可读时触发 virtual void doGetNextFrame(); protected: H264FramedSource(UsageEnvironment env, const char* fifoFileName); virtual ~H264FramedSource(); private: static void incomingDataHandler(H264FramedSource* source); void incomingDataHandler1(); static void onSourceClosure(void* clientData); void onSourceClosure1(); private: FILE* m_fFifo; EventTriggerId m_eventTriggerId; char m_fifoFileName[256]; }; #endif// H264FramedSource.cpp #include "H264FramedSource.h" #include fcntl.h #include sys/stat.h #include unistd.h #define FIFO_READ_SIZE 200000 // 根据NALU最大尺寸调整 H264FramedSource* H264FramedSource::createNew(UsageEnvironment env, const char* fifoFileName) { H264FramedSource* newSource = new H264FramedSource(env, fifoFileName); return newSource; } H264FramedSource::H264FramedSource(UsageEnvironment env, const char* fifoFileName) : FramedSource(env), m_fFifo(NULL), m_eventTriggerId(0) { strcpy(m_fifoFileName, fifoFileName); // 以非阻塞方式打开FIFO,避免在无数据时阻塞 m_fFifo = fopen(fifoFileName, "rb"); if (m_fFifo == NULL) { envir() "Failed to open FIFO: " fifoFileName " "; return; } // 设置文件描述符为非阻塞 int fd = fileno(m_fFifo); int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); // 注册一个事件触发器,当有数据可读时触发 m_eventTriggerId = envir().taskScheduler().createEventTrigger(incomingDataHandler); } H264FramedSource::~H264FramedSource() { if (m_fFifo) { fclose(m_fFifo); m_fFifo = NULL; } if (m_eventTriggerId) { envir().taskScheduler().deleteEventTrigger(m_eventTr