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
|
|
|
|
|
|
|
#include <gmock/gmock.h>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
2023-12-01 17:32:19 +00:00
|
|
|
#include <packager/media/base/media_handler_test_base.h>
|
|
|
|
#include <packager/status/status_test_util.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-05-25 17:41:02 +00:00
|
|
|
using ::testing::_;
|
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
|
|
|
using ::testing::ElementsAre;
|
|
|
|
using ::testing::IsEmpty;
|
|
|
|
|
|
|
|
namespace shaka {
|
|
|
|
namespace media {
|
|
|
|
namespace {
|
2018-03-20 17:12:18 +00:00
|
|
|
const size_t kStreamIndex = 0;
|
2021-08-04 18:56:44 +00:00
|
|
|
const int32_t kTimeScale0 = 800;
|
|
|
|
const int32_t kTimeScale1 = 1000;
|
2018-03-20 17:12:18 +00:00
|
|
|
const int64_t kDuration = 300;
|
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
|
|
|
const bool kKeyFrame = true;
|
|
|
|
const bool kIsSubsegment = true;
|
|
|
|
const bool kEncrypted = true;
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2017-09-14 16:23:29 +00:00
|
|
|
class ChunkingHandlerTest : public MediaHandlerGraphTestBase {
|
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
|
|
|
public:
|
|
|
|
void SetUpChunkingHandler(int num_inputs,
|
2017-07-27 17:23:27 +00:00
|
|
|
const ChunkingParams& chunking_params) {
|
|
|
|
chunking_handler_.reset(new ChunkingHandler(chunking_params));
|
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
|
|
|
SetUpGraph(num_inputs, num_inputs, chunking_handler_);
|
|
|
|
ASSERT_OK(chunking_handler_->Initialize());
|
|
|
|
}
|
|
|
|
|
|
|
|
Status Process(std::unique_ptr<StreamData> stream_data) {
|
|
|
|
return chunking_handler_->Process(std::move(stream_data));
|
|
|
|
}
|
|
|
|
|
2017-02-22 20:14:26 +00:00
|
|
|
Status OnFlushRequest(int stream_index) {
|
|
|
|
return chunking_handler_->OnFlushRequest(stream_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
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
std::shared_ptr<ChunkingHandler> chunking_handler_;
|
|
|
|
};
|
|
|
|
|
|
|
|
TEST_F(ChunkingHandlerTest, AudioNoSubsegmentsThenFlush) {
|
2017-07-27 17:23:27 +00:00
|
|
|
ChunkingParams chunking_params;
|
|
|
|
chunking_params.segment_duration_in_seconds = 1;
|
|
|
|
SetUpChunkingHandler(1, chunking_params);
|
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-09-12 17:24:24 +00:00
|
|
|
ASSERT_OK(Process(StreamData::FromStreamInfo(
|
2018-03-20 17:12:18 +00:00
|
|
|
kStreamIndex, GetAudioStreamInfo(kTimeScale0))));
|
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
|
|
|
EXPECT_THAT(
|
|
|
|
GetOutputStreamDataVector(),
|
2018-05-25 17:41:02 +00:00
|
|
|
ElementsAre(IsStreamInfo(kStreamIndex, kTimeScale0, !kEncrypted, _)));
|
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
|
|
|
|
|
|
|
for (int i = 0; i < 5; ++i) {
|
|
|
|
ClearOutputStreamDataVector();
|
2017-09-12 17:24:24 +00:00
|
|
|
ASSERT_OK(Process(StreamData::FromMediaSample(
|
2018-03-20 17:12:18 +00:00
|
|
|
kStreamIndex, GetMediaSample(i * kDuration, kDuration, kKeyFrame))));
|
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
|
|
|
// One output stream_data except when i == 3, which also has SegmentInfo.
|
|
|
|
if (i == 3) {
|
2017-03-11 02:48:04 +00:00
|
|
|
EXPECT_THAT(GetOutputStreamDataVector(),
|
2018-03-20 17:12:18 +00:00
|
|
|
ElementsAre(IsSegmentInfo(kStreamIndex, 0, kDuration * 3,
|
2017-03-11 02:48:04 +00:00
|
|
|
!kIsSubsegment, !kEncrypted),
|
2018-03-20 17:12:18 +00:00
|
|
|
IsMediaSample(kStreamIndex, i * kDuration,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _)));
|
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
|
|
|
} else {
|
|
|
|
EXPECT_THAT(GetOutputStreamDataVector(),
|
2018-03-20 17:12:18 +00:00
|
|
|
ElementsAre(IsMediaSample(kStreamIndex, i * kDuration,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _)));
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ClearOutputStreamDataVector();
|
2018-03-20 17:12:18 +00:00
|
|
|
ASSERT_OK(OnFlushRequest(kStreamIndex));
|
2017-03-11 02:48:04 +00:00
|
|
|
EXPECT_THAT(
|
|
|
|
GetOutputStreamDataVector(),
|
2018-03-20 17:12:18 +00:00
|
|
|
ElementsAre(IsSegmentInfo(kStreamIndex, kDuration * 3, kDuration * 2,
|
2017-03-11 02:48:04 +00:00
|
|
|
!kIsSubsegment, !kEncrypted)));
|
2017-02-24 01:17:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ChunkingHandlerTest, AudioWithSubsegments) {
|
2017-07-27 17:23:27 +00:00
|
|
|
ChunkingParams chunking_params;
|
|
|
|
chunking_params.segment_duration_in_seconds = 1;
|
|
|
|
chunking_params.subsegment_duration_in_seconds = 0.5;
|
|
|
|
SetUpChunkingHandler(1, chunking_params);
|
2017-02-24 01:17:47 +00:00
|
|
|
|
2017-09-12 17:24:24 +00:00
|
|
|
ASSERT_OK(Process(StreamData::FromStreamInfo(
|
2018-03-20 17:12:18 +00:00
|
|
|
kStreamIndex, GetAudioStreamInfo(kTimeScale0))));
|
2017-02-24 01:17:47 +00:00
|
|
|
for (int i = 0; i < 5; ++i) {
|
2017-09-12 17:24:24 +00:00
|
|
|
ASSERT_OK(Process(StreamData::FromMediaSample(
|
2018-03-20 17:12:18 +00:00
|
|
|
kStreamIndex, GetMediaSample(i * kDuration, kDuration, kKeyFrame))));
|
2017-02-24 01:17:47 +00:00
|
|
|
}
|
|
|
|
EXPECT_THAT(
|
|
|
|
GetOutputStreamDataVector(),
|
|
|
|
ElementsAre(
|
2018-05-25 17:41:02 +00:00
|
|
|
IsStreamInfo(kStreamIndex, kTimeScale0, !kEncrypted, _),
|
2018-06-14 23:39:59 +00:00
|
|
|
IsMediaSample(kStreamIndex, 0, kDuration, !kEncrypted, _),
|
|
|
|
IsMediaSample(kStreamIndex, kDuration, kDuration, !kEncrypted, _),
|
2018-03-20 17:12:18 +00:00
|
|
|
IsSegmentInfo(kStreamIndex, 0, kDuration * 2, kIsSubsegment,
|
2017-03-11 02:48:04 +00:00
|
|
|
!kEncrypted),
|
2018-06-14 23:39:59 +00:00
|
|
|
IsMediaSample(kStreamIndex, 2 * kDuration, kDuration, !kEncrypted, _),
|
2018-03-20 17:12:18 +00:00
|
|
|
IsSegmentInfo(kStreamIndex, 0, kDuration * 3, !kIsSubsegment,
|
2017-03-11 02:48:04 +00:00
|
|
|
!kEncrypted),
|
2018-06-14 23:39:59 +00:00
|
|
|
IsMediaSample(kStreamIndex, 3 * kDuration, kDuration, !kEncrypted, _),
|
|
|
|
IsMediaSample(kStreamIndex, 4 * kDuration, kDuration, !kEncrypted,
|
|
|
|
_)));
|
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
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ChunkingHandlerTest, VideoAndSubsegmentAndNonzeroStart) {
|
2017-07-27 17:23:27 +00:00
|
|
|
ChunkingParams chunking_params;
|
|
|
|
chunking_params.segment_duration_in_seconds = 1;
|
|
|
|
chunking_params.subsegment_duration_in_seconds = 0.3;
|
|
|
|
SetUpChunkingHandler(1, chunking_params);
|
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-09-12 17:24:24 +00:00
|
|
|
ASSERT_OK(Process(StreamData::FromStreamInfo(
|
2018-03-20 17:12:18 +00:00
|
|
|
kStreamIndex, GetVideoStreamInfo(kTimeScale1))));
|
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
|
|
|
const int64_t kVideoStartTimestamp = 12345;
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
|
|
// Alternate key frame.
|
|
|
|
const bool is_key_frame = (i % 2) == 1;
|
2017-09-12 17:24:24 +00:00
|
|
|
ASSERT_OK(Process(StreamData::FromMediaSample(
|
2018-03-20 17:12:18 +00:00
|
|
|
kStreamIndex, GetMediaSample(kVideoStartTimestamp + i * kDuration,
|
|
|
|
kDuration, is_key_frame))));
|
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
|
|
|
}
|
|
|
|
EXPECT_THAT(
|
|
|
|
GetOutputStreamDataVector(),
|
|
|
|
ElementsAre(
|
2018-05-25 17:41:02 +00:00
|
|
|
IsStreamInfo(kStreamIndex, kTimeScale1, !kEncrypted, _),
|
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
|
|
|
// The first samples @ kStartTimestamp is discarded - not key frame.
|
2018-03-20 17:12:18 +00:00
|
|
|
IsMediaSample(kStreamIndex, kVideoStartTimestamp + kDuration,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _),
|
2018-03-20 17:12:18 +00:00
|
|
|
IsMediaSample(kStreamIndex, kVideoStartTimestamp + kDuration * 2,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _),
|
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
|
|
|
// The next segment boundary 13245 / 1000 != 12645 / 1000.
|
2018-03-20 17:12:18 +00:00
|
|
|
IsSegmentInfo(kStreamIndex, kVideoStartTimestamp + kDuration,
|
|
|
|
kDuration * 2, !kIsSubsegment, !kEncrypted),
|
|
|
|
IsMediaSample(kStreamIndex, kVideoStartTimestamp + kDuration * 3,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _),
|
2018-03-20 17:12:18 +00:00
|
|
|
IsMediaSample(kStreamIndex, kVideoStartTimestamp + kDuration * 4,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _),
|
2018-03-20 17:12:18 +00:00
|
|
|
// The subsegment has duration kDuration * 2 since it can only
|
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
|
|
|
// terminate before key frame.
|
2018-03-20 17:12:18 +00:00
|
|
|
IsSegmentInfo(kStreamIndex, kVideoStartTimestamp + kDuration * 3,
|
|
|
|
kDuration * 2, kIsSubsegment, !kEncrypted),
|
|
|
|
IsMediaSample(kStreamIndex, kVideoStartTimestamp + kDuration * 5,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _)));
|
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
|
|
|
TEST_F(ChunkingHandlerTest, CueEvent) {
|
2018-01-03 00:10:33 +00:00
|
|
|
ChunkingParams chunking_params;
|
|
|
|
chunking_params.segment_duration_in_seconds = 1;
|
|
|
|
chunking_params.subsegment_duration_in_seconds = 0.5;
|
|
|
|
SetUpChunkingHandler(1, chunking_params);
|
|
|
|
|
|
|
|
ASSERT_OK(Process(StreamData::FromStreamInfo(
|
2018-03-20 17:12:18 +00:00
|
|
|
kStreamIndex, GetVideoStreamInfo(kTimeScale1))));
|
2018-03-21 18:03:54 +00:00
|
|
|
ClearOutputStreamDataVector();
|
2018-01-03 00:10:33 +00:00
|
|
|
|
|
|
|
const int64_t kVideoStartTimestamp = 12345;
|
2018-03-20 17:12:18 +00:00
|
|
|
const double kCueTimeInSeconds =
|
|
|
|
static_cast<double>(kVideoStartTimestamp + kDuration) / kTimeScale1;
|
2018-01-03 00:10:33 +00:00
|
|
|
|
2018-03-20 17:12:18 +00:00
|
|
|
auto cue_event = std::make_shared<CueEvent>();
|
|
|
|
cue_event->time_in_seconds = kCueTimeInSeconds;
|
2018-01-03 00:10:33 +00:00
|
|
|
|
2018-03-21 18:03:54 +00:00
|
|
|
for (int i = 0; i < 6; ++i) {
|
2018-01-03 00:10:33 +00:00
|
|
|
const bool is_key_frame = true;
|
|
|
|
ASSERT_OK(Process(StreamData::FromMediaSample(
|
2018-03-20 17:12:18 +00:00
|
|
|
kStreamIndex, GetMediaSample(kVideoStartTimestamp + i * kDuration,
|
|
|
|
kDuration, is_key_frame))));
|
|
|
|
if (i == 0) {
|
|
|
|
ASSERT_OK(Process(StreamData::FromCueEvent(kStreamIndex, cue_event)));
|
|
|
|
}
|
2018-01-03 00:10:33 +00:00
|
|
|
}
|
2018-03-15 23:01:47 +00:00
|
|
|
|
2018-01-03 00:10:33 +00:00
|
|
|
EXPECT_THAT(
|
|
|
|
GetOutputStreamDataVector(),
|
|
|
|
ElementsAre(
|
2018-03-20 17:12:18 +00:00
|
|
|
IsMediaSample(kStreamIndex, kVideoStartTimestamp, kDuration,
|
2018-06-14 23:39:59 +00:00
|
|
|
!kEncrypted, _),
|
2018-01-03 00:10:33 +00:00
|
|
|
// A new segment is created due to the existance of Cue.
|
2018-03-20 17:12:18 +00:00
|
|
|
IsSegmentInfo(kStreamIndex, kVideoStartTimestamp, kDuration,
|
2018-01-03 00:10:33 +00:00
|
|
|
!kIsSubsegment, !kEncrypted),
|
2018-03-20 17:12:18 +00:00
|
|
|
IsCueEvent(kStreamIndex, kCueTimeInSeconds),
|
|
|
|
IsMediaSample(kStreamIndex, kVideoStartTimestamp + kDuration * 1,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _),
|
2018-03-20 17:12:18 +00:00
|
|
|
IsMediaSample(kStreamIndex, kVideoStartTimestamp + kDuration * 2,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _),
|
2018-03-21 18:03:54 +00:00
|
|
|
IsSegmentInfo(kStreamIndex, kVideoStartTimestamp + kDuration,
|
|
|
|
kDuration * 2, kIsSubsegment, !kEncrypted),
|
|
|
|
IsMediaSample(kStreamIndex, kVideoStartTimestamp + kDuration * 3,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _),
|
2018-03-21 18:03:54 +00:00
|
|
|
IsMediaSample(kStreamIndex, kVideoStartTimestamp + kDuration * 4,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _),
|
2018-03-21 18:03:54 +00:00
|
|
|
IsSegmentInfo(kStreamIndex, kVideoStartTimestamp + kDuration,
|
|
|
|
kDuration * 4, !kIsSubsegment, !kEncrypted),
|
|
|
|
IsMediaSample(kStreamIndex, kVideoStartTimestamp + kDuration * 5,
|
2018-06-14 23:39:59 +00:00
|
|
|
kDuration, !kEncrypted, _)));
|
2018-01-03 00:10:33 +00:00
|
|
|
}
|
|
|
|
|
2021-08-25 15:38:05 +00:00
|
|
|
TEST_F(ChunkingHandlerTest, LowLatencyDash) {
|
|
|
|
ChunkingParams chunking_params;
|
|
|
|
chunking_params.low_latency_dash_mode = true;
|
|
|
|
chunking_params.segment_duration_in_seconds = 1;
|
|
|
|
SetUpChunkingHandler(1, chunking_params);
|
|
|
|
|
|
|
|
// Each completed segment will contain 2 chunks
|
|
|
|
const int64_t kChunkDurationInMs = 500;
|
|
|
|
const int64_t kSegmentDurationInMs = 1000;
|
|
|
|
|
|
|
|
ASSERT_OK(Process(StreamData::FromStreamInfo(
|
|
|
|
kStreamIndex, GetVideoStreamInfo(kTimeScale1))));
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
ASSERT_OK(Process(StreamData::FromMediaSample(
|
|
|
|
kStreamIndex, GetMediaSample(i * kChunkDurationInMs, kChunkDurationInMs,
|
|
|
|
kKeyFrame))));
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Each MediaSample will create a chunk, dispatching SegmentInfo
|
|
|
|
EXPECT_THAT(
|
|
|
|
GetOutputStreamDataVector(),
|
|
|
|
ElementsAre(
|
|
|
|
IsStreamInfo(kStreamIndex, kTimeScale1, !kEncrypted, _),
|
|
|
|
// Chunk 1 for segment 1
|
|
|
|
IsMediaSample(kStreamIndex, 0, kChunkDurationInMs, !kEncrypted, _),
|
|
|
|
IsSegmentInfo(kStreamIndex, 0, kChunkDurationInMs, kIsSubsegment,
|
|
|
|
!kEncrypted),
|
|
|
|
// Chunk 2 for segment 1
|
|
|
|
IsMediaSample(kStreamIndex, kChunkDurationInMs, kChunkDurationInMs,
|
|
|
|
!kEncrypted, _),
|
|
|
|
IsSegmentInfo(kStreamIndex, 0, 2 * kChunkDurationInMs, !kIsSubsegment,
|
|
|
|
!kEncrypted),
|
|
|
|
// Chunk 1 for segment 2
|
|
|
|
IsMediaSample(kStreamIndex, kSegmentDurationInMs, kChunkDurationInMs,
|
|
|
|
!kEncrypted, _),
|
|
|
|
IsSegmentInfo(kStreamIndex, kSegmentDurationInMs, kChunkDurationInMs,
|
|
|
|
kIsSubsegment, !kEncrypted),
|
|
|
|
// Chunk 2 for segment 2
|
|
|
|
IsMediaSample(kStreamIndex, kSegmentDurationInMs + kChunkDurationInMs,
|
|
|
|
kChunkDurationInMs, !kEncrypted, _)));
|
|
|
|
}
|
|
|
|
|
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
|