shaka-packager/packager/media/trick_play/trick_play_handler.h

95 lines
3.8 KiB
C
Raw Normal View History

// Copyright 2017 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#ifndef PACKAGER_MEDIA_BASE_TRICK_PLAY_HANDLER_H_
#define PACKAGER_MEDIA_BASE_TRICK_PLAY_HANDLER_H_
#include "packager/media/base/media_handler.h"
namespace shaka {
namespace media {
struct TrickPlayOptions {
/// Trick play rates. Note that there can be multiple trick play rates,
/// e.g., 2, 4 and 8. That means, one input video stream will generate 3
/// output trick play streams and original stream. Three trick play streams
/// are:
/// [key_frame_0, key_frame_2, key_frame_4, ...]
/// [key_frame_0, key_frame_4, key_frame_8,...]
/// [key_frame_0, key_frame_8, key_frame_16, ...].
std::vector<int16_t> trick_play_rates;
};
/// TrickPlayHandler is a single-input-multiple-output media handler. It creates
/// trick play streams from the input.
// The stream data in trick play stream is not a simple duplicate. Some
// information need to be updated, including trick_play_rate in
// VideoStreamInfo, the duration in MediaSample (which makes sure there is no
// gap between the media sample dts). Since the duration information can be
// determined after getting the next media sample, a queue is used to cache the
// input stream data before the next key frame.
class TrickPlayHandler : public MediaHandler {
public:
explicit TrickPlayHandler(const TrickPlayOptions& trick_play_options);
~TrickPlayHandler() override;
protected:
/// @name MediaHandler implementation overrides.
/// @{
Status InitializeInternal() override;
Status Process(std::unique_ptr<StreamData> stream_data) override;
bool ValidateOutputStreamIndex(size_t stream_index) const override;
Status OnFlushRequest(size_t input_stream_index) override;
/// @}
private:
friend class TrickPlayHandlerTest;
// Process the cached stream data for one trick play stream.
// The cached data is dispatched to the |output_stream_index|.
// The |current_dts| is for updating the duration of key frames,
// so that there is no gap between consecutive key frames. When
// |current_dts| = -1, the original duration of the key frame is used.
Status ProcessCachedStreamData(
int output_stream_index,
std::deque<std::shared_ptr<StreamData>>* cached_stream_data);
// Process a single stream data. Depending on the stream data type, some
// information needs to be updated.
// Decoding timestamp for current key media sample. It is used for calculating
// the duration of previous key media sample, to make sure there is no gap
// between two key media samples.
Status ProcessOneStreamData(int output_stream_index,
const std::shared_ptr<StreamData>& stream_data);
const TrickPlayOptions trick_play_options_;
TrickPlayHandler(const TrickPlayHandler&) = delete;
TrickPlayHandler& operator=(const TrickPlayHandler&) = delete;
/// Num of key frames received.
uint32_t total_key_frames_ = 0;
// End timestamp of the previous processed media_sample, which is |dts| +
// |duration|. The duration of key frame in trick play stream is updated based
// on this timestamp.
int64_t prev_sample_end_timestamp_ = 0;
// The data in output streams should be in the same order as in the input
// stream. Cache the stream data before next key frame so that we can
// determine the duration for the current key frame. Since one key frame may
// be dispatched to different trick play stream, each trick play stream need
// its own queue to handle the synchronization.
// TODO(hmchen): Use one queue and multiple iterators, instead of multiple
// queues.
std::vector<std::deque<std::shared_ptr<StreamData>>> cached_stream_data_;
};
} // namespace media
} // namespace shaka
#endif // PACKAGER_MEDIA_BASE_TRICK_PLAY_HANDLER_H_