【问题标题】:How to extract H264 frames using live555如何使用 live555 提取 H264 帧
【发布时间】:2018-05-08 14:57:46
【问题描述】:

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

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

因此,如果我用testRTSPClient.cpp 中的H264or5VideoRTPSink 子类的实例替换DummySink 的实例并让这个子类接收我认为它可能工作的帧。

如果我只是按照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 Sink 类:https://github.com/lucaszanella/jscam/blob/f6b38eea2934519bcccd76c8d3aee7f58793da00/src/jscam/android/app/src/main/cpp/MyH264VideoRTPSink.cpp,但它的 createNewDummySink 中的不同:

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

根本没有提到RTPgs 是什么意思,rtpPayloadFormat 也没有。我什至不知道我是否走在正确的轨道上......

【问题讨论】:

  • 你使用H264VideoRTPSink提取h264数据成功了吗
  • @Riskhan 我什至没有尝试过,那东西的编码和记录都很糟糕。我用github.com/Ansersion/myRtspClient
  • 是的,你是对的。我会尝试上面的链接。谢谢老哥及时回复
  • @Riskhan 它在示例文件夹中的示例非常有用,您还可以看到我所做的:github.com/lucaszanella/orwell/blob/… 它的编码非常糟糕,因为我还没有清理东西但是看看
  • 好吧。我会看看

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


【解决方案1】:

第一个混淆是在 Source 和 Sink 之间,FAQ 简要描述了工作流程:

'source1' -> 'source2' (过滤器) -> 'source3' (过滤器) -> 'sink'

H264VideoRTPSink 类用于通过 RTP 发布数据,而不是消费数据。

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

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

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

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

【讨论】:

  • 这很奇怪。在testRTSPClient.cpp 中明确表示需要 DummySink 来接收帧。所以H264VideoRTPSink 应该接收并解析 h264 帧。如果H264VideoRTPSink 是发送,H264VideoRTPSource 不应该是接收吗?我的意思是,如果这是图书馆需要做的主要事情,为什么live555 不实施其中的一些?我对做 h264bitstrem 没问题,但我认为所有这些接收器(h265、音频接收器等)都是为此而设计的。每一个都很难实现
  • 是的,DummySink 是接收从根据 SDP 信息创建的 FramedSource 接收的帧的消费者,您可以在创建 H264VideoRTPSource 的MediaSession 中看到这一点。接下来 DummySink 对这些帧做它喜欢的事情,写入、流式传输、解码......
猜你喜欢
  • 1970-01-01
  • 2016-09-28
  • 2016-07-19
  • 1970-01-01
  • 2017-05-01
  • 2013-12-03
  • 1970-01-01
  • 1970-01-01
  • 2012-06-12
相关资源
最近更新 更多