MediaHandler implementation
MediaHandler is the basic processing unit in shaka-packager 2.0. Change-Id: I5f8d744e39adfff5cfebe0c50a29ead4d717cca4
This commit is contained in:
parent
97fbaaa567
commit
64c6821dc8
|
@ -54,6 +54,8 @@
|
|||
'key_source.h',
|
||||
'limits.h',
|
||||
'macros.h',
|
||||
'media_handler.cc',
|
||||
'media_handler.h',
|
||||
'media_parser.h',
|
||||
'media_sample.cc',
|
||||
'media_sample.h',
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
// 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
|
||||
|
||||
#include "packager/media/base/media_handler.h"
|
||||
|
||||
namespace shaka {
|
||||
namespace media {
|
||||
|
||||
Status MediaHandler::SetHandler(int output_stream_index,
|
||||
std::shared_ptr<MediaHandler> handler) {
|
||||
if (!ValidateOutputStreamIndex(output_stream_index))
|
||||
return Status(error::INVALID_ARGUMENT, "Invalid output stream index");
|
||||
if (output_handlers_.find(output_stream_index) != output_handlers_.end()) {
|
||||
return Status(error::ALREADY_EXISTS,
|
||||
"The handler at the specified index already exists.");
|
||||
}
|
||||
output_handlers_[output_stream_index] =
|
||||
std::make_pair(handler, handler->num_input_streams_++);
|
||||
next_output_stream_index_ = output_stream_index + 1;
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
Status MediaHandler::FlushStream(int input_stream_index) {
|
||||
// The default implementation treats the output stream index to be identical
|
||||
// to the input stream index, which is true for most handlers.
|
||||
auto handler_it = output_handlers_.find(input_stream_index);
|
||||
if (handler_it == output_handlers_.end()) {
|
||||
return Status(error::NOT_FOUND,
|
||||
"No output handler exist at the specified index.");
|
||||
}
|
||||
return handler_it->second.first->FlushStream(handler_it->second.second);
|
||||
}
|
||||
|
||||
bool MediaHandler::ValidateOutputStreamIndex(int stream_index) const {
|
||||
return stream_index >= 0 && stream_index < num_input_streams_;
|
||||
}
|
||||
|
||||
Status MediaHandler::Dispatch(std::unique_ptr<StreamData> stream_data) {
|
||||
int output_stream_index = stream_data->stream_index;
|
||||
auto handler_it = output_handlers_.find(output_stream_index);
|
||||
if (handler_it == output_handlers_.end()) {
|
||||
return Status(error::NOT_FOUND,
|
||||
"No output handler exist at the specified index.");
|
||||
}
|
||||
stream_data->stream_index = handler_it->second.second;
|
||||
return handler_it->second.first->Process(std::move(stream_data));
|
||||
}
|
||||
|
||||
} // namespace media
|
||||
} // namespace shaka
|
|
@ -0,0 +1,169 @@
|
|||
// 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_MEDIA_HANDLER_H_
|
||||
#define PACKAGER_MEDIA_BASE_MEDIA_HANDLER_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "packager/media/base/status.h"
|
||||
|
||||
namespace shaka {
|
||||
namespace media {
|
||||
|
||||
/// MediaHandler is the base media processing unit. Media handlers transform
|
||||
/// the input streams and propagate the outputs to downstream media handlers.
|
||||
/// There are three different types of media handlers:
|
||||
/// 1) Single input single output
|
||||
/// This is the most basic handler. It only supports one input and one
|
||||
/// output with both index as 0.
|
||||
/// 2) Multiple inputs multiple outputs
|
||||
/// The number of outputs must be equal to the number of inputs. The
|
||||
/// output stream at a specific index comes from the input stream at the
|
||||
/// same index. Different streams usually share a common resource, although
|
||||
/// they may be independent. One example of this is encryptor handler.
|
||||
/// 3) Single input multiple outputs
|
||||
/// The input stream is splitted into multiple output streams. One example
|
||||
/// of this is trick play handler.
|
||||
/// Other types of media handlers are disallowed and not supported.
|
||||
class MediaHandler {
|
||||
public:
|
||||
MediaHandler() = default;
|
||||
virtual ~MediaHandler() = default;
|
||||
|
||||
/// Connect downstream handler at the specified output stream index.
|
||||
Status SetHandler(int output_stream_index,
|
||||
std::shared_ptr<MediaHandler> handler);
|
||||
|
||||
/// Connect downstream handler to the next availble output stream index.
|
||||
Status AddHandler(std::shared_ptr<MediaHandler> handler) {
|
||||
return SetHandler(next_output_stream_index_, handler);
|
||||
}
|
||||
|
||||
protected:
|
||||
enum class StreamDataType {
|
||||
kUnknown,
|
||||
kPeriodInfo,
|
||||
kStreamInfo,
|
||||
kEncryptionConfig,
|
||||
kMediaSample,
|
||||
kMediaEvent,
|
||||
kSegmentInfo,
|
||||
};
|
||||
|
||||
// TODO(kqyang): Define these structures.
|
||||
struct PeriodInfo {};
|
||||
struct StreamInfo {};
|
||||
struct EncryptionConfig {};
|
||||
struct MediaSample {};
|
||||
struct MediaEvent {};
|
||||
struct SegmentInfo {};
|
||||
|
||||
// TODO(kqyang): Should we use protobuf?
|
||||
struct StreamData {
|
||||
int stream_index;
|
||||
StreamDataType stream_data_type;
|
||||
|
||||
std::unique_ptr<PeriodInfo> period_info;
|
||||
std::unique_ptr<StreamInfo> stream_info;
|
||||
std::unique_ptr<EncryptionConfig> encryption_config;
|
||||
std::unique_ptr<MediaSample> media_sample;
|
||||
std::unique_ptr<MediaEvent> media_event;
|
||||
std::unique_ptr<SegmentInfo> segment_info;
|
||||
};
|
||||
|
||||
/// Process the incoming stream data. Note that (1) stream_data.stream_index
|
||||
/// should be the input stream index; (2) The implementation needs to call
|
||||
/// DispatchXxx to dispatch the processed stream data to the downstream
|
||||
/// handlers after finishing processing if needed.
|
||||
virtual Status Process(std::unique_ptr<StreamData> stream_data) = 0;
|
||||
|
||||
/// Flush the stream at the specified input stream index.
|
||||
virtual Status FlushStream(int input_stream_index);
|
||||
|
||||
/// Validate if the stream at the specified index actually exists.
|
||||
virtual bool ValidateOutputStreamIndex(int stream_index) const;
|
||||
|
||||
/// Dispatch the stream data to downstream handlers. Note that
|
||||
/// stream_data.stream_index should be the output stream index.
|
||||
Status Dispatch(std::unique_ptr<StreamData> stream_data);
|
||||
|
||||
/// Dispatch the period info to downstream handlers.
|
||||
Status DispatchPeriodInfo(int stream_index,
|
||||
std::unique_ptr<PeriodInfo> period_info) {
|
||||
std::unique_ptr<StreamData> stream_data(new StreamData);
|
||||
stream_data->stream_index = stream_index;
|
||||
stream_data->period_info = std::move(period_info);
|
||||
return Dispatch(std::move(stream_data));
|
||||
}
|
||||
|
||||
/// Dispatch the stream info to downstream handlers.
|
||||
Status DispatchStreamInfo(int stream_index,
|
||||
std::unique_ptr<StreamInfo> stream_info) {
|
||||
std::unique_ptr<StreamData> stream_data(new StreamData);
|
||||
stream_data->stream_index = stream_index;
|
||||
stream_data->stream_info = std::move(stream_info);
|
||||
return Dispatch(std::move(stream_data));
|
||||
}
|
||||
|
||||
/// Dispatch the encryption config to downstream handlers.
|
||||
Status DispatchEncryptionConfig(
|
||||
int stream_index,
|
||||
std::unique_ptr<EncryptionConfig> encryption_config) {
|
||||
std::unique_ptr<StreamData> stream_data(new StreamData);
|
||||
stream_data->stream_index = stream_index;
|
||||
stream_data->encryption_config = std::move(encryption_config);
|
||||
return Dispatch(std::move(stream_data));
|
||||
}
|
||||
|
||||
/// Dispatch the media sample to downstream handlers.
|
||||
Status DispatchMediaSample(int stream_index,
|
||||
std::unique_ptr<MediaSample> media_sample) {
|
||||
std::unique_ptr<StreamData> stream_data(new StreamData);
|
||||
stream_data->stream_index = stream_index;
|
||||
stream_data->media_sample = std::move(media_sample);
|
||||
return Dispatch(std::move(stream_data));
|
||||
}
|
||||
|
||||
/// Dispatch the media event to downstream handlers.
|
||||
Status DispatchMediaEvent(int stream_index,
|
||||
std::unique_ptr<MediaEvent> media_event) {
|
||||
std::unique_ptr<StreamData> stream_data(new StreamData);
|
||||
stream_data->stream_index = stream_index;
|
||||
stream_data->media_event = std::move(media_event);
|
||||
return Dispatch(std::move(stream_data));
|
||||
}
|
||||
|
||||
/// Dispatch the segment info to downstream handlers.
|
||||
Status DispatchSegmentInfo(int stream_index,
|
||||
std::unique_ptr<SegmentInfo> segment_info) {
|
||||
std::unique_ptr<StreamData> stream_data(new StreamData);
|
||||
stream_data->stream_index = stream_index;
|
||||
stream_data->segment_info = std::move(segment_info);
|
||||
return Dispatch(std::move(stream_data));
|
||||
}
|
||||
|
||||
int num_input_streams() const { return num_input_streams_; }
|
||||
|
||||
private:
|
||||
MediaHandler(const MediaHandler&) = delete;
|
||||
MediaHandler& operator=(const MediaHandler&) = delete;
|
||||
|
||||
// Number of input streams.
|
||||
int num_input_streams_ = 0;
|
||||
// The next available output stream index, used by AddHandler.
|
||||
int next_output_stream_index_ = 0;
|
||||
// output stream index -> {output handler, output handler input stream index}
|
||||
// map.
|
||||
std::map<int, std::pair<std::shared_ptr<MediaHandler>, int>> output_handlers_;
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
} // namespace shaka
|
||||
|
||||
#endif // PACKAGER_MEDIA_BASE_MEDIA_HANDLER_H_
|
|
@ -68,6 +68,10 @@ enum Code {
|
|||
|
||||
// Value was not found.
|
||||
NOT_FOUND,
|
||||
|
||||
// The entity that a client attempted to create (e.g., file or directory)
|
||||
// already exists.
|
||||
ALREADY_EXISTS,
|
||||
};
|
||||
|
||||
} // namespace error
|
||||
|
|
Loading…
Reference in New Issue