diff --git a/packager/media/chunking/cue_alignment_handler.cc b/packager/media/chunking/cue_alignment_handler.cc index c742698a43..77e96d8c06 100644 --- a/packager/media/chunking/cue_alignment_handler.cc +++ b/packager/media/chunking/cue_alignment_handler.cc @@ -56,6 +56,11 @@ CueAlignmentHandler::CueAlignmentHandler(SyncPointQueue* sync_points) Status CueAlignmentHandler::InitializeInternal() { sync_points_->AddThread(); stream_states_.resize(num_input_streams()); + + // Get the first hint for the stream. Use a negative hint so that if there is + // suppose to be a sync point at zero, we will still respect it. + hint_ = sync_points_->GetHint(-1); + return Status::OK; } @@ -106,9 +111,6 @@ Status CueAlignmentHandler::OnStreamInfo(std::unique_ptr data) { // Keep a copy of the stream info so that we can check type and check // timescale. stream_state.info = data->stream_info; - // Get the first hint for the stream. Use a negative hint so that if there is - // suppose to be a sync point at zero, we will still respect it. - stream_state.next_cue_hint = sync_points_->GetHint(-1); return Dispatch(std::move(data)); } @@ -129,8 +131,7 @@ Status CueAlignmentHandler::OnSample(std::unique_ptr sample) { if (stream_state.info->stream_type() == kStreamVideo) { const double sample_time = TimeInSeconds(*stream_state.info, *sample); - if (sample->media_sample->is_key_frame() && - sample_time >= stream_state.next_cue_hint) { + if (sample->media_sample->is_key_frame() && sample_time >= hint_) { std::shared_ptr next_sync = sync_points_->PromoteAt(sample_time); if (!next_sync) { @@ -162,14 +163,7 @@ Status CueAlignmentHandler::OnSample(std::unique_ptr sample) { // to wait for all streams to converge on a hint so that we can get the next // sync point. if (EveryoneWaitingAtHint()) { - // All streams should have the same hint right now. - const double next_cue_hint = stream_state.next_cue_hint; - for (const StreamState& stream_state : stream_states_) { - DCHECK_EQ(next_cue_hint, stream_state.next_cue_hint); - } - - std::shared_ptr next_sync = - sync_points_->GetNext(next_cue_hint); + std::shared_ptr next_sync = sync_points_->GetNext(hint_); if (!next_sync) { // This happens only if the job is cancelled. return Status(error::CANCELLED, "SyncPointQueue is cancelled."); @@ -186,8 +180,8 @@ Status CueAlignmentHandler::OnSample(std::unique_ptr sample) { Status CueAlignmentHandler::UseNewSyncPoint( std::shared_ptr new_sync) { - const double new_hint = sync_points_->GetHint(new_sync->time_in_seconds); - DCHECK_GT(new_hint, new_sync->time_in_seconds); + hint_ = sync_points_->GetHint(new_sync->time_in_seconds); + DCHECK_GT(hint_, new_sync->time_in_seconds); Status status; for (StreamState& stream_state : stream_states_) { @@ -202,16 +196,13 @@ Status CueAlignmentHandler::UseNewSyncPoint( return Status(error::INVALID_ARGUMENT, "Cue events too close together"); } - // Add the cue and update the hint. The cue will always be used over the - // hint, so hint should always be greater than the latest cue. stream_state.cue = new_sync; - stream_state.next_cue_hint = new_hint; while (status.ok() && !stream_state.samples.empty()) { std::unique_ptr& sample = stream_state.samples.front(); const double sample_time_in_seconds = TimeInSeconds(*stream_state.info, *sample); - if (sample_time_in_seconds >= stream_state.next_cue_hint) { + if (sample_time_in_seconds >= hint_) { DCHECK(!stream_state.cue); break; } @@ -249,7 +240,7 @@ Status CueAlignmentHandler::AcceptSample(std::unique_ptr sample, if (stream_state->samples.empty()) { const double sample_time_in_seconds = TimeInSeconds(*stream_state->info, *sample); - if (sample_time_in_seconds < stream_state->next_cue_hint) { + if (sample_time_in_seconds < hint_) { Status status; if (stream_state->cue) { status.Update(DispatchCueIfNeeded(stream_index, sample_time_in_seconds, @@ -280,7 +271,7 @@ Status CueAlignmentHandler::DispatchCueIfNeeded( DCHECK(stream_state->cue); if (next_sample_time_in_seconds < stream_state->cue->time_in_seconds) return Status::OK; - DCHECK_LT(stream_state->cue->time_in_seconds, stream_state->next_cue_hint); + DCHECK_LT(stream_state->cue->time_in_seconds, hint_); return DispatchCueEvent(stream_index, std::move(stream_state->cue)); } diff --git a/packager/media/chunking/cue_alignment_handler.h b/packager/media/chunking/cue_alignment_handler.h index 0d5518eac0..6ac0bebeaf 100644 --- a/packager/media/chunking/cue_alignment_handler.h +++ b/packager/media/chunking/cue_alignment_handler.h @@ -44,14 +44,6 @@ class CueAlignmentHandler : public MediaHandler { // it is not set, the next cue is not determined. // This is set but not really used by video stream. std::shared_ptr cue; - // If |cue| is set, this is the hint for the cue after |cue|, i.e. next next - // cue; otherwise this is the hint for the next cue. This holds the time in - // seconds of the scheduled (unpromoted) next or next next cue's time. This - // is essentially the barrier for the sample stream. Non video samples after - // this barrier must wait until the |cue| is determined and thus the next - // hint to be determined; video samples will promote the hint to cue when - // seeing the first key frame after |next_cue_hint|. - double next_cue_hint = 0; }; // MediaHandler overrides. @@ -80,6 +72,16 @@ class CueAlignmentHandler : public MediaHandler { SyncPointQueue* const sync_points_ = nullptr; std::vector stream_states_; + + // A common hint used by all streams. When a new cue is given to all streams, + // the hint will be updated. The hint will always be larger than any cue. The + // hint represents the min time in seconds for the next cue appear. The hints + // are based off the un-promoted cue event times in |sync_points_|. + // + // When a video stream passes the hint, it will promote the corresponding cue + // event. If all streams get to the hint and there are no video streams, the + // thread will block until |sync_points_| gives back a promoted cue event. + double hint_; }; } // namespace media