]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
[mod_av] make key_frame_min_freq work to prevent generate key frames too frequently
authorSeven Du <dujinfang@gmail.com>
Sat, 16 Nov 2019 08:43:47 +0000 (16:43 +0800)
committerAndrey Volk <andywolk@gmail.com>
Sat, 23 Oct 2021 19:00:32 +0000 (22:00 +0300)
src/mod/applications/mod_av/avcodec.c
src/mod/applications/mod_av/test/test_mod_av.c

index 827df4df6b39f351671ab3ca48f48d14fedb10d0..573b8baaa161ea5c53256b313caa2fa592ecfdf9 100644 (file)
@@ -385,6 +385,7 @@ typedef struct h264_codec_context_s {
        switch_image_t *img;
        switch_image_t *encimg;
        int need_key_frame;
+       switch_time_t last_keyframe_request;
        switch_bool_t nalu_28_start;
 
        int change_bandwidth;
@@ -420,7 +421,7 @@ struct avcodec_globals {
        int debug;
        uint32_t max_bitrate;
        uint32_t rtp_slice_size;
-       uint32_t key_frame_min_freq;
+       uint32_t key_frame_min_freq; // in ms
        uint32_t enc_threads;
        uint32_t dec_threads;
 
@@ -1567,10 +1568,14 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec, switch_frame_t
 
        avframe->pts = context->pts++;
 
-       if (context->need_key_frame) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG5, "Send AV KEYFRAME\n");
+       if (context->need_key_frame && (context->last_keyframe_request + avcodec_globals.key_frame_min_freq) < switch_time_now()) {
+               if (avcodec_globals.debug) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Generate/Send AV KEYFRAME\n");
+               }
+
                 avframe->pict_type = AV_PICTURE_TYPE_I;
                 avframe->key_frame = 1;
+                context->last_keyframe_request = switch_time_now();
        }
 
        /* encode the image */
@@ -1585,7 +1590,7 @@ GCC_DIAG_ON(deprecated-declarations)
                goto error;
        }
 
-       if (context->need_key_frame) {
+       if (context->need_key_frame && avframe->key_frame == 1) {
                avframe->pict_type = 0;
                avframe->key_frame = 0;
                context->need_key_frame = 0;
@@ -1633,8 +1638,12 @@ GCC_DIAG_ON(deprecated-declarations)
                                context->nalus[i].start = p;
                                context->nalus[i].eat = p;
 
-                               if (mod_av_globals.debug && (*p & 0x1f) == 7) {
-                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "KEY FRAME GENERATED\n");
+                               if ((*p & 0x1f) == 7) { // Got Keyframe
+                                       // prevent to generate key frame too frequently
+                                       context->last_keyframe_request = switch_time_now();
+                                       if (mod_av_globals.debug) {
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "KEY FRAME GENERATED\n");
+                                       }
                                }
                        } else {
                                context->nalus[i].len = p - context->nalus[i].start;
index a058aa63fd6e92318f0a6742dc4d9adfc1fdc7bc..69468dbda25e947637a0f005b3cf70610996a287 100644 (file)
@@ -50,7 +50,7 @@ static fctcl_init_t my_cl_options[] = {
 
 FST_CORE_BEGIN("conf")
 {
-        const char *loop_;
+       const char *loop_;
        fctcl_install(my_cl_options);
 
        loop_ = fctcl_val("--loop");
@@ -73,7 +73,11 @@ FST_CORE_BEGIN("conf")
                        uint8_t buf[SWITCH_DEFAULT_VIDEO_SIZE + 12];
                        switch_frame_t frame = { 0 };
                        int packets = 0;
+                       int frames = 0;
+                       int last_key_frame = 0;
+                       int key_frames = 0;
                        switch_status_t encode_status;
+                       int debug_level = 9;
 
                        switch_set_string(codec_settings.video.config_profile_name, "conference");
 
@@ -105,6 +109,8 @@ FST_CORE_BEGIN("conf")
                        frame.timestamp = 0;
                        frame.img = img;
 
+                       switch_core_codec_control(&codec, SCC_DEBUG, SCCT_NONE, &debug_level, SCCT_INT, NULL, NULL, NULL);
+
                        do {
                                frame.datalen = SWITCH_DEFAULT_VIDEO_SIZE;
                                encode_status = switch_core_codec_encode_video(&codec, &frame);
@@ -120,8 +126,21 @@ FST_CORE_BEGIN("conf")
 
                                        if (frame.datalen == 0) break;
 
-                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[%d]: %02x %02x | m=%d | %d\n", loop, buf[12], buf[13], frame.m, frame.datalen);
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "[%d]: %02x %02x | m=%d | %d\n", frames, buf[12], buf[13], frame.m, frame.datalen);
                                        packets++;
+
+                                       if (frame.m) frames++;
+
+                                       if (frames % 20 == 2) {
+                                               switch_core_codec_control(&codec, SCC_VIDEO_GEN_KEYFRAME, SCCT_NONE, NULL, SCCT_NONE, NULL, NULL, NULL);
+                                       }
+
+                                       if (buf[12] == 0x67) {
+                                               key_frames++;
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Key Frame %d last=%d diff=%d\n",
+                                                       key_frames, last_key_frame, frames - last_key_frame);
+                                               last_key_frame = frames;
+                                       }
                                }
 
                        } while(encode_status == SWITCH_STATUS_MORE_DATA || loop-- > 1);