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 <cstddef>
10#include <cstdint>
11#include <memory>
12#include <string>
13#include <utility>
14
15#include <absl/log/check.h>
16
17#include <packager/macros/status.h>
18#include <packager/media/base/media_handler.h>
19#include <packager/media/base/media_sample.h>
20#include <packager/media/base/stream_info.h>
21#include <packager/media/base/text_stream_info.h>
22#include <packager/status.h>
23
24namespace shaka {
25namespace media {
26namespace ttml {
27
28namespace {
29
30size_t kTrackId = 0;
31
32std::shared_ptr<MediaSample> CreateMediaSample(const std::string& data,
33 int64_t start_time,
34 int64_t duration) {
35 DCHECK_GE(start_time, 0);
36 DCHECK_GT(duration, 0);
37
38 const bool kIsKeyFrame = true;
39
40 std::shared_ptr<MediaSample> sample = MediaSample::CopyFrom(
41 reinterpret_cast<const uint8_t*>(data.data()), data.size(), kIsKeyFrame);
42 sample->set_pts(start_time);
43 sample->set_dts(start_time);
44 sample->set_duration(duration);
45
46 return sample;
47}
48
49} // namespace
50
51Status TtmlToMp4Handler::InitializeInternal() {
52 return Status::OK;
53}
54
55Status TtmlToMp4Handler::Process(std::unique_ptr<StreamData> stream_data) {
56 switch (stream_data->stream_data_type) {
57 case StreamDataType::kStreamInfo:
58 return OnStreamInfo(std::move(stream_data));
59 case StreamDataType::kCueEvent:
60 return OnCueEvent(std::move(stream_data));
61 case StreamDataType::kSegmentInfo:
62 return OnSegmentInfo(std::move(stream_data));
63 case StreamDataType::kTextSample:
64 return OnTextSample(std::move(stream_data));
65 default:
66 return Status(error::INTERNAL_ERROR,
67 "Invalid stream data type (" +
68 StreamDataTypeToString(stream_data->stream_data_type) +
69 ") for this TtmlToMp4 handler");
70 }
71}
72
73Status TtmlToMp4Handler::OnStreamInfo(std::unique_ptr<StreamData> stream_data) {
74 DCHECK(stream_data);
75 DCHECK(stream_data->stream_info);
76
77 auto clone = stream_data->stream_info->Clone();
78 clone->set_codec(kCodecTtml);
79 clone->set_codec_string("ttml");
80
81 if (clone->stream_type() != kStreamText)
82 return Status(error::MUXER_FAILURE, "Incorrect stream type");
83 auto* text_stream = static_cast<const TextStreamInfo*>(clone.get());
84 generator_.Initialize(text_stream->regions(), text_stream->language(),
85 text_stream->time_scale());
86
87 return Dispatch(
88 StreamData::FromStreamInfo(stream_data->stream_index, std::move(clone)));
89}
90
91Status TtmlToMp4Handler::OnCueEvent(std::unique_ptr<StreamData> stream_data) {
92 DCHECK(stream_data);
93 DCHECK(stream_data->cue_event);
94 return Dispatch(std::move(stream_data));
95}
96
97Status TtmlToMp4Handler::OnSegmentInfo(
98 std::unique_ptr<StreamData> stream_data) {
99 DCHECK(stream_data);
100 DCHECK(stream_data->segment_info);
101
102 const auto& segment = stream_data->segment_info;
103
104 std::string data;
105 if (!generator_.Dump(&data))
106 return Status(error::INTERNAL_ERROR, "Error generating XML");
107 generator_.Reset();
108
109 RETURN_IF_ERROR(DispatchMediaSample(
110 kTrackId,
111 CreateMediaSample(data, segment->start_timestamp, segment->duration)));
112
113 return Dispatch(std::move(stream_data));
114}
115
116Status TtmlToMp4Handler::OnTextSample(std::unique_ptr<StreamData> stream_data) {
117 DCHECK(stream_data);
118 DCHECK(stream_data->text_sample);
119
120 auto& sample = stream_data->text_sample;
121
122 // Ignore empty samples. This will create gaps, but we will handle that
123 // later.
124 if (sample->body().is_empty()) {
125 return Status::OK;
126 }
127
128 // Add the new text sample to the cache of samples that belong in the
129 // current segment.
130 generator_.AddSample(*sample);
131 return Status::OK;
132}
133
134} // namespace ttml
135} // namespace media
136} // 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.