diff --git a/html/recordplaytest.js b/html/recordplaytest.js index 8cb6ae1d0e..0d66c4d58b 100644 --- a/html/recordplaytest.js +++ b/html/recordplaytest.js @@ -316,13 +316,9 @@ $(document).ready(function() { }, ondataopen: function(data) { Janus.log("The DataChannel is available!"); - $('#waitingvideo').remove(); $('#videobox').append( '' ); - if(spinner) - spinner.stop(); - spinner = null; }, ondata: function(data) { Janus.debug("We got data from the DataChannel!", data); diff --git a/plugins/janus_recordplay.c b/plugins/janus_recordplay.c index 35474b5f7a..5b4f536242 100644 --- a/plugins/janus_recordplay.c +++ b/plugins/janus_recordplay.c @@ -261,7 +261,6 @@ #include #include -#include #include #include #include @@ -406,7 +405,7 @@ typedef struct janus_recordplay_recording { char *vfmtp; /* Video fmtp, if any */ int video_pt; /* Payload types to use for audio when playing recordings */ char *drc_file; /* Data file name */ - gboolean textdata; /* Data format is text */ + gboolean textdata; /* Whether data format is text */ char *offer; /* The SDP offer that will be sent to watchers */ gboolean e2ee; /* Whether media in the recording is encrypted, e.g., using Insertable Streams */ GList *viewers; /* List of users watching this recording */ @@ -498,8 +497,6 @@ void janus_recordplay_send_rtcp_feedback(janus_plugin_session *handle, int video #define AUDIO_PT 111 #define VIDEO_PT 100 -#define UDPHDR_SIZE 8 - /* Helper method to check which codec was used in a specific recording (and if it's end-to-end encrypted) */ static const char *janus_recordplay_parse_codec(const char *dir, const char *filename, char *fmtp, size_t fmtplen, gboolean *e2ee) { if(dir == NULL || filename == NULL) @@ -626,7 +623,7 @@ static const char *janus_recordplay_parse_codec(const char *dir, const char *fil const char *c = json_string_value(codec); if (data) { /* Found! */ - c = !strcasecmp(c, "text")? "text" : "bin"; + c = !strcasecmp(c, "text") ? "text" : "binary"; json_decref(info); fclose(file); return c; @@ -2072,8 +2069,10 @@ void janus_recordplay_update_recordings_list(void) { char *ext = strstr(rec->drc_file, ".mjr"); if(ext != NULL) *ext = '\0'; - rec->textdata = !strcasecmp("text", janus_recordplay_parse_codec(recordings_path, - rec->drc_file, NULL, sizeof(NULL), NULL)); + const char *textcodec = janus_recordplay_parse_codec(recordings_path, + rec->drc_file, NULL, sizeof(NULL), NULL); + if (textcodec) + rec->textdata = !strcasecmp("text", textcodec); } rec->audio_pt = AUDIO_PT; if(rec->acodec != JANUS_AUDIOCODEC_NONE) { @@ -2261,7 +2260,7 @@ janus_recordplay_frame_packet *janus_recordplay_get_frames(const char *dir, cons } w_time = json_integer_value(created); /* Summary */ - JANUS_LOG(LOG_VERB, "This is %s recording:\n", video ? "a video" : audio ? "an audio" : "a data"); + JANUS_LOG(LOG_VERB, "This is %s recording:\n", video ? "a video" : (audio ? "an audio" : "a data")); JANUS_LOG(LOG_VERB, " -- Codec: %s\n", c); JANUS_LOG(LOG_VERB, " -- Created: %"SCNi64"\n", c_time); JANUS_LOG(LOG_VERB, " -- Written: %"SCNi64"\n", w_time); @@ -2431,6 +2430,8 @@ janus_recordplay_frame_packet *janus_recordplay_get_frames(const char *dir, cons return list; } +#define ntohll(x) ((1==ntohl(1)) ? (x) : ((gint64)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) + static void *janus_recordplay_playout_thread(void *sessiondata) { janus_recordplay_session *session = (janus_recordplay_session *)sessiondata; if(!session) { @@ -2539,7 +2540,6 @@ static void *janus_recordplay_playout_thread(void *sessiondata) { if(audio_pt == 0 || audio_pt == 8 || audio_pt == 9) akhz = 8; int vkhz = 90; - int dhz = 1; while(!g_atomic_int_get(&session->destroyed) && session->active && !g_atomic_int_get(&rec->destroyed) && (audio || video)) { @@ -2680,10 +2680,24 @@ static void *janus_recordplay_playout_thread(void *sessiondata) { if(data) { if(data == session->dframes) { /* First packet, send now */ - /* Data recording stores raw UDP packets */ - fseek(dfile, data->offset+UDPHDR_SIZE, SEEK_SET); - bytes = fread(buffer, sizeof(char), data->len-UDPHDR_SIZE, dfile); - if(bytes != data->len-UDPHDR_SIZE) + /* Data recording stores recording timestamp in first 8 bytes - it follows the frame ts monotonically. + invariant: when = data->ts + when(initial packet) */ + gint64 when = 0; + int len = data->len; + int offset = data->offset; + fseek(dfile, data->offset, SEEK_SET); + bytes = fread(&when, sizeof(gint64), 1, dfile); + when = ntohll(when); // NOTE: not currently used - playback is interested in actual data packets. + offset += sizeof(gint64); + len -= sizeof(gint64); + + /* Read data packet */ + fseek(dfile, offset, SEEK_SET); + bytes = fread(buffer, sizeof(char), len, dfile); + JANUS_LOG(LOG_INFO, "Sending data packet at rtp_timestamp = %lu, timestamp = %lu, delta = %lu\n", (data->ts), when, when - data->ts); + fseek(dfile, offset, SEEK_SET); + bytes = fread(buffer, sizeof(char), len, dfile); + if(bytes != data->len) JANUS_LOG(LOG_WARN, "Didn't manage to read all the bytes we needed (%d < %d)...\n", bytes, data->len); /* Update payload type */ janus_plugin_data datapacket = { @@ -2703,7 +2717,6 @@ static void *janus_recordplay_playout_thread(void *sessiondata) { } else { /* What's the timestamp skip from the previous packet? */ ts_diff = data->ts - data->prev->ts; - ts_diff = (ts_diff)/dhz; /* Check if it's time to send */ gettimeofday(&now, NULL); d_s = now.tv_sec - dbefore.tv_sec; @@ -2726,16 +2739,27 @@ static void *janus_recordplay_playout_thread(void *sessiondata) { dbefore.tv_sec += ts_diff/1000000; dbefore.tv_usec -= ts_diff/1000000; } - /* Send now */ - fseek(dfile, data->offset+UDPHDR_SIZE, SEEK_SET); - bytes = fread(buffer, sizeof(char), data->len-UDPHDR_SIZE, dfile); - if(bytes != data->len-UDPHDR_SIZE) + /* Send now */ + gint64 when = 0; + int len = data->len; + int offset = data->offset; + fseek(dfile, data->offset, SEEK_SET); + bytes = fread(&when, sizeof(gint64), 1, dfile); + when = ntohll(when); + offset += sizeof(gint64); + len -= sizeof(gint64); + + /* Read data packet */ + fseek(dfile, offset, SEEK_SET); + bytes = fread(buffer, sizeof(char), len, dfile); + JANUS_LOG(LOG_VERB, "Sending data packet at timestamp = %lu, recorded timestamp = %lu\n", (data->ts), when); + if(bytes != len) JANUS_LOG(LOG_WARN, "Didn't manage to read all the bytes we needed (%d < %d)...\n", bytes, data->len); /* Update payload type */ janus_plugin_data datapacket = { .label = NULL, .protocol = NULL, - .binary = rec->textdata? FALSE : TRUE, + .binary = rec->textdata ? FALSE : TRUE, .buffer = (char *)buffer, .length = bytes }; diff --git a/plugins/janus_streaming.c b/plugins/janus_streaming.c index 498a42a7b0..f5482e3c7a 100644 --- a/plugins/janus_streaming.c +++ b/plugins/janus_streaming.c @@ -4000,7 +4000,7 @@ static json_t *janus_streaming_process_synchronous_request(janus_streaming_sessi } if(data) { const char *datafile = json_string_value(data); - drc = janus_recorder_create(NULL, source->textdata ? "text" : "bin", (char *)datafile); + drc = janus_recorder_create(NULL, "text", (char *)datafile); if(drc == NULL) { if(arc != NULL) { janus_recorder_close(arc);