blob: 9d4736120595be104fd2038fbd46a598b5c54747 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_FUCHSIA_COMMON_STREAM_PROCESSOR_HELPER_H_
#define MEDIA_FUCHSIA_COMMON_STREAM_PROCESSOR_HELPER_H_
#include <fuchsia/media/cpp/fidl.h>
#include <fuchsia/sysmem/cpp/fidl.h>
#include <forward_list>
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "media/base/media_export.h"
namespace media {
// Helper class of fuchsia::media::StreamProcessor. It's responsible for:
// 1. Data validation check.
// 2. Stream/Buffer life time management.
// 3. Configure StreamProcessor and input/output buffer settings.
class MEDIA_EXPORT StreamProcessorHelper {
public:
class MEDIA_EXPORT IoPacket {
public:
IoPacket(size_t index,
size_t offset,
size_t size,
base::TimeDelta timestamp,
bool unit_end,
base::OnceClosure destroy_cb);
IoPacket(const IoPacket&) = delete;
IoPacket& operator=(const IoPacket&) = delete;
~IoPacket();
IoPacket(IoPacket&&);
IoPacket& operator=(IoPacket&&);
size_t buffer_index() const { return index_; }
size_t offset() const { return offset_; }
size_t size() const { return size_; }
base::TimeDelta timestamp() const { return timestamp_; }
bool unit_end() const { return unit_end_; }
void set_format(fuchsia::media::FormatDetails format) {
format_ = std::move(format);
}
const fuchsia::media::FormatDetails& format() const { return format_; }
// Adds a |closure| that will be called when the packet is destroyed.
void AddOnDestroyClosure(base::OnceClosure closure);
private:
size_t index_;
size_t offset_;
size_t size_;
base::TimeDelta timestamp_;
bool unit_end_;
fuchsia::media::FormatDetails format_;
std::forward_list<base::OnceClosure> destroy_callbacks_;
};
class Client {
public:
// Allocate output buffers with the given constraints. Client should call
// ProvideIOutputBufferCollectionToken to finish the buffer allocation flow.
virtual void OnStreamProcessorAllocateOutputBuffers(
const fuchsia::media::StreamBufferConstraints& stream_constraints) = 0;
// Called when all the pushed packets are processed.
virtual void OnStreamProcessorEndOfStream() = 0;
// Called when output format is available.
virtual void OnStreamProcessorOutputFormat(
fuchsia::media::StreamOutputFormat format) = 0;
// Called when output packet is available. Deleting |packet| will notify
// StreamProcessor the output buffer is available to be re-used. Client
// should delete |packet| on the same thread as this function.
virtual void OnStreamProcessorOutputPacket(IoPacket packet) = 0;
// Only available for decryption, which indicates currently the
// StreamProcessor doesn't have the content key to process.
virtual void OnStreamProcessorNoKey() = 0;
// Called when any fatal errors happens.
virtual void OnStreamProcessorError() = 0;
protected:
virtual ~Client() = default;
};
StreamProcessorHelper(fuchsia::media::StreamProcessorPtr processor,
Client* client);
~StreamProcessorHelper();
// Process one packet. Caller can reuse the underlying buffer when the
// |packet| is destroyed.
void Process(IoPacket packet);
// Push End-Of-Stream to StreamProcessor. No more data should be sent to
// StreamProcessor without calling Reset.
void ProcessEos();
// Sets buffer collection tocken to use for input buffers.
void SetInputBufferCollectionToken(
fuchsia::sysmem::BufferCollectionTokenPtr token);
// Provide output BufferCollectionToken to finish StreamProcessor buffer
// setup flow. Should be called only after AllocateOutputBuffers.
void CompleteOutputBuffersAllocation(
fuchsia::sysmem::BufferCollectionTokenPtr token);
// Closes the current stream and starts a new one. After that all packets
// passed to Process() will be sent with a new |stream_lifetime_ordinal|
// value.
void Reset();
private:
// Event handlers for |processor_|.
void OnStreamFailed(uint64_t stream_lifetime_ordinal,
fuchsia::media::StreamError error);
void OnInputConstraints(
fuchsia::media::StreamBufferConstraints input_constraints);
void OnFreeInputPacket(fuchsia::media::PacketHeader free_input_packet);
void OnOutputConstraints(
fuchsia::media::StreamOutputConstraints output_constraints);
void OnOutputFormat(fuchsia::media::StreamOutputFormat output_format);
void OnOutputPacket(fuchsia::media::Packet output_packet,
bool error_detected_before,
bool error_detected_during);
void OnOutputEndOfStream(uint64_t stream_lifetime_ordinal,
bool error_detected_before);
void OnError();
void OnRecycleOutputBuffer(uint64_t buffer_lifetime_ordinal,
uint32_t packet_index);
uint64_t stream_lifetime_ordinal_ = 1;
// Set to true if we've sent an input packet with the current
// stream_lifetime_ordinal_.
bool active_stream_ = false;
// Map from packet index to corresponding input IoPacket. IoPacket should be
// owned by this class until StreamProcessor released the buffer.
base::flat_map<size_t, IoPacket> input_packets_;
// Output buffers.
uint64_t output_buffer_lifetime_ordinal_ = 1;
fuchsia::media::StreamBufferConstraints output_buffer_constraints_;
fuchsia::media::StreamProcessorPtr processor_;
Client* const client_;
// FIDL interfaces are thread-affine (see crbug.com/1012875).
THREAD_CHECKER(thread_checker_);
base::WeakPtr<StreamProcessorHelper> weak_this_;
base::WeakPtrFactory<StreamProcessorHelper> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(StreamProcessorHelper);
};
} // namespace media
#endif // MEDIA_FUCHSIA_COMMON_STREAM_PROCESSOR_HELPER_H_