Как извлечь кадры H264 с помощью live555 - PullRequest
0 голосов
/ 08 мая 2018

Полного примера нигде просто нет. В папках live555 есть следующая программа: testRTSPClient.cpp , которая обращается к RTSP и получает необработанные RTP-пакеты, но ничего с ними не делает. Он получает их через класс DummySink.

Существует пример о том, как использовать testRTSPClient.cpp для получения единиц NAL от h264, но live555 имеет собственные классы приемников специально для каждого кодека, поэтому их гораздо лучше использовать. Пример: H264or5VideoRTPSink.cpp .

Так что, если я заменю экземпляр DummySink экземпляром подкласса H264or5VideoRTPSink в testRTSPClient.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:

UPDATE:

Я создал собственный класс Мойки H264: https://github.com/lucaszanella/jscam/blob/f6b38eea2934519bcccd76c8d3aee7f58793da00/src/jscam/android/app/src/main/cpp/MyH264VideoRTPSink.cpp, но у него createNew отличается от класса DummySink:

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

Просто нет упоминания о том, что должно быть RTPgs, а также rtpPayloadFormat. Я даже не знаю, нахожусь ли я на правильном пути ...

1 Ответ

0 голосов
/ 10 мая 2018

Первая путаница между Source & Sink, FAQ кратко описывает рабочий процесс:

«source1» -> «source2» (фильтр) -> «source3» (фильтр) -> «сток»

Класс H264VideoRTPSink предназначен для публикации данных через RTP, а не для их использования.

В случае примера клиента RTSP testRTSPClient.cpp создается источник, зависящий от кодека, который обрабатывает ответ DESCRIBE, вызывая MediaSession::createNew.

Sink не зависит от кодека, метод startPlaying в MediaSink регистрирует обратный вызов afterGettingFrame, который вызывается при получении данных источником. Затем, когда этот обратный вызов будет выполнен, вы должны позвонить continuePlaying, чтобы снова зарегистрировать его для следующих входящих данных.

В DummySink::afterGettingFrame буфер содержит кадры элементарного потока H264, извлеченные из буфера RTP.

Чтобы сбросить кадр элементарного потока H264, вы можете взглянуть на h264bitstream

...