Shaka Packager SDK
Loading...
Searching...
No Matches
ttml_to_mp4_handler.cc
1// Copyright 2020 Google LLC. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file or at
5// https://developers.google.com/open-source/licenses/bsd
6
7#include <packager/media/formats/ttml/ttml_to_mp4_handler.h>
8
9#include <absl/log/check.h>
10
11#include <packager/macros/status.h>
12
13namespace shaka {
14namespace media {
15namespace ttml {
16
17namespace {
18
19size_t kTrackId = 0;
20
21std::shared_ptr<MediaSample> CreateMediaSample(const std::string& data,
22 int64_t start_time,
23 int64_t duration) {
24 DCHECK_GE(start_time, 0);
25 DCHECK_GT(duration, 0);
26
27 const bool kIsKeyFrame = true;
28
29 std::shared_ptr<MediaSample> sample = MediaSample::CopyFrom(
30 reinterpret_cast<const uint8_t*>(data.data()), data.size(), kIsKeyFrame);
31 sample->set_pts(start_time);
32 sample->set_dts(start_time);
33 sample->set_duration(duration);
34
35 return sample;
36}
37
38} // namespace
39
40Status TtmlToMp4Handler::InitializeInternal() {
41 return Status::OK;
42}
43
44Status TtmlToMp4Handler::Process(std::unique_ptr<StreamData> stream_data) {
45 switch (stream_data->stream_data_type) {
46 case StreamDataType::kStreamInfo:
47 return OnStreamInfo(std::move(stream_data));
48 case StreamDataType::kCueEvent:
49 return OnCueEvent(std::move(stream_data));
50 case StreamDataType::kSegmentInfo:
51 return OnSegmentInfo(std::move(stream_data));
52 case StreamDataType::kTextSample:
53 return OnTextSample(std::move(stream_data));
54 default:
55 return Status(error::INTERNAL_ERROR,
56 "Invalid stream data type (" +
57 StreamDataTypeToString(stream_data->stream_data_type) +
58 ") for this TtmlToMp4 handler");
59 }
60}
61
62Status TtmlToMp4Handler::OnStreamInfo(std::unique_ptr<StreamData> stream_data) {
63 DCHECK(stream_data);
64 DCHECK(stream_data->stream_info);
65
66 auto clone = stream_data->stream_info->Clone();
67 clone->set_codec(kCodecTtml);
68 clone->set_codec_string("ttml");
69
70 if (clone->stream_type() != kStreamText)
71 return Status(error::MUXER_FAILURE, "Incorrect stream type");
72 auto* text_stream = static_cast<const TextStreamInfo*>(clone.get());
73 generator_.Initialize(text_stream->regions(), text_stream->language(),
74 text_stream->time_scale());
75
76 return Dispatch(
77 StreamData::FromStreamInfo(stream_data->stream_index, std::move(clone)));
78}
79
80Status TtmlToMp4Handler::OnCueEvent(std::unique_ptr<StreamData> stream_data) {
81 DCHECK(stream_data);
82 DCHECK(stream_data->cue_event);
83 return Dispatch(std::move(stream_data));
84}
85
86Status TtmlToMp4Handler::OnSegmentInfo(
87 std::unique_ptr<StreamData> stream_data) {
88 DCHECK(stream_data);
89 DCHECK(stream_data->segment_info);
90
91 const auto& segment = stream_data->segment_info;
92
93 std::string data;
94 if (!generator_.Dump(&data))
95 return Status(error::INTERNAL_ERROR, "Error generating XML");
96 generator_.Reset();
97
98 RETURN_IF_ERROR(DispatchMediaSample(
99 kTrackId,
100 CreateMediaSample(data, segment->start_timestamp, segment->duration)));
101
102 return Dispatch(std::move(stream_data));
103}
104
105Status TtmlToMp4Handler::OnTextSample(std::unique_ptr<StreamData> stream_data) {
106 DCHECK(stream_data);
107 DCHECK(stream_data->text_sample);
108
109 auto& sample = stream_data->text_sample;
110
111 // Ignore empty samples. This will create gaps, but we will handle that
112 // later.
113 if (sample->body().is_empty()) {
114 return Status::OK;
115 }
116
117 // Add the new text sample to the cache of samples that belong in the
118 // current segment.
119 generator_.AddSample(*sample);
120 return Status::OK;
121}
122
123} // namespace ttml
124} // namespace media
125} // namespace shaka
Status DispatchMediaSample(size_t stream_index, std::shared_ptr< const MediaSample > media_sample) const
Dispatch the media sample to downstream handlers.
Status Dispatch(std::unique_ptr< StreamData > stream_data) const
static std::shared_ptr< MediaSample > CopyFrom(const uint8_t *data, size_t size, bool is_key_frame)
All the methods that are virtual are virtual for mocking.