From 79e9bca11f53208b09d7b62cfb93d44baaa52374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Trzci=C5=84ski?= Date: Sat, 29 Oct 2022 11:36:58 +0200 Subject: [PATCH] Discover H264 keyframes on dequeue --- device/buffer_queue.c | 23 +++++++++++++++++++++++ output/http_ffmpeg.c | 2 +- output/http_h264.c | 23 +---------------------- output/output.h | 1 - output/rtsp/rtsp.cc | 2 +- output/webrtc/webrtc.cc | 2 +- 6 files changed, 27 insertions(+), 26 deletions(-) diff --git a/device/buffer_queue.c b/device/buffer_queue.c index 38c4071..de9fd51 100644 --- a/device/buffer_queue.c +++ b/device/buffer_queue.c @@ -2,6 +2,7 @@ #include "device/buffer_list.h" #include "device/device.h" #include "util/opts/log.h" +#include "util/opts/fourcc.h" #include #include @@ -144,6 +145,24 @@ int buffer_list_enqueue(buffer_list_t *buf_list, buffer_t *dma_buf) return 1; } +static void buffer_update_h264_key_frame(buffer_t *buf) +{ + unsigned char *data = buf->start; + + static const int N = 8; + char buffer [3*N+1]; + buffer[sizeof(buffer)-1] = 0; + for(int j = 0; j < N; j++) + sprintf(&buffer[sizeof(buffer)/N*j], "%02X ", data[j]); + + if (buf->flags.is_keyframe) { + LOG_DEBUG(buf, "Got key frame (from V4L2)!: %s", buffer); + } else if (buf->used >= 5 && (data[4] & 0x1F) == 0x07) { + LOG_DEBUG(buf, "Got key frame (from buffer)!: %s", buffer); + buf->flags.is_keyframe = true; + } +} + buffer_t *buffer_list_dequeue(buffer_list_t *buf_list) { buffer_t *buf = NULL; @@ -174,6 +193,10 @@ buffer_t *buffer_list_dequeue(buffer_list_t *buf_list) buf->dma_source = NULL; } + if (buf_list->fmt.format == V4L2_PIX_FMT_H264) { + buffer_update_h264_key_frame(buf); + } + buf_list->frames++; return buf; diff --git a/output/http_ffmpeg.c b/output/http_ffmpeg.c index c66b256..1336346 100644 --- a/output/http_ffmpeg.c +++ b/output/http_ffmpeg.c @@ -77,7 +77,7 @@ static int http_ffmpeg_write_to_stream(void *opaque, uint8_t *buf, int buf_size) static int http_ffmpeg_video_buf_part(buffer_lock_t *buf_lock, buffer_t *buf, int frame, http_ffmpeg_status_t *status) { if (!status->had_key_frame) { - status->had_key_frame = h264_is_key_frame(buf); + status->had_key_frame = buf->flags.is_keyframe; } if (!status->had_key_frame) { diff --git a/output/http_h264.c b/output/http_h264.c index 52d62b4..90a8a3a 100644 --- a/output/http_h264.c +++ b/output/http_h264.c @@ -31,31 +31,10 @@ typedef struct { bool requested_key_frame; } http_video_status_t; -bool h264_is_key_frame(buffer_t *buf) -{ - unsigned char *data = buf->start; - - static const int N = 8; - char buffer [3*N+1]; - buffer[sizeof(buffer)-1] = 0; - for(int j = 0; j < N; j++) - sprintf(&buffer[sizeof(buffer)/N*j], "%02X ", data[j]); - - if (buf->flags.is_keyframe) { - LOG_DEBUG(buf, "Got key frame (from V4L2)!: %s", buffer); - return true; - } else if (buf->used >= 5 && (data[4] & 0x1F) == 0x07) { - LOG_DEBUG(buf, "Got key frame (from buffer)!: %s", buffer); - return true; - } - - return false; -} - int http_video_buf_part(buffer_lock_t *buf_lock, buffer_t *buf, int frame, http_video_status_t *status) { if (!status->had_key_frame) { - status->had_key_frame = h264_is_key_frame(buf); + status->had_key_frame = buf->flags.is_keyframe; } if (!status->had_key_frame) { diff --git a/output/output.h b/output/output.h index 42ae185..6b98e44 100644 --- a/output/output.h +++ b/output/output.h @@ -17,7 +17,6 @@ void http_stream(struct http_worker_s *worker, FILE *stream); void http_option(struct http_worker_s *worker, FILE *stream); // H264 -bool h264_is_key_frame(struct buffer_s *buf); void http_h264_video(struct http_worker_s *worker, FILE *stream); void http_mkv_video(struct http_worker_s *worker, FILE *stream); void http_mp4_video(struct http_worker_s *worker, FILE *stream); diff --git a/output/rtsp/rtsp.cc b/output/rtsp/rtsp.cc index e3511ca..404cc46 100644 --- a/output/rtsp/rtsp.cc +++ b/output/rtsp/rtsp.cc @@ -75,7 +75,7 @@ public: return; } - if (h264_is_key_frame(buf)) { + if (buf->flags.is_keyframe) { fHadKeyFrame = true; } diff --git a/output/webrtc/webrtc.cc b/output/webrtc/webrtc.cc index c50fd58..f4df590 100644 --- a/output/webrtc/webrtc.cc +++ b/output/webrtc/webrtc.cc @@ -115,7 +115,7 @@ public: } if (!had_key_frame) { - if (!h264_is_key_frame(buf)) { + if (!buf->flags.is_keyframe) { device_video_force_key(buf->buf_list->dev); LOG_VERBOSE(self, "Skipping as key frame was not yet sent."); return;