2023-12-01 17:32:19 +00:00
|
|
|
// Copyright 2017 Google LLC. All rights reserved.
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file or at
|
|
|
|
// https://developers.google.com/open-source/licenses/bsd
|
|
|
|
|
2023-12-01 17:32:19 +00:00
|
|
|
#include <packager/media/chunking/chunking_handler.h>
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
|
2018-01-09 01:18:15 +00:00
|
|
|
#include <algorithm>
|
|
|
|
|
2023-12-01 17:32:19 +00:00
|
|
|
#include <absl/log/check.h>
|
|
|
|
#include <absl/log/log.h>
|
|
|
|
|
|
|
|
#include <packager/macros/logging.h>
|
|
|
|
#include <packager/macros/status.h>
|
|
|
|
#include <packager/media/base/media_sample.h>
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
|
2018-03-15 23:01:47 +00:00
|
|
|
namespace shaka {
|
|
|
|
namespace media {
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
namespace {
|
2018-03-20 17:12:18 +00:00
|
|
|
const size_t kStreamIndex = 0;
|
2018-03-21 02:13:22 +00:00
|
|
|
|
|
|
|
bool IsNewSegmentIndex(int64_t new_index, int64_t current_index) {
|
|
|
|
return new_index != current_index &&
|
|
|
|
// Index is calculated from pts, which could decrease. We do not expect
|
|
|
|
// it to decrease by more than one segment though, which could happen
|
|
|
|
// only if there is a big overlap in the timeline, in which case, we
|
|
|
|
// will create a new segment and leave it to the player to handle it.
|
|
|
|
new_index != current_index - 1;
|
|
|
|
}
|
|
|
|
|
2018-03-15 23:01:47 +00:00
|
|
|
} // namespace
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
|
2017-07-27 17:23:27 +00:00
|
|
|
ChunkingHandler::ChunkingHandler(const ChunkingParams& chunking_params)
|
2018-03-20 17:12:18 +00:00
|
|
|
: chunking_params_(chunking_params) {
|
2017-07-27 17:23:27 +00:00
|
|
|
CHECK_NE(chunking_params.segment_duration_in_seconds, 0u);
|
2024-05-02 20:25:49 +00:00
|
|
|
segment_number_ = chunking_params.start_segment_number;
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Status ChunkingHandler::InitializeInternal() {
|
2018-03-20 17:12:18 +00:00
|
|
|
if (num_input_streams() != 1 || next_output_stream_index() != 1) {
|
|
|
|
return Status(error::INVALID_ARGUMENT,
|
|
|
|
"Expects exactly one input and one output.");
|
|
|
|
}
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
return Status::OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status ChunkingHandler::Process(std::unique_ptr<StreamData> stream_data) {
|
|
|
|
switch (stream_data->stream_data_type) {
|
2018-02-12 20:19:34 +00:00
|
|
|
case StreamDataType::kStreamInfo:
|
2018-03-20 17:12:18 +00:00
|
|
|
return OnStreamInfo(std::move(stream_data->stream_info));
|
|
|
|
case StreamDataType::kCueEvent:
|
|
|
|
return OnCueEvent(std::move(stream_data->cue_event));
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
case StreamDataType::kSegmentInfo:
|
2017-12-11 16:59:40 +00:00
|
|
|
VLOG(3) << "Droppping existing segment info.";
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
return Status::OK;
|
2018-02-12 22:49:03 +00:00
|
|
|
case StreamDataType::kMediaSample:
|
2018-03-20 17:12:18 +00:00
|
|
|
return OnMediaSample(std::move(stream_data->media_sample));
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
default:
|
|
|
|
VLOG(3) << "Stream data type "
|
|
|
|
<< static_cast<int>(stream_data->stream_data_type) << " ignored.";
|
2018-02-12 22:49:03 +00:00
|
|
|
return Dispatch(std::move(stream_data));
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-01 17:32:19 +00:00
|
|
|
Status ChunkingHandler::OnFlushRequest(size_t /*input_stream_index*/) {
|
2018-03-21 18:03:54 +00:00
|
|
|
RETURN_IF_ERROR(EndSegmentIfStarted());
|
2018-03-20 17:12:18 +00:00
|
|
|
return FlushDownstream(kStreamIndex);
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:12:18 +00:00
|
|
|
Status ChunkingHandler::OnStreamInfo(std::shared_ptr<const StreamInfo> info) {
|
|
|
|
time_scale_ = info->time_scale();
|
|
|
|
segment_duration_ =
|
|
|
|
chunking_params_.segment_duration_in_seconds * time_scale_;
|
|
|
|
subsegment_duration_ =
|
|
|
|
chunking_params_.subsegment_duration_in_seconds * time_scale_;
|
|
|
|
return DispatchStreamInfo(kStreamIndex, std::move(info));
|
2018-02-12 20:19:34 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:12:18 +00:00
|
|
|
Status ChunkingHandler::OnCueEvent(std::shared_ptr<const CueEvent> event) {
|
2018-03-21 18:03:54 +00:00
|
|
|
RETURN_IF_ERROR(EndSegmentIfStarted());
|
|
|
|
const double event_time_in_seconds = event->time_in_seconds;
|
|
|
|
RETURN_IF_ERROR(DispatchCueEvent(kStreamIndex, std::move(event)));
|
|
|
|
|
2018-03-20 17:12:18 +00:00
|
|
|
// Force start new segment after cue event.
|
2023-12-01 17:32:19 +00:00
|
|
|
segment_start_time_ = std::nullopt;
|
2018-03-21 18:03:54 +00:00
|
|
|
// |cue_offset_| will be applied to sample timestamp so the segment after cue
|
|
|
|
// point have duration ~= |segment_duration_|.
|
|
|
|
cue_offset_ = event_time_in_seconds * time_scale_;
|
|
|
|
return Status::OK;
|
2018-02-12 20:38:47 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:12:18 +00:00
|
|
|
Status ChunkingHandler::OnMediaSample(
|
|
|
|
std::shared_ptr<const MediaSample> sample) {
|
2021-08-04 18:56:44 +00:00
|
|
|
DCHECK_GT(time_scale_, 0) << "kStreamInfo should arrive before kMediaSample";
|
2018-02-12 22:49:03 +00:00
|
|
|
|
2018-03-21 02:13:22 +00:00
|
|
|
const int64_t timestamp = sample->pts();
|
2018-03-15 23:01:47 +00:00
|
|
|
|
2018-03-20 17:12:18 +00:00
|
|
|
bool started_new_segment = false;
|
|
|
|
const bool can_start_new_segment =
|
|
|
|
sample->is_key_frame() || !chunking_params_.segment_sap_aligned;
|
|
|
|
if (can_start_new_segment) {
|
2018-03-21 18:03:54 +00:00
|
|
|
const int64_t segment_index =
|
|
|
|
timestamp < cue_offset_ ? 0
|
|
|
|
: (timestamp - cue_offset_) / segment_duration_;
|
2018-03-21 02:13:22 +00:00
|
|
|
if (!segment_start_time_ ||
|
|
|
|
IsNewSegmentIndex(segment_index, current_segment_index_)) {
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
current_segment_index_ = segment_index;
|
2017-02-24 01:17:47 +00:00
|
|
|
// Reset subsegment index.
|
|
|
|
current_subsegment_index_ = 0;
|
2018-01-03 00:10:33 +00:00
|
|
|
|
2018-03-21 18:03:54 +00:00
|
|
|
RETURN_IF_ERROR(EndSegmentIfStarted());
|
2018-03-20 17:12:18 +00:00
|
|
|
segment_start_time_ = timestamp;
|
|
|
|
subsegment_start_time_ = timestamp;
|
2018-03-21 02:13:22 +00:00
|
|
|
max_segment_time_ = timestamp + sample->duration();
|
2018-03-20 17:12:18 +00:00
|
|
|
started_new_segment = true;
|
2017-12-12 16:51:50 +00:00
|
|
|
}
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
}
|
2021-08-25 15:38:05 +00:00
|
|
|
|
|
|
|
// This handles the LL-DASH case.
|
|
|
|
// On each media sample, which is the basis for a chunk,
|
|
|
|
// we must increment the current_subsegment_index_
|
|
|
|
// in order to hit FinalizeSegment() within Segmenter.
|
|
|
|
if (!started_new_segment && chunking_params_.low_latency_dash_mode) {
|
|
|
|
current_subsegment_index_++;
|
|
|
|
|
|
|
|
RETURN_IF_ERROR(EndSubsegmentIfStarted());
|
|
|
|
subsegment_start_time_ = timestamp;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Here, a subsegment refers to a fragment that is within a segment.
|
|
|
|
// This fragment size can be set with the 'fragment_duration' cmd arg.
|
|
|
|
// This is NOT for the LL-DASH case.
|
|
|
|
if (!started_new_segment && IsSubsegmentEnabled() &&
|
|
|
|
!chunking_params_.low_latency_dash_mode) {
|
2018-03-20 17:12:18 +00:00
|
|
|
const bool can_start_new_subsegment =
|
|
|
|
sample->is_key_frame() || !chunking_params_.subsegment_sap_aligned;
|
|
|
|
if (can_start_new_subsegment) {
|
|
|
|
const int64_t subsegment_index =
|
|
|
|
(timestamp - segment_start_time_.value()) / subsegment_duration_;
|
2018-03-21 02:13:22 +00:00
|
|
|
if (IsNewSegmentIndex(subsegment_index, current_subsegment_index_)) {
|
2018-03-20 17:12:18 +00:00
|
|
|
current_subsegment_index_ = subsegment_index;
|
|
|
|
|
2018-03-21 18:03:54 +00:00
|
|
|
RETURN_IF_ERROR(EndSubsegmentIfStarted());
|
2018-03-20 17:12:18 +00:00
|
|
|
subsegment_start_time_ = timestamp;
|
|
|
|
}
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-20 17:12:18 +00:00
|
|
|
VLOG(3) << "Sample ts: " << timestamp << " "
|
|
|
|
<< " duration: " << sample->duration() << " scale: " << time_scale_
|
|
|
|
<< (segment_start_time_ ? " dispatch " : " discard ");
|
2018-03-21 02:13:22 +00:00
|
|
|
if (!segment_start_time_) {
|
|
|
|
DCHECK(!subsegment_start_time_);
|
|
|
|
// Discard samples before segment start. If the segment has started,
|
|
|
|
// |segment_start_time_| won't be null.
|
2018-01-09 01:18:15 +00:00
|
|
|
return Status::OK;
|
2018-03-21 02:13:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
segment_start_time_ = std::min(segment_start_time_.value(), timestamp);
|
|
|
|
subsegment_start_time_ = std::min(subsegment_start_time_.value(), timestamp);
|
|
|
|
max_segment_time_ =
|
|
|
|
std::max(max_segment_time_, timestamp + sample->duration());
|
2018-03-20 17:12:18 +00:00
|
|
|
return DispatchMediaSample(kStreamIndex, std::move(sample));
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
}
|
|
|
|
|
2024-05-02 20:25:49 +00:00
|
|
|
Status ChunkingHandler::EndSegmentIfStarted() {
|
2018-03-20 17:12:18 +00:00
|
|
|
if (!segment_start_time_)
|
|
|
|
return Status::OK;
|
2018-01-09 01:18:15 +00:00
|
|
|
|
2018-03-20 17:12:18 +00:00
|
|
|
auto segment_info = std::make_shared<SegmentInfo>();
|
|
|
|
segment_info->start_timestamp = segment_start_time_.value();
|
2018-03-21 02:13:22 +00:00
|
|
|
segment_info->duration = max_segment_time_ - segment_start_time_.value();
|
2024-05-02 20:25:49 +00:00
|
|
|
segment_info->segment_number = segment_number_++;
|
|
|
|
|
2021-08-25 15:38:05 +00:00
|
|
|
if (chunking_params_.low_latency_dash_mode) {
|
|
|
|
segment_info->is_chunk = true;
|
|
|
|
segment_info->is_final_chunk_in_seg = true;
|
|
|
|
}
|
2024-05-02 20:25:49 +00:00
|
|
|
|
2018-03-20 17:12:18 +00:00
|
|
|
return DispatchSegmentInfo(kStreamIndex, std::move(segment_info));
|
2018-01-09 01:18:15 +00:00
|
|
|
}
|
|
|
|
|
2018-03-20 17:12:18 +00:00
|
|
|
Status ChunkingHandler::EndSubsegmentIfStarted() const {
|
|
|
|
if (!subsegment_start_time_)
|
|
|
|
return Status::OK;
|
2018-01-09 01:18:15 +00:00
|
|
|
|
2018-03-20 17:12:18 +00:00
|
|
|
auto subsegment_info = std::make_shared<SegmentInfo>();
|
|
|
|
subsegment_info->start_timestamp = subsegment_start_time_.value();
|
|
|
|
subsegment_info->duration =
|
2018-03-21 02:13:22 +00:00
|
|
|
max_segment_time_ - subsegment_start_time_.value();
|
2018-03-20 17:12:18 +00:00
|
|
|
subsegment_info->is_subsegment = true;
|
2021-08-25 15:38:05 +00:00
|
|
|
if (chunking_params_.low_latency_dash_mode)
|
|
|
|
subsegment_info->is_chunk = true;
|
2018-03-20 17:12:18 +00:00
|
|
|
return DispatchSegmentInfo(kStreamIndex, std::move(subsegment_info));
|
2018-01-09 01:18:15 +00:00
|
|
|
}
|
|
|
|
|
Implement ChunkingHandler
This handler is a multi-in multi-out handler. If more than one input is
provided, there should be one and only one video stream; also, all inputs
should come from the same thread and are synchronized.
There can be multiple chunking handler running in different threads or even
different processes, we use the "consistent chunking algorithm" to make sure
the chunks in different streams are aligned without explicit communcating
with each other - which is not efficient and often difficult.
Consistent Chunking Algorithm:
1. Find the consistent chunkable boundary
Let the timestamps for video frames be (t1, t2, t3, ...). Then a
consistent chunkable boundary is simply the first chunkable boundary after
(tk / N) != (tk-1 / N), where '/' denotes integer division, and N is the
intended chunk duration.
2. Chunk only at the consistent chunkable boundary
This algorithm will make sure the chunks from different video streams are
aligned if they have aligned GoPs. However, this algorithm will only work
for video streams. To be able to chunk non video streams at similar
positions as video streams, ChunkingHandler is designed to accept one video
input and multiple non video inputs, the non video inputs are chunked when
the video input is chunked. If the inputs are synchronized - which is true
if the inputs come from the same demuxer, the video and non video chunks
are aligned.
Change-Id: Id3bad51ab14f311efdb8713b6cd36d36cf9e4639
2017-02-07 18:58:47 +00:00
|
|
|
} // namespace media
|
|
|
|
} // namespace shaka
|