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 const size_t kStreamIndexIn = 0;
16 const size_t kStreamIndexOut = 0;
19 TrickPlayHandler::TrickPlayHandler(uint32_t factor) : factor_(factor) {
21 <<
"Trick Play Handles must have a factor of 1 or higher.";
24 Status TrickPlayHandler::InitializeInternal() {
28 Status TrickPlayHandler::Process(std::unique_ptr<StreamData> stream_data) {
30 DCHECK_EQ(stream_data->stream_index, kStreamIndexIn);
32 switch (stream_data->stream_data_type) {
33 case StreamDataType::kStreamInfo:
34 return OnStreamInfo(*stream_data->stream_info);
36 case StreamDataType::kSegmentInfo:
37 return OnSegmentInfo(std::move(stream_data->segment_info));
39 case StreamDataType::kMediaSample:
40 return OnMediaSample(*stream_data->media_sample);
43 return Status(error::TRICK_PLAY_ERROR,
44 "Trick play only supports stream info, segment info, and " 45 "media sample messages.");
49 Status TrickPlayHandler::OnFlushRequest(
size_t input_stream_index) {
50 DCHECK_EQ(input_stream_index, 0u);
55 while (s.ok() && delayed_messages_.size()) {
56 s.Update(
Dispatch(std::move(delayed_messages_.front())));
57 delayed_messages_.pop_front();
63 Status TrickPlayHandler::OnStreamInfo(
const StreamInfo& info) {
64 if (info.stream_type() != kStreamVideo) {
65 return Status(error::TRICK_PLAY_ERROR,
66 "Trick play does not support non-video stream");
71 video_info_ = std::make_shared<VideoStreamInfo>(
72 static_cast<const VideoStreamInfo&
>(info));
74 if (video_info_->trick_play_factor() > 0) {
75 return Status(error::TRICK_PLAY_ERROR,
76 "This stream is already a trick play stream.");
79 video_info_->set_trick_play_factor(factor_);
80 video_info_->set_playback_rate(0);
85 delayed_messages_.push_back(
86 StreamData::FromStreamInfo(kStreamIndexOut, video_info_));
91 Status TrickPlayHandler::OnSegmentInfo(
92 std::shared_ptr<const SegmentInfo> info) {
93 if (delayed_messages_.empty()) {
94 return Status(error::TRICK_PLAY_ERROR,
95 "Cannot handle segments with no preceding samples.");
99 if (info->is_subsegment) {
103 const StreamDataType previous_type =
104 delayed_messages_.back()->stream_data_type;
106 switch (previous_type) {
107 case StreamDataType::kSegmentInfo:
111 previous_segment_->duration += info->duration;
114 case StreamDataType::kMediaSample:
119 previous_segment_ = std::make_shared<SegmentInfo>(*info);
120 delayed_messages_.push_back(
121 StreamData::FromSegmentInfo(kStreamIndexOut, previous_segment_));
125 return Status(error::TRICK_PLAY_ERROR,
126 "Unexpected sample in trick play deferred queue : type=" +
127 std::to_string(static_cast<int>(previous_type)));
131 Status TrickPlayHandler::OnMediaSample(
const MediaSample& sample) {
134 if (sample.is_key_frame()) {
137 if ((total_key_frames_ - 1) % factor_ == 0) {
138 return OnTrickFrame(sample);
143 if (total_trick_frames_ < 2) {
150 video_info_->set_playback_rate(total_frames_);
156 DCHECK(previous_trick_frame_);
157 previous_trick_frame_->set_duration(previous_trick_frame_->duration() +
163 Status TrickPlayHandler::OnTrickFrame(
const MediaSample& sample) {
164 total_trick_frames_++;
167 previous_trick_frame_ = sample.Clone();
170 delayed_messages_.push_back(
171 StreamData::FromMediaSample(kStreamIndexOut, previous_trick_frame_));
176 if (total_trick_frames_ < 2) {
183 while (s.ok() && delayed_messages_.size() > 1) {
184 s.Update(
Dispatch(std::move(delayed_messages_.front())));
185 delayed_messages_.pop_front();
All the methods that are virtual are virtual for mocking.