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"
15 TrickPlayHandler::TrickPlayHandler(
const TrickPlayOptions& trick_play_option)
16 : trick_play_options_(trick_play_option),
17 cached_stream_data_(trick_play_option.trick_play_rates.size()) {
18 for (
auto rate : trick_play_option.trick_play_rates) {
23 TrickPlayHandler::~TrickPlayHandler() {}
30 std::unique_ptr<StreamData> input_stream_data) {
33 DCHECK_EQ(input_stream_data->stream_index, 0u);
34 std::unique_ptr<StreamData> output_stream_data(
new StreamData());
35 *output_stream_data = *input_stream_data;
36 Status status = Dispatch(std::move(output_stream_data));
41 std::shared_ptr<StreamData> stream_data(std::move(input_stream_data));
42 if (stream_data->stream_data_type == StreamDataType::kStreamInfo) {
43 if (stream_data->stream_info->stream_type() != kStreamVideo) {
44 status.
SetError(error::TRICK_PLAY_ERROR,
45 "Trick play does not support non-video stream");
50 if (video_stream_info.trick_play_rate() > 0) {
51 status.
SetError(error::TRICK_PLAY_ERROR,
52 "This stream is alreay a trick play stream.");
57 if (stream_data->stream_data_type != StreamDataType::kMediaSample) {
61 for (
size_t i = 0; i < cached_stream_data_.size(); ++i)
62 cached_stream_data_[i].push_back(stream_data);
66 if (stream_data->media_sample->is_key_frame()) {
69 DCHECK_EQ(trick_play_options_.trick_play_rates.size(),
70 cached_stream_data_.size());
71 for (
size_t i = 0; i < cached_stream_data_.size(); ++i) {
72 int16_t rate = trick_play_options_.trick_play_rates[i];
73 if (total_key_frames_ % rate == 0) {
74 if (!cached_stream_data_[i].empty()) {
76 ProcessCachedStreamData(i + 1, &cached_stream_data_[i]);
80 cached_stream_data_[i].push_back(stream_data);
87 prev_sample_end_timestamp_ =
88 stream_data->media_sample->dts() + stream_data->media_sample->duration();
95 return stream_index <= trick_play_options_.trick_play_rates.size();
99 DCHECK_EQ(input_stream_index, 0u)
100 <<
"Trick Play Handler should only have single input.";
101 for (
size_t i = 0; i < cached_stream_data_.size(); ++i) {
102 ProcessCachedStreamData(i + 1, &cached_stream_data_[i]);
107 Status TrickPlayHandler::ProcessCachedStreamData(
108 size_t output_stream_index,
109 std::deque<std::shared_ptr<StreamData>>* cached_stream_data) {
110 while (!cached_stream_data->empty()) {
112 ProcessOneStreamData(output_stream_index, cached_stream_data->front());
116 cached_stream_data->pop_front();
121 Status TrickPlayHandler::ProcessOneStreamData(
122 size_t output_stream_index,
123 const std::shared_ptr<StreamData>& stream_data) {
124 uint32_t trick_play_rate =
125 trick_play_options_.trick_play_rates[output_stream_index - 1];
127 switch (stream_data->stream_data_type) {
129 case StreamDataType::kStreamInfo: {
130 const VideoStreamInfo& video_stream_info =
131 static_cast<const VideoStreamInfo&
>(*stream_data->stream_info);
132 std::shared_ptr<VideoStreamInfo> trick_play_video_stream_info(
133 new VideoStreamInfo(video_stream_info));
134 trick_play_video_stream_info->set_trick_play_rate(trick_play_rate);
136 DispatchStreamInfo(output_stream_index, trick_play_video_stream_info);
139 case StreamDataType::kMediaSample: {
140 if (stream_data->media_sample->is_key_frame()) {
141 std::shared_ptr<MediaSample> trick_play_media_sample =
143 trick_play_media_sample->set_duration(prev_sample_end_timestamp_ -
144 stream_data->media_sample->dts());
147 DispatchMediaSample(output_stream_index, trick_play_media_sample);
152 std::unique_ptr<StreamData> new_stream_data(
new StreamData(*stream_data));
153 new_stream_data->stream_index = output_stream_index;
154 status = Dispatch(std::move(new_stream_data));