]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-5302 --resolve
authorAnthony Minessale <anthm@freeswitch.org>
Fri, 19 Apr 2013 20:25:11 +0000 (15:25 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Fri, 19 Apr 2013 19:07:57 +0000 (14:07 -0500)
src/mod/applications/mod_oreka/mod_oreka.c
src/switch_rtp.c

index 64f5e8ffd34c05ee1d143754239db9712623454a..4879de3eb382e1c3b9b66864ae8db3d6894895d3 100644 (file)
@@ -52,10 +52,12 @@ typedef struct oreka_session_s {
        uint32_t read_cnt;
        uint32_t write_cnt;
        switch_media_bug_t *read_bug;
-       switch_media_bug_t *write_bug;
+       //switch_media_bug_t *write_bug;
        switch_event_t *invite_extra_headers;
        switch_event_t *bye_extra_headers;
        int usecnt;
+    switch_audio_resampler_t *read_resampler;
+    switch_audio_resampler_t *write_resampler;
 } oreka_session_t;
 
 struct {
@@ -117,6 +119,7 @@ static int oreka_setup_rtp(oreka_session_t *oreka, oreka_stream_type_t type)
        const char  *err = "unknown error";
        const char *type_str = type == FS_OREKA_READ ? "read" : "write";
 
+
        if (type == FS_OREKA_READ) {
                status = switch_core_session_get_read_impl(oreka->session, &oreka->read_impl);
                codec_impl = &oreka->read_impl;
@@ -150,6 +153,10 @@ static int oreka_setup_rtp(oreka_session_t *oreka, oreka_stream_type_t type)
                res = -1;
                goto done;
        }
+
+    switch_rtp_intentional_bugs(rtp_stream, RTP_BUG_SEND_LINEAR_TIMESTAMPS); 
+
+
 done:
        if (res == -1) {
                if (rtp_port) {
@@ -379,57 +386,105 @@ done:
        return rc;
 }
 
-static switch_bool_t oreka_core_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type, oreka_stream_type_t stype, const char *stype_str)
+static switch_bool_t oreka_audio_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
 {
        oreka_session_t *oreka = user_data;
        switch_core_session_t *session = oreka->session;
-       switch_frame_t pcmu_frame;
-       switch_frame_t linear_frame = { 0 };
-       switch_status_t status = SWITCH_STATUS_SUCCESS;
+       switch_frame_t pcmu_frame = { 0 };
+    switch_frame_t *linear_frame;
        uint8_t pcmu_data[SWITCH_RECOMMENDED_BUFFER_SIZE];
-       uint8_t linear_data[SWITCH_RECOMMENDED_BUFFER_SIZE];
+       uint8_t resample_data[SWITCH_RECOMMENDED_BUFFER_SIZE];
+    uint32_t linear_len = 0;
        uint32_t i = 0;
        int16_t *linear_samples = NULL;
 
-       if (type == SWITCH_ABC_TYPE_READ || type == SWITCH_ABC_TYPE_WRITE) {
-               memset(&linear_frame, 0, sizeof(linear_frame));
-               linear_frame.data = linear_data;
-               linear_frame.buflen = sizeof(linear_data);
-               status = switch_core_media_bug_read(bug, &linear_frame, SWITCH_TRUE);
-               if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error reading media bug: %d\n", status);
-                       goto done;
-               }
-               if (!linear_frame.datalen) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Linear frame with no length!\n");
-                       goto done;
-               }
+    
+
+       if (type == SWITCH_ABC_TYPE_READ_REPLACE || type == SWITCH_ABC_TYPE_WRITE_REPLACE) {
+        int16_t *data;
+
+        if (type == SWITCH_ABC_TYPE_READ_REPLACE) {
+            linear_frame = switch_core_media_bug_get_read_replace_frame(bug);
+
+            if (oreka->read_resampler) {
+                data = (int16_t *) linear_frame->data;
+                switch_resample_process(oreka->read_resampler, data, (int) linear_frame->datalen / 2);
+                linear_len = oreka->read_resampler->to_len * 2;
+                memcpy(resample_data, oreka->read_resampler->to, linear_len);
+                linear_samples = (int16_t *)resample_data;
+            } else {
+                linear_samples = linear_frame->data;
+                linear_len = linear_frame->datalen;
+            }
+        }
+
+        if (type == SWITCH_ABC_TYPE_WRITE_REPLACE) {
+            linear_frame = switch_core_media_bug_get_write_replace_frame(bug);
+
+            if (oreka->write_resampler) {
+                data = (int16_t *) linear_frame->data;
+                switch_resample_process(oreka->write_resampler, data, (int) linear_frame->datalen / 2);
+                linear_len = oreka->write_resampler->to_len * 2;
+                memcpy(resample_data, oreka->write_resampler->to, linear_len);
+                linear_samples = (int16_t *)resample_data;
+            } else {
+                linear_samples = linear_frame->data;
+                linear_len = linear_frame->datalen;
+            }
+        }
+
                /* convert the L16 frame into PCMU */
-               linear_samples = linear_frame.data;
                memset(&pcmu_frame, 0, sizeof(pcmu_frame));
-               for (i = 0; i < linear_frame.datalen/sizeof(int16_t); i++) {
+               for (i = 0; i < linear_len / sizeof(int16_t); i++) {
                        pcmu_data[i] = linear_to_ulaw(linear_samples[i]);
                }
                pcmu_frame.source = __FUNCTION__;
                pcmu_frame.data = pcmu_data;
-               pcmu_frame.datalen = i; 
+               pcmu_frame.datalen = i;
                pcmu_frame.payload = 0;
        }
 
        switch (type) {
        case SWITCH_ABC_TYPE_INIT:
                {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Starting Oreka recording for %s stream\n", stype_str);
-                       oreka_send_sip_message(oreka, FS_OREKA_START, stype);
+            switch_codec_implementation_t read_impl;
+
+            switch_core_session_get_read_impl(session, &read_impl);
+
+            if (read_impl.actual_samples_per_second != 8000) {
+                switch_resample_create(&oreka->read_resampler,
+                                       read_impl.actual_samples_per_second,
+                                       8000,
+                                       320, SWITCH_RESAMPLE_QUALITY, 1);
+
+                switch_resample_create(&oreka->write_resampler,
+                                       read_impl.actual_samples_per_second,
+                                       8000,
+                                       320, SWITCH_RESAMPLE_QUALITY, 1);                
+            }
+
+
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Starting Oreka recording for audio stream\n");
+                       oreka_send_sip_message(oreka, FS_OREKA_START, FS_OREKA_READ);
+                       oreka_send_sip_message(oreka, FS_OREKA_START, FS_OREKA_WRITE);
                }
                break;
        case SWITCH_ABC_TYPE_CLOSE:
                {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Stopping Oreka recording for %s stream\n", stype_str);
-                       oreka_send_sip_message(oreka, FS_OREKA_STOP, stype);
+            if (oreka->read_resampler) {
+                switch_resample_destroy(&oreka->read_resampler);
+            }
+
+            if (oreka->write_resampler) {
+                switch_resample_destroy(&oreka->write_resampler);
+            }
+
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Stopping Oreka recording for audio stream\n");
+                       oreka_send_sip_message(oreka, FS_OREKA_STOP, FS_OREKA_READ);
+                       oreka_send_sip_message(oreka, FS_OREKA_STOP, FS_OREKA_WRITE);
                }
                break;
-       case SWITCH_ABC_TYPE_READ:
+       case SWITCH_ABC_TYPE_READ_REPLACE:
                {
                        if (pcmu_frame.datalen) {
                                if (switch_rtp_write_frame(oreka->read_rtp_stream, &pcmu_frame) > 0) {
@@ -443,7 +498,7 @@ static switch_bool_t oreka_core_callback(switch_media_bug_t *bug, void *user_dat
                        }
                }
                break;
-       case SWITCH_ABC_TYPE_WRITE:
+       case SWITCH_ABC_TYPE_WRITE_REPLACE:
                {
                        if (pcmu_frame.datalen) {
                                if (switch_rtp_write_frame(oreka->write_rtp_stream, &pcmu_frame) > 0) {
@@ -460,19 +515,10 @@ static switch_bool_t oreka_core_callback(switch_media_bug_t *bug, void *user_dat
        default:
                break;
        }
-done:
-       return SWITCH_TRUE;
-}
 
-static switch_bool_t oreka_read_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
-{
-       return oreka_core_callback(bug, user_data, type, FS_OREKA_READ, "read");
+       return SWITCH_TRUE;
 }
 
-static switch_bool_t oreka_write_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
-{
-       return oreka_core_callback(bug, user_data, type, FS_OREKA_WRITE, "write");
-}
 
 SWITCH_STANDARD_APP(oreka_start_function)
 {
@@ -491,10 +537,6 @@ SWITCH_STANDARD_APP(oreka_start_function)
                                switch_core_media_bug_remove(session, &oreka->read_bug);
                                oreka->read_bug = NULL;
                        }
-                       if (oreka->write_bug) {
-                               switch_core_media_bug_remove(session, &oreka->write_bug);
-                               oreka->write_bug = NULL;
-                       }
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Stopped oreka recorder\n");
                } else {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot run oreka recording 2 times on the same session!\n");
@@ -516,22 +558,15 @@ SWITCH_STANDARD_APP(oreka_start_function)
        }
 
        oreka->session = session;
-       status = switch_core_media_bug_add(session, OREKA_BUG_NAME_READ, NULL, oreka_read_callback, oreka, 0,
-                       (SMBF_READ_STREAM | SMBF_ANSWER_REQ), &bug);
+       status = switch_core_media_bug_add(session, OREKA_BUG_NAME_READ, NULL, oreka_audio_callback, oreka, 0,
+                       (SMBF_READ_REPLACE | SMBF_WRITE_REPLACE | SMBF_ANSWER_REQ), &bug);
        if (status != SWITCH_STATUS_SUCCESS) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to attach oreka to read media stream!\n");
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to attach oreka to media stream!\n");
                return;
        }
        oreka->read_bug = bug;
        oreka->usecnt++;
        bug = NULL;
-       status = switch_core_media_bug_add(session, OREKA_BUG_NAME_WRITE, NULL, oreka_write_callback, oreka, 0,
-                       (SMBF_WRITE_STREAM | SMBF_ANSWER_REQ), &bug);
-       if (status != SWITCH_STATUS_SUCCESS) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to attach oreka to write media stream!\n");
-               return;
-       }
-       oreka->write_bug = bug;
        oreka->usecnt++;
        switch_channel_set_private(channel, OREKA_PRIVATE, oreka);
 
index 21f17985377941aea3f35857680a5a6fffaa8673..495ccf07570f2999817c8fcf3fbd201b0213ba22 100644 (file)
@@ -1000,6 +1000,9 @@ static uint8_t get_next_write_ts(switch_rtp_t *rtp_session, uint32_t timestamp)
                }
        } else {
                rtp_session->ts += rtp_session->samples_per_interval;
+               if (rtp_session->ts <= rtp_session->last_write_ts && rtp_session->ts > 0) {
+                       rtp_session->ts = rtp_session->last_write_ts + rtp_session->samples_per_interval;
+               }               
        }
 
        return m;