Don't Always Start Text At Time Zero
Previously, the text padder media handler would assume that text always started at time zero. This would work for VOD but would result with a large pad at the start of LIVE content. To avoid this, the text padder will use a bias to test whether or not it thinks the content starts at zero. Right now the bias is set to be 10 minutes, but will later be configurable with a command line flag. 10 minutes was used as LIVE content will have much larger values and VOD content should have much lower values. Issue: #416 Change-Id: I07af15a577392fb030e36f052085cd4e667700e8
This commit is contained in:
parent
b4256bf040
commit
1600909c4b
|
@ -16,7 +16,8 @@ namespace {
|
||||||
const uint64_t kStreamIndex = 0;
|
const uint64_t kStreamIndex = 0;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TextPadder::TextPadder(int64_t duration_ms) : duration_ms_(duration_ms) {}
|
TextPadder::TextPadder(int64_t zero_start_bias_ms)
|
||||||
|
: zero_start_bias_ms_(zero_start_bias_ms) {}
|
||||||
|
|
||||||
Status TextPadder::InitializeInternal() {
|
Status TextPadder::InitializeInternal() {
|
||||||
return Status::OK;
|
return Status::OK;
|
||||||
|
@ -30,20 +31,16 @@ Status TextPadder::Process(std::unique_ptr<StreamData> data) {
|
||||||
: Dispatch(std::move(data));
|
: Dispatch(std::move(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
Status TextPadder::OnFlushRequest(size_t index) {
|
|
||||||
if (duration_ms_ > max_end_time_ms_) {
|
|
||||||
std::shared_ptr<TextSample> filler = std::make_shared<TextSample>();
|
|
||||||
filler->SetTime(max_end_time_ms_, duration_ms_);
|
|
||||||
RETURN_IF_ERROR(
|
|
||||||
MediaHandler::DispatchTextSample(kStreamIndex, std::move(filler)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return FlushDownstream(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status TextPadder::OnTextSample(std::unique_ptr<StreamData> data) {
|
Status TextPadder::OnTextSample(std::unique_ptr<StreamData> data) {
|
||||||
const TextSample& sample = *data->text_sample;
|
const TextSample& sample = *data->text_sample;
|
||||||
|
|
||||||
|
// If this is the first sample we have seen, we need to check if we should
|
||||||
|
// start at time zero.
|
||||||
|
if (max_end_time_ms_ < 0) {
|
||||||
|
max_end_time_ms_ =
|
||||||
|
sample.start_time() > zero_start_bias_ms_ ? sample.start_time() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if there will be a gap between samples if we just dispatch this
|
// Check if there will be a gap between samples if we just dispatch this
|
||||||
// sample right away. If there will be one, create an empty sample that will
|
// sample right away. If there will be one, create an empty sample that will
|
||||||
// fill in that gap.
|
// fill in that gap.
|
||||||
|
|
|
@ -13,13 +13,18 @@ namespace shaka {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
/// A media handler that will inject empty text samples to fill any gaps
|
/// A media handler that will inject empty text samples to fill any gaps
|
||||||
/// that may appear in the text stream. A min duration can be given to
|
/// that may appear in the text stream.
|
||||||
/// ensure that the stream will have samples up to the given duration.
|
|
||||||
class TextPadder : public MediaHandler {
|
class TextPadder : public MediaHandler {
|
||||||
public:
|
public:
|
||||||
/// Create a new text padder that will ensure the stream's duration is
|
/// Create a new text padder.
|
||||||
// at least |duration_ms| long.
|
///
|
||||||
explicit TextPadder(int64_t duration_ms);
|
/// |zero_start_bias_ms| is the threshold used to determine if we should
|
||||||
|
/// assume that the stream actually starts at time zero. If the first sample
|
||||||
|
/// comes before the |zero_start_bias_ms|, then the start will be padded as
|
||||||
|
/// the stream is assumed to start at zero. If the first sample comes after
|
||||||
|
/// |zero_start_bias_ms| then the start of the stream will not be padded as
|
||||||
|
/// we cannot assume the start time of the stream.
|
||||||
|
explicit TextPadder(int64_t zero_start_bias_ms);
|
||||||
~TextPadder() override = default;
|
~TextPadder() override = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -29,11 +34,12 @@ class TextPadder : public MediaHandler {
|
||||||
Status InitializeInternal() override;
|
Status InitializeInternal() override;
|
||||||
|
|
||||||
Status Process(std::unique_ptr<StreamData> data) override;
|
Status Process(std::unique_ptr<StreamData> data) override;
|
||||||
Status OnFlushRequest(size_t index) override;
|
|
||||||
Status OnTextSample(std::unique_ptr<StreamData> data);
|
Status OnTextSample(std::unique_ptr<StreamData> data);
|
||||||
|
|
||||||
int64_t duration_ms_;
|
const int64_t zero_start_bias_ms_;
|
||||||
int64_t max_end_time_ms_ = 0;
|
// Will be set once we see our first sample. Using -1 to signal that we have
|
||||||
|
// not seen the first sample yet.
|
||||||
|
int64_t max_end_time_ms_ = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
|
|
|
@ -66,6 +66,8 @@ namespace {
|
||||||
|
|
||||||
const char kMediaInfoSuffix[] = ".media_info";
|
const char kMediaInfoSuffix[] = ".media_info";
|
||||||
|
|
||||||
|
const int64_t kDefaultTextZeroBiasMs = 10 * 60 * 1000; // 10 minutes
|
||||||
|
|
||||||
MuxerOptions CreateMuxerOptions(const StreamDescriptor& stream,
|
MuxerOptions CreateMuxerOptions(const StreamDescriptor& stream,
|
||||||
const PackagingParams& params) {
|
const PackagingParams& params) {
|
||||||
MuxerOptions options;
|
MuxerOptions options;
|
||||||
|
@ -465,10 +467,9 @@ Status CreateHlsTextJob(const StreamDescriptor& stream,
|
||||||
std::unique_ptr<FileReader> reader;
|
std::unique_ptr<FileReader> reader;
|
||||||
RETURN_IF_ERROR(FileReader::Open(stream.input, &reader));
|
RETURN_IF_ERROR(FileReader::Open(stream.input, &reader));
|
||||||
|
|
||||||
const int64_t kNoDuration = 0;
|
|
||||||
auto parser =
|
auto parser =
|
||||||
std::make_shared<WebVttParser>(std::move(reader), stream.language);
|
std::make_shared<WebVttParser>(std::move(reader), stream.language);
|
||||||
auto padder = std::make_shared<TextPadder>(kNoDuration);
|
auto padder = std::make_shared<TextPadder>(kDefaultTextZeroBiasMs);
|
||||||
auto cue_aligner = sync_points
|
auto cue_aligner = sync_points
|
||||||
? std::make_shared<CueAlignmentHandler>(sync_points)
|
? std::make_shared<CueAlignmentHandler>(sync_points)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
@ -490,10 +491,9 @@ Status CreateWebVttToMp4TextJob(const StreamDescriptor& stream,
|
||||||
std::unique_ptr<FileReader> reader;
|
std::unique_ptr<FileReader> reader;
|
||||||
RETURN_IF_ERROR(FileReader::Open(stream.input, &reader));
|
RETURN_IF_ERROR(FileReader::Open(stream.input, &reader));
|
||||||
|
|
||||||
const int64_t kNoDuration = 0;
|
|
||||||
auto parser =
|
auto parser =
|
||||||
std::make_shared<WebVttParser>(std::move(reader), stream.language);
|
std::make_shared<WebVttParser>(std::move(reader), stream.language);
|
||||||
auto padder = std::make_shared<TextPadder>(kNoDuration);
|
auto padder = std::make_shared<TextPadder>(kDefaultTextZeroBiasMs);
|
||||||
|
|
||||||
auto text_to_mp4 = std::make_shared<WebVttToMp4Handler>();
|
auto text_to_mp4 = std::make_shared<WebVttToMp4Handler>();
|
||||||
auto muxer = muxer_factory->CreateMuxer(GetOutputFormat(stream), stream);
|
auto muxer = muxer_factory->CreateMuxer(GetOutputFormat(stream), stream);
|
||||||
|
|
Loading…
Reference in New Issue