7 #include "packager/media/trick_play/trick_play_handler.h"
9 #include "packager/base/logging.h"
10 #include "packager/media/base/video_stream_info.h"
16 const size_t kMainStreamIndex = 0;
19 TrickPlayHandler::TrickPlayHandler() {}
21 TrickPlayHandler::~TrickPlayHandler() {}
23 void TrickPlayHandler::SetHandlerForMainStream(
24 std::shared_ptr<MediaHandler> handler) {
25 SetHandler(kMainStreamIndex, std::move(handler));
28 void TrickPlayHandler::SetHandlerForTrickPlay(
29 uint32_t trick_play_factor,
30 std::shared_ptr<MediaHandler> handler) {
31 trick_play_factors_.push_back(trick_play_factor);
33 SetHandler(trick_play_factors_.size(), std::move(handler));
37 if (!HasMainStream()) {
38 return Status(error::TRICK_PLAY_ERROR,
39 "Trick play does not have main stream");
41 if (trick_play_factors_.empty()) {
42 return Status(error::TRICK_PLAY_ERROR,
43 "Trick play factors are not specified.");
45 size_t num_trick_play_factors = trick_play_factors_.size();
46 cached_stream_data_.resize(num_trick_play_factors);
47 playback_rates_.resize(num_trick_play_factors, 0);
56 DCHECK_EQ(stream_data->stream_index, 0u);
58 std::unique_ptr<StreamData> copy(
new StreamData);
65 std::shared_ptr<StreamData> shared_stream_data(std::move(stream_data));
67 if (shared_stream_data->stream_data_type == StreamDataType::kStreamInfo) {
68 if (shared_stream_data->stream_info->stream_type() != kStreamVideo) {
69 status.
SetError(error::TRICK_PLAY_ERROR,
70 "Trick play does not support non-video stream");
75 if (video_stream_info.trick_play_factor() > 0) {
76 status.
SetError(error::TRICK_PLAY_ERROR,
77 "This stream is alreay a trick play stream.");
82 if (shared_stream_data->stream_data_type == StreamDataType::kSegmentInfo) {
83 for (
auto& cached_data : cached_stream_data_) {
87 if (!cached_data.empty() &&
88 cached_data.back()->stream_data_type == StreamDataType::kMediaSample)
89 cached_data.push_back(shared_stream_data);
94 if (shared_stream_data->stream_data_type != StreamDataType::kMediaSample) {
98 for (
size_t i = 0; i < cached_stream_data_.size(); ++i)
99 cached_stream_data_[i].push_back(shared_stream_data);
103 if (shared_stream_data->media_sample->is_key_frame()) {
106 DCHECK_EQ(trick_play_factors_.size(), cached_stream_data_.size());
107 for (
size_t i = 0; i < cached_stream_data_.size(); ++i) {
108 uint32_t factor = trick_play_factors_[i];
109 if (total_key_frames_ % factor == 0) {
112 if (!cached_stream_data_[i].empty() && total_key_frames_ > 0) {
115 if (playback_rates_[i] == 0)
116 playback_rates_[i] = total_frames_;
119 ProcessCachedStreamData(i + 1, &cached_stream_data_[i]);
123 cached_stream_data_[i].push_back(shared_stream_data);
131 prev_sample_end_timestamp_ = shared_stream_data->media_sample->dts() +
132 shared_stream_data->media_sample->duration();
140 return stream_index <= trick_play_factors_.size();
144 DCHECK_EQ(input_stream_index, 0u)
145 <<
"Trick Play Handler should only have single input.";
146 for (
size_t i = 0; i < cached_stream_data_.size(); ++i) {
147 LOG_IF(WARNING, playback_rates_[i] == 0)
148 <<
"Max playout rate for trick play factor " << trick_play_factors_[i]
149 <<
" is not determined. "
150 <<
"Specify it as total number of frames: " << total_frames_ <<
".";
151 playback_rates_[i] = total_frames_;
152 ProcessCachedStreamData(i + 1, &cached_stream_data_[i]);
157 bool TrickPlayHandler::HasMainStream() {
158 const auto& handlers = output_handlers();
159 const auto& main_stream_handler = handlers.find(kMainStreamIndex);
160 if (main_stream_handler == handlers.end()) {
163 return main_stream_handler->second.first !=
nullptr;
166 Status TrickPlayHandler::ProcessCachedStreamData(
167 size_t output_stream_index,
168 std::deque<std::shared_ptr<StreamData>>* cached_stream_data) {
169 while (!cached_stream_data->empty()) {
171 ProcessOneStreamData(output_stream_index, *cached_stream_data->front());
175 cached_stream_data->pop_front();
180 Status TrickPlayHandler::ProcessOneStreamData(
size_t output_stream_index,
181 const StreamData& stream_data) {
182 size_t trick_play_index = output_stream_index - 1;
183 uint32_t trick_play_factor = trick_play_factors_[trick_play_index];
185 switch (stream_data.stream_data_type) {
187 case StreamDataType::kStreamInfo: {
188 const VideoStreamInfo& video_stream_info =
189 static_cast<const VideoStreamInfo&
>(*stream_data.stream_info);
190 std::shared_ptr<VideoStreamInfo> trick_play_video_stream_info(
191 new VideoStreamInfo(video_stream_info));
192 trick_play_video_stream_info->set_trick_play_factor(trick_play_factor);
193 DCHECK_GT(playback_rates_[trick_play_index], 0u);
194 trick_play_video_stream_info->set_playback_rate(
195 playback_rates_[trick_play_index]);
200 case StreamDataType::kMediaSample: {
201 if (stream_data.media_sample->is_key_frame()) {
202 std::shared_ptr<MediaSample> trick_play_media_sample =
204 trick_play_media_sample->set_duration(prev_sample_end_timestamp_ -
205 stream_data.media_sample->dts());
212 std::unique_ptr<StreamData> copy(
new StreamData(stream_data));
213 copy->stream_index = output_stream_index;
void SetError(error::Code error_code, const std::string &error_message)