Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added changes to pause & resume recorder #918

Closed

Conversation

AjayChoudary
Copy link

As @lminiero suggested in discussion , i created the pull request to pause & resume the active recording by manipulating RTP Time-stamps.

@lminiero
Copy link
Member

lminiero commented Jun 5, 2017

Thanks for working on this! From a quick glance there are some things that need to be fixed, though:

  1. There's a new "keyframe" request that is not needed. I see you already added an automatic FIR/PLI request when recording is resumed.
  2. Pausing/resuming recordings don't check if the recording object exists, which should cause an error if not.
  3. The ts-related changes in the recorder are not what I meant by keeping the RTP header consistent. That should not be done in the recorder code, but outside. Look at the calls to janus_rtp_header_update to see how plugins handle that for features like source switching: you'll see you'll need a context for the recorder, in case, and that's the plugin's responsibility, as the recorder should just worry about dumping packets without messing with them (and risking to break them).

@AjayChoudary
Copy link
Author

@lminiero below are my comments

  1. This "keyframe" is very handy for application servers, which are using rtp-forword. Instead of blindly requesting keyframe for every 10 seconds in janus, we can trigger keyframe request from App server whenever needed.

  2. Sorry I didn't get, which part you are referring to. Mostly i added NULL checks :)

  3. I have checked janus_rtp_header_update it only depends on SSRC, but in our case SSRC will be same. And we don't need to store all those context details.
    Pause the recording is completely independent of plug-in(audio/video rooms or record&play).
    I felt its good if we are doing recorder, post-processor is even better place.
    In my use case, I am pausing all the conference handles, but if any one wants to pause only one handle then they need this info in post-processor for synchronizing with other streams.
    At least for data channel we need to touch recorder.

@lminiero
Copy link
Member

lminiero commented Jun 9, 2017

Just a ping to tell you I haven't forgotten about this PR... I'm just awfully busy this period and can't look into it yet, sorry. That said, janus_rtp_header_update is not only used for switching: if you simulate an SSRC change, it will force the whole context to self update, and so make the sequence number and timestamp immediately consistent. We use something like this for viewers pausing/unpausing in the VideoRoom too (although there we only update the sequence number but not the timestamp).

Copy link
Member

@lminiero lminiero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried doing a deeper review. I'm not 100% sure this fits nicely in how we do things in all plugins and in the post-processor, but I'd have to try this. It definitely has interesting concepts, though, so in case I try to tackle this myself later on this would help greatly. Thanks again for working on this!

record.h Outdated
@@ -48,6 +48,10 @@ typedef struct janus_recorder {
gint64 created;
/*! \brief Media this instance is recording */
janus_recorder_medium type;
/*! \brief Timestaps for pause and resume the recording */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pausing and resuming

record.h Outdated
@@ -48,6 +48,10 @@ typedef struct janus_recorder {
gint64 created;
/*! \brief Media this instance is recording */
janus_recorder_medium type;
/*! \brief Timestaps for pause and resume the recording */
gint64 paused_ts, offset_ts;
/*! \brief Whether recording paused or not */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whether the recording has been paused or not

record.h Outdated
* @param[in] recorder The janus_recorder instance
* @param[in] boolean Whether to pause or resume
* @returns 0 in case of success, a negative integer otherwise */
int janus_recorder_pause(janus_recorder *recorder, gboolean pause);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather have two separate methods, janus_recorder_pause and janus_recorder_resume, as from a semantic perspective a method called janus_recorder_pause that can be used to resume as well is counter-intuitive.

@@ -506,6 +506,7 @@ typedef struct janus_videoroom_publisher {
gint64 fir_latest; /* Time of latest sent FIR (to avoid flooding) */
gint fir_seq; /* FIR sequence number */
gboolean recording_active; /* Whether this publisher has to be recorded or not */
gboolean recording_pause;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nitpicking, I know, but recording_paused is a better name for this. Can you also add a comment on the side, as we do for the other properties?

@@ -2699,7 +2699,18 @@ static void janus_videoroom_recorder_create(janus_videoroom_publisher *participa
}
}
}

static void janus_videoroom_recorder_pause(janus_videoroom_publisher *participant, gboolean paused) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See below for the semantic names. In this case, to keep things compact, the name could be changed to janus_videoroom_recorder_status or something like this, in order to keep the boolean flag.

@@ -3349,6 +3362,28 @@ static void *janus_videoroom_handler(void *data) {
}
}
}
if(record_pause) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no check here on whether arc, vrc or drc exist. Trying to pause/resume a non existing recording should return an error, while in this case you're always succeeding no matter what.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is important, because you may set a recording to paused and then start it, and the fact that both succeeded may make you think that you started the recording as paused, and you can resume it later, which is not the case.

@@ -2964,6 +2975,7 @@ static void *janus_videoroom_handler(void *data) {
publisher->video_active = FALSE;
publisher->data_active = FALSE;
publisher->recording_active = FALSE;
publisher->recording_pause = FALSE;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be reset in hangup_media as well. As a side note, it might be useful to have this property returned when doing query_session as well, as we have a section related to recording in there when querying publishers.

JANUS_LOG(LOG_VERB, "Video keyframe, sending PLI to %"SCNu64" (%s)\n",
participant->user_id, participant->display ? participant->display : "??");
gateway->relay_rtcp(participant->session->handle, 1, buf, 12);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this request not generating any event to confirm the success?

record.c Outdated
recorder->offset_ts = (uint32_t) recorder->offset_ts + (ntohl(rtp->timestamp) - (uint32_t)recorder->paused_ts);
JANUS_LOG(LOG_INFO, "RESUME TIME TS = %u OFFSET=%u \n", rtp->timestamp, recorder->paused_ts, recorder->offset_ts);
}
recorder->paused_ts = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens here when you pause/resume more than once? Not sure this would still work. Besides, there's no fix to the sequence numbers, which means they won't be sequential, with big holes in between. This will cause severe issues when trying to replay them via Record&Play, because the recipient will think packets have been missed, and NACK them. This is one of the reasons why I'm insisting on using the RTP context here too, as it's one of the things it takes care of for you.

@lminiero
Copy link
Member

Closing as this is based on a pull request we since closed (ICE restarts).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants