]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7500: Work in progress. Added codec config params that can be set from session...
authorAnthony Minessale <anthm@freeswitch.org>
Sat, 15 Nov 2014 01:01:56 +0000 (19:01 -0600)
committerMichael Jerris <mike@jerris.com>
Thu, 28 May 2015 17:46:44 +0000 (12:46 -0500)
src/include/switch_core_media.h
src/include/switch_module_interfaces.h
src/include/switch_rtp.h
src/include/switch_types.h
src/mod/codecs/mod_vpx/mod_vpx.c
src/mod/formats/mod_vlc/mod_vlc.c
src/switch_core_codec.c
src/switch_core_io.c
src/switch_core_media.c
src/switch_rtp.c

index b0f88acf49a16804c1880b6f0eeac86f53bb718e..8e4f0b74a18ef67eaa6c4814bb4f6d5a3e12180e 100644 (file)
@@ -157,6 +157,9 @@ typedef struct switch_core_media_params_s {
 
        switch_bool_t external_video_source;
 
+       uint32_t video_key_freq;
+       uint32_t video_key_first;
+
 } switch_core_media_params_t;
 
 static inline const char *switch_media_type2str(switch_media_type_t type)
@@ -305,6 +308,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_codec_control(switch_core_sess
                                                                                                                                switch_codec_control_type_t *rtype,
                                                                                                                                void **ret_data);
 
+
+#define switch_core_media_gen_key_frame(_session) switch_core_media_codec_control(_session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_IO_WRITE, \
+                                                                                                                                                                 SCC_VIDEO_REFRESH, SCCT_NONE, NULL, NULL, NULL) \
+
+
 SWITCH_DECLARE(switch_timer_t *) switch_core_media_get_timer(switch_core_session_t *session, switch_media_type_t mtype);
 
 SWITCH_END_EXTERN_C
index f989b2808c0d3fc0ce36b63adef3976dd439720d..0a2dc0946a42494cf89fe1850f1fb57a55b8d72e 100644 (file)
@@ -591,12 +591,21 @@ struct switch_directory_handle {
        void *private_info;
 };
 
-/* nobody has more setting than speex so we will let them set the standard */
-/*! \brief Various codec settings (currently only relevant to speex) */
-struct switch_codec_settings {
+struct switch_audio_codec_settings {
        int unused;
 };
 
+struct switch_video_codec_settings {
+       uint32_t bandwidth;
+       int32_t width;
+       int32_t height;
+};
+
+union switch_codec_settings {
+       struct switch_audio_codec_settings audio;
+       struct switch_video_codec_settings video;
+};
+
 /*! an abstract handle of a fmtp parsed by codec */
 struct switch_codec_fmtp {
        /*! actual samples transferred per second for those who are not moron g722 RFC writers */
index 3046946657f5bd49877d6e03ec4e1a9b5de3e3f8..9e7f9198d8f22bf7c7522ee23dd798cb0fe5986a 100644 (file)
@@ -517,6 +517,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_del_dtls(switch_rtp_t *rtp_session, d
 
 SWITCH_DECLARE(int) switch_rtp_has_dtls(void);
 SWITCH_DECLARE(void) switch_rtp_video_refresh(switch_rtp_t *rtp_session);
+SWITCH_DECLARE(void) switch_rtp_video_loss(switch_rtp_t *rtp_session);
 
 /*!
   \}
index 2dbc4a20a64780eb4f640f01b0045c2c4ce142c9..783ed022201cd7f1a940fe687e2f3cc04e06426d 100644 (file)
@@ -1496,7 +1496,8 @@ typedef enum {
        SFF_RTCP = (1 << 10),
        SFF_MARKER = (1 << 11),
        SFF_WAIT_KEY_FRAME = (1 << 12),
-       SFF_RAW_RTP_PARSE_FRAME = (1 << 13)
+       SFF_RAW_RTP_PARSE_FRAME = (1 << 13),
+       SFF_PICTURE_RESET = (1 << 14)
 } switch_frame_flag_enum_t;
 typedef uint32_t switch_frame_flag_t;
 
@@ -2101,7 +2102,7 @@ typedef struct switch_codec switch_codec_t;
 typedef struct switch_core_thread_session switch_core_thread_session_t;
 typedef struct switch_codec_implementation switch_codec_implementation_t;
 typedef struct switch_buffer switch_buffer_t;
-typedef struct switch_codec_settings switch_codec_settings_t;
+typedef union  switch_codec_settings switch_codec_settings_t;
 typedef struct switch_codec_fmtp switch_codec_fmtp_t;
 typedef struct switch_odbc_handle switch_odbc_handle_t;
 typedef struct switch_pgsql_handle switch_pgsql_handle_t;
index 0fe2b0a1396644b6b6bcad3c25b1b4307d995cfb..2c0028cde5d968f29b039bf5cdc07ca6f737beb1 100644 (file)
 SWITCH_MODULE_LOAD_FUNCTION(mod_vpx_load);
 SWITCH_MODULE_DEFINITION(mod_vpx, mod_vpx_load, NULL, NULL);
 
+
+#define encoder_interface (vpx_codec_vp8_cx())
+#define decoder_interface (vpx_codec_vp8_dx())
+
 struct vpx_context {
        switch_codec_t *codec;
        unsigned int flags;
-
+       switch_codec_settings_t codec_settings;
+       unsigned int bandwidth;
        vpx_codec_enc_cfg_t     config;
 
        vpx_codec_ctx_t encoder;
+       uint8_t encoder_init;
        vpx_image_t *pic;
        switch_bool_t force_key_frame;
-       int width;
-       int height;
-       int bitrate;
        int fps;
        int format;
        int intra_period;
@@ -65,9 +68,8 @@ struct vpx_context {
        const vpx_codec_cx_pkt_t *pkt;
        int pkt_pos;
        vpx_codec_iter_t iter;
-       switch_time_t last_ts;
-
        vpx_codec_ctx_t decoder;
+       uint8_t decoder_init;
        switch_buffer_t *vpx_packet_buffer;
        int got_key_frame;
        switch_size_t last_received_timestamp;
@@ -76,48 +78,17 @@ struct vpx_context {
 };
 typedef struct vpx_context vpx_context_t;
 
-static switch_status_t switch_vpx_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
-{
-       vpx_context_t *context = NULL;
-       int encoding, decoding;
-       vpx_codec_ctx_t *encoder = NULL;
-       vpx_codec_ctx_t *decoder = NULL;
-       vpx_codec_enc_cfg_t *config;
-       const vpx_codec_iface_t* encoder_interface = vpx_codec_vp8_cx();
-       const vpx_codec_iface_t* decoder_interface = vpx_codec_vp8_dx();
-
-
-       encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
-       decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
-
-       if (!(encoding || decoding) || ((context = switch_core_alloc(codec->memory_pool, sizeof(*context))) == 0)) {
-               return SWITCH_STATUS_FALSE;
-       }
-       memset(context, 0, sizeof(*context));
-       context->flags = flags;
-       codec->private_info = context;
 
-       if (codec->fmtp_in) {
-               codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in);
-       }
-
-       config = &context->config;
-
-       if (vpx_codec_enc_config_default(encoder_interface, config, 0) != VPX_CODEC_OK) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder config Error\n");
-               return SWITCH_STATUS_FALSE;
-       }
-
-       // very big defaults till we know why scaling segs it
-       context->width = 3840;
-       context->height = 2160;
-       context->bitrate = 3840000;
+static switch_status_t init_codec(switch_codec_t *codec)
+{
+       vpx_context_t *context = (vpx_context_t *)codec->private_info;
+       vpx_codec_enc_cfg_t *config = &context->config;
 
        // settings
        config->g_profile = 1;
-       config->g_w = context->width;
-       config->g_h = context->height;
-       config->rc_target_bitrate = context->bitrate;
+       config->g_w = context->codec_settings.video.width;
+       config->g_h = context->codec_settings.video.height;
+       config->rc_target_bitrate = context->bandwidth;
        config->g_timebase.num = 1;
        config->g_timebase.den = 1000;
        config->g_error_resilient = VPX_ERROR_RESILIENT_PARTITIONS;
@@ -127,11 +98,11 @@ static switch_status_t switch_vpx_init(switch_codec_t *codec, switch_codec_flag_
        config->rc_dropframe_thresh = 0;
        config->rc_end_usage = VPX_CBR;
        config->g_pass = VPX_RC_ONE_PASS;
-       // config->kf_mode = VPX_KF_DISABLED;
-       config->kf_mode = VPX_KF_AUTO;
-       // config->kf_min_dist = FPS;// Intra Period 3 seconds;
-       // config->kf_max_dist = FPS * 3;
-       config->rc_resize_allowed = 0;
+       config->kf_mode = VPX_KF_DISABLED;
+       //config->kf_mode = VPX_KF_AUTO;
+       //config->kf_min_dist = FPS;// Intra Period 3 seconds;
+       //config->kf_max_dist = FPS;
+       config->rc_resize_allowed = 1;
        config->rc_min_quantizer = 2;
        config->rc_max_quantizer = 56;
        //Rate control adaptation undershoot control.
@@ -157,59 +128,74 @@ static switch_status_t switch_vpx_init(switch_codec_t *codec, switch_codec_flag_
        //      indicates that the client will buffer (at least) 5000ms worth
        //      of encoded data. Use the target bitrate (rc_target_bitrate) to
        //      convert to bits/bytes, if necessary.
-       config->rc_buf_sz = 1000;
+       config->rc_buf_sz = 5000;
        //Decoder Buffer Initial Size.
        //      This value indicates the amount of data that will be buffered
        //      by the decoding application prior to beginning playback.
        //      This value is expressed in units of time (milliseconds).
        //      Use the target bitrate (rc_target_bitrate) to convert to
        //      bits/bytes, if necessary.
-       config->rc_buf_initial_sz = 500;
+       config->rc_buf_initial_sz = 1000;
        //Decoder Buffer Optimal Size.
        //      This value indicates the amount of data that the encoder should
        //      try to maintain in the decoder's buffer. This value is expressed
        //      in units of time (milliseconds).
        //      Use the target bitrate (rc_target_bitrate) to convert to
        //      bits/bytes, if necessary.
-       config->rc_buf_optimal_sz = 600;
+       config->rc_buf_optimal_sz = 1000;
+
+       if (context->flags & SWITCH_CODEC_FLAG_ENCODE) {
+
+               if (context->encoder_init) {
+                       vpx_codec_destroy(&context->encoder);
+                       context->encoder_init = 0;
+               }
 
-       if (encoding) {
                if (vpx_codec_enc_init(&context->encoder, encoder_interface, config, 0 & VPX_CODEC_USE_OUTPUT_PARTITION) != VPX_CODEC_OK) {
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec init error: [%d:%s]\n", encoder->err, encoder->err_detail);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec init error: [%d:%s]\n", context->encoder.err, context->encoder.err_detail);
                        return SWITCH_STATUS_FALSE;
                }
 
+               context->encoder_init = 1;
+
                // The static threshold imposes a change threshold on blocks below which they will be skipped by the encoder.
-               vpx_codec_control(encoder, VP8E_SET_STATIC_THRESHOLD, 100);
+               vpx_codec_control(&context->encoder, VP8E_SET_STATIC_THRESHOLD, 100);
                //Set cpu usage, a bit lower than normal (-6) but higher than android (-12)
-               vpx_codec_control(encoder, VP8E_SET_CPUUSED, -8);
+               vpx_codec_control(&context->encoder, VP8E_SET_CPUUSED, -6);
                // Only one partition
-               // vpx_codec_control(encoder, VP8E_SET_TOKEN_PARTITIONS, VP8_ONE_TOKENPARTITION);
+               // vpx_codec_control(&context->encoder, VP8E_SET_TOKEN_PARTITIONS, VP8_ONE_TOKENPARTITION);
                // Enable noise reduction
-               vpx_codec_control(encoder, VP8E_SET_NOISE_SENSITIVITY, 0);
+               vpx_codec_control(&context->encoder, VP8E_SET_NOISE_SENSITIVITY, 1);
                //Set max data rate for Intra frames.
                //      This value controls additional clamping on the maximum size of a keyframe.
                //      It is expressed as a percentage of the average per-frame bitrate, with the
                //      special (and default) value 0 meaning unlimited, or no additional clamping
                //      beyond the codec's built-in algorithm.
                //      For example, to allocate no more than 4.5 frames worth of bitrate to a keyframe, set this to 450.
-               vpx_codec_control(encoder, VP8E_SET_MAX_INTRA_BITRATE_PCT, 0);
+               vpx_codec_control(&context->encoder, VP8E_SET_MAX_INTRA_BITRATE_PCT, 0);
        }
 
-       if (decoding) {
+       if (context->flags & SWITCH_CODEC_FLAG_DECODE) {
                vp8_postproc_cfg_t ppcfg;
 
+               if (context->decoder_init) {
+                       vpx_codec_destroy(&context->decoder);
+                       context->decoder_init = 0;
+               }
+
                if (vpx_codec_dec_init(&context->decoder, decoder_interface, NULL, VPX_CODEC_USE_POSTPROC) != VPX_CODEC_OK) {
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec init error: [%d:%s]\n", encoder->err, encoder->err_detail);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Codec init error: [%d:%s]\n", context->encoder.err, context->encoder.err_detail);
                        return SWITCH_STATUS_FALSE;
                }
 
+               context->decoder_init = 1;
+
                // the types of post processing to be done, should be combination of "vp8_postproc_level"
                ppcfg.post_proc_flag = VP8_DEMACROBLOCK | VP8_DEBLOCK;
                // the strength of deblocking, valid range [0, 16]
                ppcfg.deblocking_level = 3;
                // Set deblocking settings
-               vpx_codec_control(decoder, VP8_SET_POSTPROC, &ppcfg);
+               vpx_codec_control(&context->decoder, VP8_SET_POSTPROC, &ppcfg);
 
                switch_buffer_create_dynamic(&context->vpx_packet_buffer, 512, 512, 1024000);
        }
@@ -217,6 +203,39 @@ static switch_status_t switch_vpx_init(switch_codec_t *codec, switch_codec_flag_
        return SWITCH_STATUS_SUCCESS;
 }
 
+static switch_status_t switch_vpx_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
+{
+       vpx_context_t *context = NULL;
+       int encoding, decoding;
+
+
+       encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
+       decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
+
+       if (!(encoding || decoding) || ((context = switch_core_alloc(codec->memory_pool, sizeof(*context))) == 0)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       memset(context, 0, sizeof(*context));
+       context->flags = flags;
+       codec->private_info = context;
+
+       if (codec_settings) {
+               context->codec_settings = *codec_settings;
+       }
+
+       if (codec->fmtp_in) {
+               codec->fmtp_out = switch_core_strdup(codec->memory_pool, codec->fmtp_in);
+       }
+
+       if (vpx_codec_enc_config_default(encoder_interface, &context->config, 0) != VPX_CODEC_OK) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder config Error\n");
+               return SWITCH_STATUS_FALSE;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
 /*     http://tools.ietf.org/html/draft-ietf-payload-vp8-10
 
        The first octets after the RTP header are the VP8 payload descriptor, with the following structure.
@@ -313,8 +332,8 @@ static switch_status_t consume_partition(vpx_context_t *context, void *data, uin
 }
 
 static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_image_t *img,
-                                                                                 void *encoded_data, uint32_t *encoded_data_len,
-                                                                                 unsigned int *flag)
+                                                                                void *encoded_data, uint32_t *encoded_data_len,
+                                                                                unsigned int *flag)
 {
        vpx_context_t *context = (vpx_context_t *)codec->private_info;
        uint32_t duration = 90000 / FPS;
@@ -332,6 +351,8 @@ static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_image_t *
 
        //d_w and d_h are messed up
 
+       //printf("WTF %d %d\n", img->d_w, img->d_h);
+
        width = img->w;
        height = img->h;
 
@@ -339,28 +360,31 @@ static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_image_t *
        //switch_assert(height > 0 && (height % 4 == 0));
 
        if (context->config.g_w != width || context->config.g_h != height) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VPX reset encoder picture from %dx%d to %dx%d\n", context->config.g_w, context->config.g_h, width, height);
-               context->config.g_w = width;
-               context->config.g_h = height;
-               if (vpx_codec_enc_config_set(&context->encoder, &context->config) != VPX_CODEC_OK) {
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX reset config error!");
+               context->codec_settings.video.width = width;
+               context->codec_settings.video.height = height;
+               if (context->codec_settings.video.bandwidth) {
+                       context->bandwidth = context->codec_settings.video.bandwidth;
+               } else {
+                       context->bandwidth = width * height * 8;
+               }
+
+               if (context->bandwidth > 1250000) {
+                       context->bandwidth = 1250000;
                }
-       }
 
-       if (context->last_ts == 0) context->last_ts = switch_micro_time_now();
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_NOTICE, 
+                                                 "VPX reset encoder picture from %dx%d to %dx%d %u BW\n", 
+                                                 context->config.g_w, context->config.g_h, width, height, context->bandwidth);
 
-       if ((switch_micro_time_now() - context->last_ts) > 2 * 1000000) {
-               // the config params doesn't seems work for generate regular key frames,
-               // so we do some trick here to force a key frame every 2 sec
-               // vpx_flags = VPX_EFLAG_FORCE_KF;
-               context->last_ts = switch_micro_time_now();
+               init_codec(codec);
+               *flag |= SFF_PICTURE_RESET;
+               context->need_key_frame = 1;
        }
 
        if (context->need_key_frame > 0) {
                // force generate a key frame
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VPX KEYFRAME REQ\n");
                vpx_flags |= VPX_EFLAG_FORCE_KF;
-               context->last_ts = switch_micro_time_now();
                context->need_key_frame--;
        }
 
@@ -539,7 +563,7 @@ static switch_status_t switch_vpx_destroy(switch_codec_t *codec)
 
        if (context) {
                if ((codec->flags & SWITCH_CODEC_FLAG_ENCODE)) {
-                       vpx_codec_destroy(&context->encoder); // TODO fix crash
+                       vpx_codec_destroy(&context->encoder);
                }
 
                if ((codec->flags & SWITCH_CODEC_FLAG_DECODE)) {
index 9c50f6de9274679501cfdc6fe197500e7b04c353..28c5e576b8c8f29d8ad02f76bfce1d22c829a077 100644 (file)
@@ -102,6 +102,7 @@ struct vlc_video_context {
        switch_mutex_t *video_mutex;
 
        switch_core_session_t *session;
+       switch_channel_t *channel;
        switch_frame_t *aud_frame;
        switch_frame_t *vid_frame;
        uint8_t video_packet[1500 + 12];
@@ -230,20 +231,11 @@ static void *vlc_video_lock_callback(void *data, void **p_pixels)
        return NULL; /* picture identifier, not needed here */
 }
 
-/* dummy callback so it should be good when no video on channel */
-static void vlc_video_unlock_dummy_callback(void *data, void *id, void *const *p_pixels)
-{
-       vlc_video_context_t *context = (vlc_video_context_t *)data;
-       assert(id == NULL); /* picture identifier, not needed here */
-       switch_mutex_unlock(context->video_mutex);
-}
-
 static void vlc_video_unlock_callback(void *data, void *id, void *const *p_pixels)
 {
        vlc_video_context_t *context = (vlc_video_context_t *) data;
-       switch_frame_t *frame = context->vid_frame;
 
-       switch_assert(id == NULL); /* picture identifier, not needed here */
+       if (context->channel && !switch_channel_test_flag(context->channel, CF_VIDEO)) return;
 
        if (!context->img) context->img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, context->width, context->height, 0);
 
@@ -251,14 +243,11 @@ static void vlc_video_unlock_callback(void *data, void *id, void *const *p_pixel
 
        yuyv_to_i420(*p_pixels, context->img->img_data, context->width, context->height);
 
-       switch_core_session_write_video_image(context->session, frame, context->img, SWITCH_DEFAULT_VIDEO_SIZE, NULL);
-
        switch_mutex_unlock(context->video_mutex);
 }
 
-static void do_buffer_frame(vlc_video_context_t *context)
+static void do_buffer_frame(vlc_video_context_t *context, switch_frame_t *frame)
 {
-       switch_frame_t *frame = context->vid_frame;
        uint32_t size = sizeof(*frame) + frame->packetlen;
 
        switch_mutex_lock(context->video_mutex);
@@ -277,32 +266,35 @@ static void do_buffer_frame(vlc_video_context_t *context)
 static void vlc_video_channel_unlock_callback(void *data, void *id, void *const *p_pixels)
 {
        vlc_video_context_t *context = (vlc_video_context_t *)data;
-       uint32_t flag = 0;
-       switch_frame_t *frame = context->vid_frame;
+
 
        switch_assert(id == NULL); /* picture identifier, not needed here */
 
+       if (context->channel && !switch_channel_test_flag(context->channel, CF_VIDEO)) return;
+
        if (!context->img) context->img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, context->width, context->height, 0);
        switch_assert(context->img);
 
        yuyv_to_i420(*p_pixels, context->img->img_data, context->width, context->height);
 
-
-       if (context->video_refresh_req > 0) {
-               flag |= SFF_WAIT_KEY_FRAME;
-               context->video_refresh_req--;
-       }
-
-       switch_core_session_write_video_image(context->session, frame, context->img, SWITCH_DEFAULT_VIDEO_SIZE, &flag);
-
        switch_mutex_unlock(context->video_mutex);
 }
 
 static void vlc_video_display_callback(void *data, void *id)
 {
+       vlc_video_context_t *context = (vlc_video_context_t *) data;
+       int32_t flag = 0;
+
        /* VLC wants to display the video */
-       (void) data;
-       assert(id == NULL);
+
+       if (context->channel && !switch_channel_test_flag(context->channel, CF_VIDEO)) return;
+
+       if (context->video_refresh_req > 0) {
+               flag |= SFF_WAIT_KEY_FRAME;
+               context->video_refresh_req--;
+       }
+
+       switch_core_session_write_video_image(context->session, context->vid_frame, context->img, SWITCH_DEFAULT_VIDEO_SIZE, NULL);
 }
 
 unsigned video_format_setup_callback(void **opaque, char *chroma, unsigned *width, unsigned *height, unsigned *pitches, unsigned *lines)
@@ -723,7 +715,9 @@ SWITCH_STANDARD_APP(play_video_function)
 
        audio_datalen = read_impl.decoded_bytes_per_packet; //codec.implementation->actual_samples_per_second / 1000 * (read_impl.microseconds_per_packet / 1000);
 
+
        context->session = session;
+       context->channel = channel;
        context->pool = pool;
        context->aud_frame = &audio_frame;
        context->vid_frame = &video_frame;
@@ -770,14 +764,8 @@ SWITCH_STANDARD_APP(play_video_function)
        libvlc_audio_set_format(context->mp, "S16N", read_impl.actual_samples_per_second, read_impl.number_of_channels);
        libvlc_audio_set_callbacks(context->mp, vlc_play_audio_callback, NULL,NULL,NULL,NULL, (void *) context);
 
-       if (switch_channel_test_flag(channel, CF_VIDEO)) {
-               // libvlc_video_set_format(context->mp, "YUYV", VIDEOWIDTH, VIDEOHEIGHT, VIDEOWIDTH * 2);
-               libvlc_video_set_format_callbacks(context->mp, video_format_setup_callback, video_format_clean_callback);
-               libvlc_video_set_callbacks(context->mp, vlc_video_lock_callback, vlc_video_unlock_callback, vlc_video_display_callback, context);
-       } else {
-               libvlc_video_set_format_callbacks(context->mp, video_format_setup_callback, video_format_clean_callback);
-               libvlc_video_set_callbacks(context->mp, vlc_video_lock_callback, vlc_video_unlock_dummy_callback, vlc_video_display_callback, context);
-       }
+       libvlc_video_set_format_callbacks(context->mp, video_format_setup_callback, video_format_clean_callback);
+       libvlc_video_set_callbacks(context->mp, vlc_video_lock_callback, vlc_video_unlock_callback, vlc_video_display_callback, context);
 
        // start play
        if (-1 == libvlc_media_player_play(context->mp)) {
@@ -928,6 +916,15 @@ switch_io_routines_t vlc_io_routines = {
        /*state_run*/ NULL
 };
 
+static switch_status_t vlc_channel_img_callback(switch_core_session_t *session, switch_frame_t *frame, switch_image_t *img, void *user_data)
+{
+       vlc_video_context_t *context = (vlc_video_context_t *) user_data;
+
+       do_buffer_frame(context, frame);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
 static switch_status_t setup_tech_pvt(switch_core_session_t *session, const char *path)
 {
        switch_channel_t *channel = switch_core_session_get_channel(session);
@@ -952,11 +949,12 @@ static switch_status_t setup_tech_pvt(switch_core_session_t *session, const char
        memset(context, 0, sizeof(vlc_file_context_t));
        tech_pvt->context = context;
 
+
        switch_buffer_create_dynamic(&(context->audio_buffer), VLC_BUFFER_SIZE, VLC_BUFFER_SIZE * 8, 0);
 
-       if (switch_channel_test_flag(channel, CF_VIDEO)) {
-               switch_buffer_create_dynamic(&(context->video_buffer), VLC_BUFFER_SIZE * 2, VLC_BUFFER_SIZE * 16, 0);
-       }
+       switch_buffer_create_dynamic(&(context->video_buffer), VLC_BUFFER_SIZE * 2, VLC_BUFFER_SIZE * 16, 0);
+
+       switch_core_session_set_image_write_callback(session, vlc_channel_img_callback, tech_pvt->context);
 
        if (switch_core_timer_init(&tech_pvt->timer, "soft", 20,
                                                           8000 / (1000 / 20), pool) != SWITCH_STATUS_SUCCESS) {
@@ -969,6 +967,9 @@ static switch_status_t setup_tech_pvt(switch_core_session_t *session, const char
        context->pool = pool;
        context->aud_frame = &tech_pvt->read_frame;
        context->vid_frame = &tech_pvt->read_video_frame;
+       context->vid_frame->packet = context->video_packet;
+       context->vid_frame->data = context->video_packet + 12;
+
        context->playing = 0;
        // context->err = 0;
 
@@ -1010,14 +1011,10 @@ static switch_status_t setup_tech_pvt(switch_core_session_t *session, const char
        libvlc_audio_set_format(context->mp, "S16N", 8000, 1);
        libvlc_audio_set_callbacks(context->mp, vlc_play_audio_callback, NULL,NULL,NULL,NULL, (void *) context);
 
-       if (switch_channel_test_flag(channel, CF_VIDEO)) {
-               // libvlc_video_set_format(context->mp, "YUYV", VIDEOWIDTH, VIDEOHEIGHT, VIDEOWIDTH * 2);
-               libvlc_video_set_format_callbacks(context->mp, video_format_setup_callback, video_format_clean_callback);
-               libvlc_video_set_callbacks(context->mp, vlc_video_lock_callback, vlc_video_channel_unlock_callback, vlc_video_display_callback, context);
-       } else {
-               libvlc_video_set_format_callbacks(context->mp, video_format_setup_callback, video_format_clean_callback);
-               libvlc_video_set_callbacks(context->mp, vlc_video_lock_callback, vlc_video_unlock_dummy_callback, vlc_video_display_callback, context);
-       }
+       
+       libvlc_video_set_format_callbacks(context->mp, video_format_setup_callback, video_format_clean_callback);
+       libvlc_video_set_callbacks(context->mp, vlc_video_lock_callback, vlc_video_channel_unlock_callback, vlc_video_display_callback, context);
+
 
        return SWITCH_STATUS_SUCCESS;
 
@@ -1026,25 +1023,13 @@ fail:
        return status;
 }
 
-static switch_status_t vlc_channel_img_callback(switch_core_session_t *session, switch_frame_t *frame, switch_image_t *img, void *user_data)
-{
-       vlc_video_context_t *context = (vlc_video_context_t *) user_data;
-
-       do_buffer_frame(context);
-
-       return SWITCH_STATUS_SUCCESS;
-}
-
-
 static switch_status_t channel_on_init(switch_core_session_t *session)
 {
        switch_channel_t *channel = switch_core_session_get_channel(session);
-       vlc_private_t *tech_pvt = switch_core_session_get_private(session);
+       //vlc_private_t *tech_pvt = switch_core_session_get_private(session);
 
        switch_channel_set_state(channel, CS_CONSUME_MEDIA);
 
-       switch_core_session_set_image_write_callback(session, vlc_channel_img_callback, tech_pvt->context);
-
        return SWITCH_STATUS_SUCCESS;
 }
 
@@ -1096,6 +1081,10 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session)
                switch_buffer_destroy(&tech_pvt->context->audio_buffer);
        }
 
+       if (tech_pvt->context->video_buffer) {
+               switch_buffer_destroy(&tech_pvt->context->video_buffer);
+       }
+
        if (tech_pvt->timer.interval) {
                switch_core_timer_destroy(&tech_pvt->timer);
        }
index ef776c790f03bcf1563c13e797e5bddcca3380c3..0e392edcbb676b7578473772671d18edffff79a6 100644 (file)
@@ -646,6 +646,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_init_with_bitrate(switch_codec
 
        memset(codec, 0, sizeof(*codec));
 
+       if (pool) {
+               codec->session = switch_core_memory_pool_get_data(pool, "__session");
+       }
+
        if ((codec_interface = switch_loadable_module_get_codec_interface(codec_name)) == 0) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid codec %s!\n", codec_name);
                return SWITCH_STATUS_GENERR;
index f7515b926423b7e102453f7f9337f1c722174193..85e6b8ce0ebe4e906ed4eef33e2d979bf6d3f140 100644 (file)
 #include <switch.h>
 #include "private/switch_core_pvt.h"
 
-SWITCH_DECLARE(void) switch_core_session_set_image_write_callback(switch_core_session_t *session, switch_image_write_callback_t callback, void *user_data)
-{
-       session->image_write_callback = callback;
-       session->image_write_callback_user_data = user_data;
-}
-
-SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_image(switch_core_session_t *session, switch_frame_t *frame, 
-                                                                                                                                         switch_image_t *img, switch_size_t size, uint32_t *flag)
-{
-       uint32_t encoded_data_len = size, lflag = 0, *flagp = flag;
-       switch_codec_t *codec = switch_core_session_get_video_write_codec(session);
-       switch_timer_t *timer;
-
-       switch_assert(session);
-
-       if (!flag) {
-               flagp = &lflag;
-       }
-
-       timer = switch_core_media_get_timer(session, SWITCH_MEDIA_TYPE_VIDEO);
-       switch_assert(timer);
-
-       switch_core_codec_encode_video(codec, img, frame->data, &encoded_data_len, flagp);
-
-       while(encoded_data_len) {
-
-               frame->datalen = encoded_data_len;
-               frame->packetlen = frame->datalen + 12;
-               frame->m = (*flagp & SFF_MARKER) ? 1 : 0;
-               frame->timestamp = timer->samplecount;
-
-               switch_set_flag(frame, SFF_RAW_RTP_PARSE_FRAME);
-               
-               switch_core_session_write_video_frame(session, frame, SWITCH_IO_FLAG_NONE, 0);
-
-               if (session->image_write_callback) {
-                       session->image_write_callback(session, frame, img, session->image_write_callback_user_data);
-               }
-
-               encoded_data_len = size;
-               switch_core_codec_encode_video(codec, NULL, frame->data, &encoded_data_len, flagp);     
-       }
-
-       return SWITCH_STATUS_SUCCESS;
-}
-
-
-SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags,
-                                                                                                                                         int stream_id)
-{
-       switch_io_event_hook_video_write_frame_t *ptr;
-       switch_status_t status = SWITCH_STATUS_FALSE;
-
-       if (switch_channel_down(session->channel)) {
-               return SWITCH_STATUS_FALSE;
-       }
-
-       if (switch_channel_test_flag(session->channel, CF_VIDEO_PAUSE)) {
-               return SWITCH_STATUS_SUCCESS;
-       }
-
-       if (session->endpoint_interface->io_routines->write_video_frame) {
-               if ((status = session->endpoint_interface->io_routines->write_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
-                       for (ptr = session->event_hooks.video_write_frame; ptr; ptr = ptr->next) {
-                               if ((status = ptr->video_write_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
-                                       break;
-                               }
-                       }
-               }
-       }
-       return status;
-}
-
-SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags,
-                                                                                                                                        int stream_id)
-{
-       switch_status_t status = SWITCH_STATUS_FALSE;
-       switch_io_event_hook_video_read_frame_t *ptr;
-
-       switch_assert(session != NULL);
-
-       if (switch_channel_down(session->channel)) {
-               return SWITCH_STATUS_FALSE;
-       }
-
-       if (switch_channel_test_flag(session->channel, CF_VIDEO_PAUSE)) {
-               *frame = &runtime.dummy_cng_frame;
-               switch_yield(20000);
-               return SWITCH_STATUS_SUCCESS;
-       }
-
-       if (session->endpoint_interface->io_routines->read_video_frame) {
-               if ((status = session->endpoint_interface->io_routines->read_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
-                       for (ptr = session->event_hooks.video_read_frame; ptr; ptr = ptr->next) {
-                               if ((status = ptr->video_read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       if (status == SWITCH_STATUS_INUSE) {
-               *frame = &runtime.dummy_cng_frame;
-               switch_yield(20000);
-               return SWITCH_STATUS_SUCCESS;
-       }
-
-       if (status != SWITCH_STATUS_SUCCESS) {
-               goto done;
-       }
-
-       if (!(*frame)) {
-               goto done;
-       }
-
-       if (switch_test_flag(*frame, SFF_CNG)) {
-               status = SWITCH_STATUS_SUCCESS;
-               goto done;
-       }
-
-       if (session->bugs) {
-               switch_media_bug_t *bp;
-               switch_bool_t ok = SWITCH_TRUE;
-               int prune = 0;
-               switch_thread_rwlock_rdlock(session->bug_rwlock);
-               for (bp = session->bugs; bp; bp = bp->next) {
-                       if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
-                               continue;
-                       }
-
-                       if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) {
-                               continue;
-                       }
-
-                       if (switch_test_flag(bp, SMBF_PRUNE)) {
-                               prune++;
-                               continue;
-                       }
-
-                       if (bp->ready && switch_test_flag(bp, SMBF_READ_PING)) {
-                               switch_mutex_lock(bp->read_mutex);
-                               bp->ping_frame = *frame;
-                               if (bp->callback) {
-                                       if (bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_VIDEO_PING) == SWITCH_FALSE
-                                               || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
-                                               ok = SWITCH_FALSE;
-                                       }
-                               }
-                               bp->ping_frame = NULL;;
-                               switch_mutex_unlock(bp->read_mutex);
-                       }
-
-                       if (ok == SWITCH_FALSE) {
-                               switch_set_flag(bp, SMBF_PRUNE);
-                               prune++;
-                       }
-               }
-               switch_thread_rwlock_unlock(session->bug_rwlock);
-               if (prune) {
-                       switch_core_media_bug_prune(session);
-               }
-       }
-
-  done:
-
-       return status;
-}
-
 SWITCH_DECLARE(void) switch_core_gen_encoded_silence(unsigned char *data, const switch_codec_implementation_t *read_impl, switch_size_t len)
 {
        unsigned char g729_filler[] = {
index 5b620548c1088d04aacb4b319bcd0962fe062c18..99a9620c34e1291c40246c5fb317e063c2b01caa 100644 (file)
@@ -154,6 +154,9 @@ typedef struct switch_rtp_engine_s {
        uint8_t pli;
        uint8_t nack;
        uint8_t no_crypto;
+
+       switch_codec_settings_t codec_settings;
+       
 } switch_rtp_engine_t;
 
 
@@ -190,6 +193,9 @@ struct switch_media_handle_s {
 
        switch_rtp_crypto_mode_t crypto_mode;
        switch_rtp_crypto_key_type_t crypto_suite_order[CRYPTO_INVALID+1];
+       switch_time_t video_last_key_time;
+       switch_time_t video_init;
+       switch_timer_t video_timer;
 };
 
 
@@ -1436,6 +1442,10 @@ SWITCH_DECLARE(void) switch_media_handle_destroy(switch_core_session_t *session)
        v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];      
 
        
+       if (smh->video_timer.timer_interface) {
+               switch_core_timer_destroy(&smh->video_timer);
+       }
+
        if (switch_core_codec_ready(&a_engine->read_codec)) {
                switch_core_codec_destroy(&a_engine->read_codec);
        }
@@ -1498,6 +1508,15 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t
                }
 
                session->media_handle->mparams = params;
+               
+               if (!session->media_handle->mparams->video_key_freq) {
+                       session->media_handle->mparams->video_key_freq = 15000000;
+               }
+
+               if (!session->media_handle->mparams->video_key_first) {
+                       session->media_handle->mparams->video_key_first = 1000000;
+               }
+
 
                for (i = 0; i <= CRYPTO_INVALID; i++) {
                        session->media_handle->crypto_suite_order[i] = CRYPTO_INVALID;
@@ -2262,6 +2281,43 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_get_offered_pt(switch_core_ses
        return SWITCH_STATUS_FALSE;
 }
 
+//#define get_int_value(_var, _set) { const char *__v = switch_channel_get_variable(session->channel, _var); if (__v) { _set = atol(__v);} }
+//?
+static void switch_core_session_parse_codec_settings(switch_core_session_t *session, switch_media_type_t type) 
+{
+       switch_media_handle_t *smh;
+       switch_rtp_engine_t *engine;
+
+       switch_assert(session);
+
+       if (!(smh = session->media_handle)) {
+               return;
+       }
+
+       if ((engine = &smh->engines[type]));
+       
+       switch(type) {
+       case SWITCH_MEDIA_TYPE_AUDIO:
+               break;
+       case SWITCH_MEDIA_TYPE_VIDEO: 
+               {
+                       const char *bwv = switch_channel_get_variable(session->channel, "video_codec_bandwidth");
+                       uint32_t bw = 0;
+
+                       if (bwv && (bw = (uint32_t) atol(bwv))) {
+                               if (switch_stristr("kb", bwv)) {
+                                       bw *= 125;
+                               } else if (switch_stristr("mb", bwv)) {
+                                       bw *= 125000;
+                               }
+                               engine->codec_settings.video.bandwidth = bw;
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+}
 
 
 //?
@@ -2300,7 +2356,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
                }
        }
 
-
+       switch_core_session_parse_codec_settings(session, SWITCH_MEDIA_TYPE_VIDEO);
 
        if (switch_core_codec_init(&v_engine->read_codec,
                                                           v_engine->cur_payload_map->rm_encoding,
@@ -2309,7 +2365,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
                                                           0,
                                                           1,
                                                           SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
-                                                          NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+                                                          &v_engine->codec_settings, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
                return SWITCH_STATUS_FALSE;
        } else {
@@ -2320,7 +2376,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
                                                                   0,
                                                                   1,
                                                                   SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
-                                                                  NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+                                                                  &v_engine->codec_settings, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
                        return SWITCH_STATUS_FALSE;
                } else {
@@ -2361,7 +2417,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_codec(switch_core_se
                        switch_channel_set_variable(session->channel, "rtp_use_video_codec_fmtp", v_engine->cur_payload_map->rm_fmtp);
                        switch_channel_set_variable_printf(session->channel, "rtp_use_video_codec_rate", "%d", v_engine->cur_payload_map->rm_rate);
                        switch_channel_set_variable_printf(session->channel, "rtp_use_video_codec_ptime", "%d", 0);
-
                }
        }
        return SWITCH_STATUS_SUCCESS;
@@ -2437,6 +2492,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
                }
        }
 
+
+       switch_core_session_parse_codec_settings(session, SWITCH_MEDIA_TYPE_AUDIO);
+
        if (switch_core_codec_init_with_bitrate(&a_engine->read_codec,
                                                                                        a_engine->cur_payload_map->iananame,
                                                                                        a_engine->cur_payload_map->rm_fmtp,
@@ -2445,7 +2503,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
                                                                                        a_engine->cur_payload_map->channels,
                                                                                        a_engine->cur_payload_map->bitrate,
                                                                                        SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | codec_flags,
-                                                                                       NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+                                                                                       &a_engine->codec_settings, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
                switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
                switch_goto_status(SWITCH_STATUS_FALSE, end);
@@ -2462,7 +2520,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_set_codec(switch_core_session_
                                                                                        a_engine->cur_payload_map->channels,
                                                                                        a_engine->cur_payload_map->bitrate,
                                                                                        SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | codec_flags,
-                                                                                       NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+                                                                                       &a_engine->codec_settings, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
                switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
                switch_goto_status(SWITCH_STATUS_FALSE, end);
@@ -7210,8 +7268,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                        pli++;
                                        nack++;
                                }
-
-                               nack = v_engine->nack = pli = v_engine->pli = 0;
+                               
+                               nack = v_engine->nack = 0;//pli = v_engine->pli = 0;
                                
                                if (vp8) {
                                        
@@ -9502,6 +9560,223 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_codec_control(switch_core_sess
        return SWITCH_STATUS_FALSE;
 }
 
+
+SWITCH_DECLARE(void) switch_core_session_set_image_write_callback(switch_core_session_t *session, switch_image_write_callback_t callback, void *user_data)
+{
+       session->image_write_callback = callback;
+       session->image_write_callback_user_data = user_data;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_image(switch_core_session_t *session, switch_frame_t *frame, 
+                                                                                                                                         switch_image_t *img, switch_size_t size, uint32_t *flag)
+{
+       uint32_t encoded_data_len = size, lflag = 0, *flagp = flag;
+       switch_codec_t *codec = switch_core_session_get_video_write_codec(session);
+       switch_timer_t *timer;
+       switch_media_handle_t *smh;
+       //switch_rtp_engine_t *v_engine;
+
+       switch_assert(session);
+
+       if (!(smh = session->media_handle)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       //v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];    
+
+
+       if (!flag) {
+               flagp = &lflag;
+       }
+
+       if (!(timer = switch_core_media_get_timer(session, SWITCH_MEDIA_TYPE_VIDEO))) {
+
+               if (!smh->video_timer.timer_interface) {
+                       switch_core_timer_init(&smh->video_timer, "soft", 1, 90, switch_core_session_get_pool(session));
+               }
+
+               timer = &smh->video_timer;
+       }
+
+
+       do {
+               encoded_data_len = size;
+               switch_core_codec_encode_video(codec, img, frame->data, &encoded_data_len, flagp);
+
+               if (*flagp & SFF_PICTURE_RESET) {
+                       smh->video_init = 0;
+                       smh->video_last_key_time = 0;
+                       *flagp &= ~SFF_PICTURE_RESET;
+               }
+
+               frame->datalen = encoded_data_len;
+               frame->packetlen = frame->datalen + 12;
+               frame->m = (*flagp & SFF_MARKER) ? 1 : 0;
+               frame->timestamp = timer->samplecount;
+
+               switch_set_flag(frame, SFF_RAW_RTP_PARSE_FRAME);
+               
+               switch_core_session_write_video_frame(session, frame, SWITCH_IO_FLAG_NONE, 0);
+
+               if (session->image_write_callback) {
+                       session->image_write_callback(session, frame, img, session->image_write_callback_user_data);
+               }
+
+               img = NULL;
+
+       } while(encoded_data_len);
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_core_session_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags,
+                                                                                                                                         int stream_id)
+{
+       switch_io_event_hook_video_write_frame_t *ptr;
+       switch_status_t status = SWITCH_STATUS_FALSE;
+       switch_media_handle_t *smh;
+
+       switch_time_t now = switch_micro_time_now();
+
+       switch_assert(session);
+
+       if (!(smh = session->media_handle)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (switch_channel_down(session->channel)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (switch_channel_test_flag(session->channel, CF_VIDEO_PAUSE)) {
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       if (!smh->video_init && smh->mparams->video_key_first && (now - smh->video_last_key_time) > smh->mparams->video_key_first) {
+               switch_core_media_gen_key_frame(smh->session);
+
+               if (smh->video_last_key_time) {
+                       smh->video_init = 1;
+               }
+
+               smh->video_last_key_time = now;
+       }       
+
+       if (smh->mparams->video_key_freq && (now - smh->video_last_key_time) > smh->mparams->video_key_freq) {
+               switch_core_media_gen_key_frame(smh->session);
+               smh->video_last_key_time = now;
+       }       
+
+       if (session->endpoint_interface->io_routines->write_video_frame) {
+               if ((status = session->endpoint_interface->io_routines->write_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
+                       for (ptr = session->event_hooks.video_write_frame; ptr; ptr = ptr->next) {
+                               if ((status = ptr->video_write_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       return status;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_core_session_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags,
+                                                                                                                                        int stream_id)
+{
+       switch_status_t status = SWITCH_STATUS_FALSE;
+       switch_io_event_hook_video_read_frame_t *ptr;
+
+       switch_assert(session != NULL);
+
+       if (switch_channel_down(session->channel)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (switch_channel_test_flag(session->channel, CF_VIDEO_PAUSE)) {
+               *frame = &runtime.dummy_cng_frame;
+               switch_yield(20000);
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       if (session->endpoint_interface->io_routines->read_video_frame) {
+               if ((status = session->endpoint_interface->io_routines->read_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
+                       for (ptr = session->event_hooks.video_read_frame; ptr; ptr = ptr->next) {
+                               if ((status = ptr->video_read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (status == SWITCH_STATUS_INUSE) {
+               *frame = &runtime.dummy_cng_frame;
+               switch_yield(20000);
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       if (status != SWITCH_STATUS_SUCCESS) {
+               goto done;
+       }
+
+       if (!(*frame)) {
+               goto done;
+       }
+
+       if (switch_test_flag(*frame, SFF_CNG)) {
+               status = SWITCH_STATUS_SUCCESS;
+               goto done;
+       }
+
+       if (session->bugs) {
+               switch_media_bug_t *bp;
+               switch_bool_t ok = SWITCH_TRUE;
+               int prune = 0;
+               switch_thread_rwlock_rdlock(session->bug_rwlock);
+               for (bp = session->bugs; bp; bp = bp->next) {
+                       if (switch_channel_test_flag(session->channel, CF_PAUSE_BUGS) && !switch_core_media_bug_test_flag(bp, SMBF_NO_PAUSE)) {
+                               continue;
+                       }
+
+                       if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && switch_core_media_bug_test_flag(bp, SMBF_ANSWER_REQ)) {
+                               continue;
+                       }
+
+                       if (switch_test_flag(bp, SMBF_PRUNE)) {
+                               prune++;
+                               continue;
+                       }
+
+                       if (bp->ready && switch_test_flag(bp, SMBF_READ_PING)) {
+                               switch_mutex_lock(bp->read_mutex);
+                               bp->ping_frame = *frame;
+                               if (bp->callback) {
+                                       if (bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_VIDEO_PING) == SWITCH_FALSE
+                                               || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
+                                               ok = SWITCH_FALSE;
+                                       }
+                               }
+                               bp->ping_frame = NULL;;
+                               switch_mutex_unlock(bp->read_mutex);
+                       }
+
+                       if (ok == SWITCH_FALSE) {
+                               switch_set_flag(bp, SMBF_PRUNE);
+                               prune++;
+                       }
+               }
+               switch_thread_rwlock_unlock(session->bug_rwlock);
+               if (prune) {
+                       switch_core_media_bug_prune(session);
+               }
+       }
+
+  done:
+
+       return status;
+}
+
+
+
 /* For Emacs:
  * Local Variables:
  * mode:c
index f272eecd15548d87fbaced70494fb9118da6dd75..a4db12ae5955f15d6c3a9c5437511fbf4d326bc8 100644 (file)
@@ -56,6 +56,7 @@
 #include <switch_ssl.h>
 
 #define FIR_COUNTDOWN 50
+#define PLI_COUNTDOWN 50
 #define JITTER_LEAD_FRAMES 10
 #define READ_INC(rtp_session) switch_mutex_lock(rtp_session->read_mutex); rtp_session->reading++
 #define READ_DEC(rtp_session)  switch_mutex_unlock(rtp_session->read_mutex); rtp_session->reading--
@@ -299,6 +300,7 @@ struct switch_rtp {
        rtcp_ext_msg_t rtcp_ext_send_msg;
        uint8_t fir_seq;
        uint16_t fir_countdown;
+       uint16_t pli_countdown;
        ts_normalize_t ts_norm;
        switch_sockaddr_t *remote_addr, *rtcp_remote_addr;
        rtp_msg_t recv_msg;
@@ -360,6 +362,7 @@ struct switch_rtp {
        uint32_t samples_per_second;
        uint32_t conf_samples_per_interval;
        uint16_t rtcp_send_rate;
+       switch_time_t rtcp_last_sent;
        uint32_t rsamples_per_interval;
        uint32_t ms_per_packet;
        uint32_t one_second;
@@ -948,7 +951,10 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
                                } else {
                                        ice->rready = 1;
                                }
-
+                               
+                               if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
+                                       switch_core_media_gen_key_frame(rtp_session->session);
+                               }
                                switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH);
                        }
                }
@@ -1097,6 +1103,9 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
 
                        if (!ice->ready) {
                                ice->ready = 1;
+                               if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
+                                       switch_core_media_gen_key_frame(rtp_session->session);
+                               }
                                switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH);
                        }
 
@@ -2017,21 +2026,23 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
        switch_time_t now = switch_micro_time_now();
 
        if (rtp_session->fir_countdown) {
-               //if (rtp_session->fir_countdown == FIR_COUNTDOWN) {
-               //      do_flush(rtp_session, SWITCH_TRUE);
-               //}
 
                if (rtp_session->fir_countdown == FIR_COUNTDOWN || (rtp_session->fir_countdown == FIR_COUNTDOWN / 2) || rtp_session->fir_countdown == 1) {
-                       if (rtp_session->flags[SWITCH_RTP_FLAG_PLI]) {
-                               send_pli(rtp_session);
-                       } else {
-                               send_fir(rtp_session);
-                       }
+                       send_fir(rtp_session);
                }
 
                rtp_session->fir_countdown--;
        }
 
+       if (rtp_session->pli_countdown) {
+
+               if (rtp_session->pli_countdown == PLI_COUNTDOWN || (rtp_session->pli_countdown == PLI_COUNTDOWN / 2) || rtp_session->pli_countdown == 1) {
+                       send_pli(rtp_session);
+               }
+
+               rtp_session->pli_countdown--;
+       }
+
        if (rtp_session->flags[SWITCH_RTP_FLAG_AUTO_CNG] && rtp_session->send_msg.header.ts && rtp_session->cng_pt &&
                rtp_session->timer.samplecount >= (rtp_session->last_write_samplecount + (rtp_session->samples_per_interval * 60))) {
                uint8_t data[10] = { 0 };
@@ -2059,17 +2070,16 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
                rtcp_ok = 0;
        }
 
+       
        if (rtp_session->rtcp_sock_output && rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] &&
-               !rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU] &&
-               (rtp_session->timer.samplecount - rtp_session->stats.rtcp.last_rpt_ts >= rtp_session->samples_per_second * rtp_session->rtcp_send_rate) ) {
-
+               !rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU] && (now - rtp_session->rtcp_last_sent) > rtp_session->rtcp_send_rate * 1000000) {
                switch_rtcp_numbers_t * stats = &rtp_session->stats.rtcp;
                struct switch_rtcp_receiver_report *rr;
                struct switch_rtcp_sender_report *sr;
                struct switch_rtcp_report_block *rtcp_report_block;
-
                switch_size_t rtcp_bytes = sizeof(struct switch_rtcp_hdr_s)+sizeof(uint32_t); /* add size of the packet header and the ssrc */
 
+               rtp_session->rtcp_last_sent = now;
                rtp_session->rtcp_send_msg.header.version = 2;
                rtp_session->rtcp_send_msg.header.p = 0;
                rtp_session->rtcp_send_msg.header.count = 1;
@@ -3548,6 +3558,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
        rtp_session->recv_msg.header.cc = 0;
 
        rtp_session->payload = payload;
+       rtp_session->rtcp_last_sent = switch_micro_time_now();
 
        switch_rtp_set_interval(rtp_session, ms_per_packet, samples_per_interval);
        rtp_session->conf_samples_per_interval = samples_per_interval;
@@ -3790,7 +3801,8 @@ static void jb_callback(stfu_instance_t *i, void *udata)
 
 SWITCH_DECLARE(switch_timer_t *) switch_rtp_get_media_timer(switch_rtp_t *rtp_session)
 {
-       if (rtp_session->timer.timer_interface) {
+
+       if (rtp_session && rtp_session->timer.timer_interface) {
                if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
                        switch_core_timer_sync(&rtp_session->timer);
                }
@@ -4066,13 +4078,23 @@ SWITCH_DECLARE(void) switch_rtp_flush(switch_rtp_t *rtp_session)
 SWITCH_DECLARE(void) switch_rtp_video_refresh(switch_rtp_t *rtp_session)
 {
        if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && 
-               (rtp_session->ice.ice_user || rtp_session->flags[SWITCH_RTP_FLAG_FIR] || rtp_session->flags[SWITCH_RTP_FLAG_PLI])) {
+               (rtp_session->ice.ice_user || rtp_session->flags[SWITCH_RTP_FLAG_FIR])) {
                if (!rtp_session->fir_countdown) {
                        rtp_session->fir_countdown = FIR_COUNTDOWN;
                }
        }
 }
 
+SWITCH_DECLARE(void) switch_rtp_video_loss(switch_rtp_t *rtp_session)
+{
+       if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && 
+               (rtp_session->ice.ice_user || rtp_session->flags[SWITCH_RTP_FLAG_PLI])) {
+               if (!rtp_session->pli_countdown) {
+                       rtp_session->pli_countdown = PLI_COUNTDOWN;
+               }
+       }
+}
+
 SWITCH_DECLARE(void) switch_rtp_break(switch_rtp_t *rtp_session)
 {
        if (!switch_rtp_ready(rtp_session)) {
@@ -5159,12 +5181,29 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
 static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t *bytes)
 {
        switch_status_t status = SWITCH_STATUS_FALSE;
-       switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session");
-       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10,"Received an RTCP packet of length %" SWITCH_SIZE_T_FMT " bytes\n", *bytes);
-       if (rtp_session->rtcp_recv_msg.header.version == 2) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10,"RTCP packet type is %d\n", rtp_session->rtcp_recv_msg.header.type);
 
-               if (rtp_session->rtcp_recv_msg.header.type == 200 || rtp_session->rtcp_recv_msg.header.type == 201) {
+       if (rtp_session->rtcp_recv_msg_p->header.version == 2) {
+
+
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG,
+                                                 "RTCP packet bytes %" SWITCH_SIZE_T_FMT " type %d\n", *bytes, rtp_session->rtcp_recv_msg_p->header.type);
+
+
+
+               if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && *bytes > 94) {
+                       //(rtp_session->rtcp_recv_msg_p->header.type == 205 || //RTPFB
+                       //rtp_session->rtcp_recv_msg_p->header.type == 206)) {//PSFB
+                       
+                       rtcp_ext_msg_t *extp = (rtcp_ext_msg_t *) rtp_session->rtcp_recv_msg_p;                 
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "PICKED UP XRTCP type: %d fmt: %d\n", 
+                                                         rtp_session->rtcp_recv_msg_p->header.type, extp->header.fmt);
+                       
+                       if ((extp->header.fmt == 4) || (extp->header.fmt == 1)) { /* FIR || PLI */
+                               switch_core_media_gen_key_frame(rtp_session->session);
+                       }
+               } else
+
+               if (rtp_session->rtcp_recv_msg_p->header.type == 200 || rtp_session->rtcp_recv_msg_p->header.type == 201) {
                        struct switch_rtcp_report_block *report_block;
                        switch_time_t now;
                        switch_time_exp_t now_hr;
@@ -5177,8 +5216,9 @@ static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_siz
                        ntp_usec = (uint32_t)(now - (sec*1000000)); /* micro seconds */
                        lsr_now = (uint32_t)(ntp_usec*0.065536) | (ntp_sec&0x0000ffff)<<16; // 0.065536 is used for convertion from useconds 
 
-                       if (rtp_session->rtcp_recv_msg.header.type == 200) { /* Sender report */
-                               struct switch_rtcp_sender_report* sr = (struct switch_rtcp_sender_report*)rtp_session->rtcp_recv_msg.body;
+                       if (rtp_session->rtcp_recv_msg_p->header.type == 200) { /* Sender report */
+                               struct switch_rtcp_sender_report* sr = (struct switch_rtcp_sender_report*)rtp_session->rtcp_recv_msg_p->body;
+                               
                                report_block = &sr->report_block;
                                rtp_session->stats.rtcp.packet_count += ntohl(sr->sender_info.pc);
                                rtp_session->stats.rtcp.octet_count += ntohl(sr->sender_info.oc);
@@ -5187,7 +5227,7 @@ static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_siz
                                lsr = (ntohl(sr->sender_info.ntp_lsw)&0xffff0000)>>16 | (ntohl(sr->sender_info.ntp_msw)&0x0000ffff)<<16; /* The middle 32 bits out of 64 in the NTP timestamp */
                                rtp_session->stats.rtcp.last_recv_lsr_peer = htonl(lsr);  /* Save it include it in the next SR */
                                rtp_session->stats.rtcp.last_recv_lsr_local = lsr_now;    /* Save it to calculate DLSR when generating next SR */
-                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10,"Received a SR with %d report blocks, " \
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG10,"Received a SR with %d report blocks, " \
                                                          "length in words = %d, " \
                                                          "SSRC = 0x%X, " \
                                                          "NTP MSW = %u, " \
@@ -5195,8 +5235,8 @@ static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_siz
                                                          "RTP timestamp = %u, " \
                                                          "Sender Packet Count = %u, " \
                                                          "Sender Octet Count = %u\n",
-                                                         rtp_session->rtcp_recv_msg.header.count,
-                                                         ntohs((uint16_t)rtp_session->rtcp_recv_msg.header.length),
+                                                         rtp_session->rtcp_recv_msg_p->header.count,
+                                                         ntohs((uint16_t)rtp_session->rtcp_recv_msg_p->header.length),
                                                          ntohl(sr->ssrc),
                                                          ntohl(sr->sender_info.ntp_msw),
                                                          ntohl(sr->sender_info.ntp_lsw),
@@ -5204,7 +5244,7 @@ static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_siz
                                                          ntohl(sr->sender_info.pc),
                                                          ntohl(sr->sender_info.oc));
                        } else { /* Receiver report */
-                               struct switch_rtcp_receiver_report* rr = (struct switch_rtcp_receiver_report*)rtp_session->rtcp_recv_msg.body;
+                               struct switch_rtcp_receiver_report* rr = (struct switch_rtcp_receiver_report*)rtp_session->rtcp_recv_msg_p->body;
                                report_block = &rr->report_block;
                                packet_ssrc = rr->ssrc;
                        }
@@ -5213,12 +5253,12 @@ static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_siz
                        if (report_block->lsr && !rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU]) {
                                switch_time_exp_gmt(&now_hr,now);
                                /* Calculating RTT = A - DLSR - LSR */
-                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE,
-                                  "Receiving an RTCP packet[%04d-%02d-%02d %02d:%02d:%02d.%d] SSRC[%u]"
-                                  "RTT[%f] A[%u] - DLSR[%u] - LSR[%u]\n",
-                                  1900 + now_hr.tm_year, now_hr.tm_mday, now_hr.tm_mon, now_hr.tm_hour, now_hr.tm_min, now_hr.tm_sec, now_hr.tm_usec,
-                                  ntohl(packet_ssrc), (double)(lsr_now - ntohl(report_block->dlsr) - ntohl(report_block->lsr))/65536,
-                                  lsr_now, ntohl(report_block->dlsr), ntohl(report_block->lsr));
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG,
+                                                                 "Receiving an RTCP packet\n[%04d-%02d-%02d %02d:%02d:%02d.%d] SSRC[%u]\n"
+                                                                 "RTT[%f] A[%u] - DLSR[%u] - LSR[%u]\n",
+                                                                 1900 + now_hr.tm_year, now_hr.tm_mday, now_hr.tm_mon, now_hr.tm_hour, now_hr.tm_min, now_hr.tm_sec, now_hr.tm_usec,
+                                                                 ntohl(packet_ssrc), (double)(lsr_now - ntohl(report_block->dlsr) - ntohl(report_block->lsr))/65536,
+                                                                 lsr_now, ntohl(report_block->dlsr), ntohl(report_block->lsr));
                        }
 
                        rtp_session->rtcp_fresh_frame = 1;
@@ -5673,26 +5713,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
                                if (rtcp_status == SWITCH_STATUS_SUCCESS) {
                                        switch_rtp_reset_media_timer(rtp_session);
 
-                                       if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && (rtp_session->rtcp_recv_msg_p->header.type == 205 || //RTPFB
-                                                                                                                                         rtp_session->rtcp_recv_msg_p->header.type == 206)) {//PSFB
-                                               rtcp_ext_msg_t *extp = (rtcp_ext_msg_t *) rtp_session->rtcp_recv_msg_p;
-
-                                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "PICKED UP XRTCP type: %d fmt: %d\n", 
-                                                                                 rtp_session->rtcp_recv_msg_p->header.type, extp->header.fmt);
-
-                                               if ((extp->header.fmt == 4) || (extp->header.fmt == 1)) { /* FIR || PLI */
-
-                                                       switch_core_media_codec_control(rtp_session->session,
-                                                                                                                       SWITCH_MEDIA_TYPE_VIDEO,
-                                                                                                                       SWITCH_IO_WRITE,
-                                                                                                                       SCC_VIDEO_REFRESH,
-                                                                                                                       SCCT_NONE,
-                                                                                                                       NULL,
-                                                                                                                       NULL,
-                                                                                                                       NULL);
-                                               }
-                                       }
-
                                        if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU]) {
                                                switch_channel_t *channel = switch_core_session_get_channel(rtp_session->session);
                                                const char *uuid = switch_channel_get_partner_uuid(channel);
@@ -6235,14 +6255,14 @@ SWITCH_DECLARE(switch_status_t) switch_rtcp_zerocopy_read_frame(switch_rtp_t *rt
 
        /* A fresh frame has been found! */
        if (rtp_session->rtcp_fresh_frame) {
-               struct switch_rtcp_sender_report* sr = (struct switch_rtcp_sender_report*)rtp_session->rtcp_recv_msg.body;
+               struct switch_rtcp_sender_report* sr = (struct switch_rtcp_sender_report*)rtp_session->rtcp_recv_msg_p->body;
                int i = 0;
 
                /* turn the flag off! */
                rtp_session->rtcp_fresh_frame = 0;
 
                 frame->ssrc = ntohl(sr->ssrc);
-                frame->packet_type = (uint16_t)rtp_session->rtcp_recv_msg.header.type;
+                frame->packet_type = (uint16_t)rtp_session->rtcp_recv_msg_p->header.type;
                 frame->ntp_msw = ntohl(sr->sender_info.ntp_msw);
                 frame->ntp_lsw = ntohl(sr->sender_info.ntp_lsw);
                 frame->timestamp = ntohl(sr->sender_info.ts);
@@ -6787,10 +6807,9 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
 
                if (rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER]) {
                        rtp_session->last_write_samplecount = rtp_session->timer.samplecount;
-               } else {
-                       rtp_session->last_write_timestamp = switch_micro_time_now();
                }
-               
+
+               rtp_session->last_write_timestamp = switch_micro_time_now();
        }
 
        ret = (int) bytes;