如何使用live555提取H264帧

时间:2018-05-08 14:57:46

标签: c++ video-streaming h.264 codec live555

在任何地方都没有完整的例子。在live555文件夹中,有以下程序:testRTSPClient.cpp访问RTSP并接收原始RTP数据包但不对它们执行任何操作。它通过DummySink类接收它们。

关于如何使用testRTSPClient.cpp从h264接收NAL单元有example,但live555专门针对每个编解码器设置了自定义接收器类,因此使用它们要好得多。示例:H264or5VideoRTPSink.cpp

因此,如果我将DummySink的实例替换为H264or5VideoRTPSinktestRTSPClient.cpp的子类的实例,并使该子类接收我认为可能有效的帧。

如果我只是遵循DummySink的实现,我只需要写下这样的内容:

class MyH264VideoRTPSink: public H264VideoRTPSink {
    public:
        static MyH264VideoRTPSink* createNew(UsageEnvironment& env,
                        MediaSubsession& subsession, // identifies the kind of data that's being received
                        char const* streamId = NULL); // identifies the stream itself (optional)

    private:
        MyH264VideoRTPSink(UsageEnvironment& env, MediaSubsession& subsession, char const* streamId);
            // called only by "createNew()"
        virtual ~MyH264VideoRTPSink();

        static void afterGettingFrame(void* clientData, unsigned frameSize,
                                      unsigned numTruncatedBytes,
                                      struct timeval presentationTime,
                                      unsigned durationInMicroseconds);
        void afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,
                    struct timeval presentationTime, unsigned durationInMicroseconds);

        // redefined virtual functions:
        virtual Boolean continuePlaying();

        u_int8_t* fReceiveBuffer;
        MediaSubsession& fSubsession;
        char* fStreamId;
};

如果我们查看DummySink,则表明afterGettingFrame是接收帧的函数。但收到的框架在哪里?我该如何访问它?

void DummySink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,
                  struct timeval presentationTime, unsigned /*durationInMicroseconds*/) {
// We've just received a frame of data.  (Optionally) print out information about it:

更新

我创建了自己的H264接收器类:https://github.com/lucaszanella/jscam/blob/f6b38eea2934519bcccd76c8d3aee7f58793da00/src/jscam/android/app/src/main/cpp/MyH264VideoRTPSink.cpp但它与createNew中的DummySink不同{/ 1}}:

createNew(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat);

根本没有提及RTPgs的意图,rtpPayloadFormat。我甚至不知道我是否走在正确的轨道上......

1 个答案:

答案 0 :(得分:2)

第一个混乱来自Source&接收器,FAQ简要描述了工作流程:

  

' source1中' - > '源2' (过滤器) - > ' source3' (过滤器) - > '信宿'

H264VideoRTPSink用于通过RTP发布数据,而不是使用数据。

对于RTSP客户端示例testRTSPClient.cpp,创建依赖于编解码器的源,处理调用MediaSession::createNew的DESCRIBE应答。

Sink不依赖于编解码器,startPlaying上的MediaSink方法注册了当源接收数据时要调用的回调afterGettingFrame。接下来,当执行此回调时,您应该调用continuePlaying再次注册它以获取下一个传入数据。

DummySink::afterGettingFrame中,缓冲区包含从RTP缓冲区中提取的H264基本流帧。

要转储H264基本流帧,您可以查看h264bitstream