[go: nahoru, domu]

blob: f6792fb68a6c9e83339fddd8c6f2724065bdd345 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_MEDIA_CMA_BACKEND_PROXY_PUSH_BUFFER_PENDING_HANDLER_H_
#define CHROMECAST_MEDIA_CMA_BACKEND_PROXY_PUSH_BUFFER_PENDING_HANDLER_H_
#include <memory>
#include <queue>
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "chromecast/media/api/cma_backend.h"
#include "chromecast/media/api/decoder_buffer_base.h"
#include "chromecast/media/cma/backend/proxy/audio_channel_push_buffer_handler.h"
#include "chromecast/media/cma/backend/proxy/buffer_id_manager.h"
namespace chromecast {
class TaskRunner;
namespace media {
// Utility to queue up PushBuffer() and SetConfig() calls to be made
// asynchronously at a later time, when a synchronous call is not possible.
//
// Per the CmaBackend::Decoder::PushBuffer() method signature, an implementing
// class must continue to accept new buffers until returning the kBufferPending
// response, which then acts as a flow control mechanism. In some
// implementations of AudioChannelPushBufferHandler, kBufferPending is not a
// possible response code, so this class acts as a utility to add that
// functionality. Upon a failed PushBuffer call to the delegated instance,
// this class will call back asynchronously, either resulting in a successful
// push or retrying again at a later time.
//
// This class stores:
// - All AudioConfigs set while the underlying AudioChannelPushBufferHandler is
// blocked.
// - A single PushBuffer call associated with the kBufferPending return value.
// Once any data is stored, it queues up a task on the task runner to try to
// call the associated function at a later time.
class PushBufferPendingHandler : public AudioChannelPushBufferHandler {
public:
// |task_runner| and |client| must persist for the lifetime of this instance.
PushBufferPendingHandler(TaskRunner* task_runner,
AudioChannelPushBufferHandler::Client* client);
~PushBufferPendingHandler() override;
// Returns whether or not this instance contains any data waiting to be sent
// at a later point.
bool IsCallPending() const;
// AudioChannelPushBufferHandler overrides.
//
// Note that the pending data is considered only for the PushBuffer() call, as
// it is only understood by the PRODUCER sequence. The CONSUMER sequence is
// not aware of its existence, so the remaining methods will not consider it.
CmaBackend::BufferStatus PushBuffer(
const PushBufferRequest& request) override;
bool HasBufferedData() const override;
absl::optional<PushBufferRequest> GetBufferedData() override;
private:
friend class PushBufferPendingHandlerTest;
PushBufferPendingHandler(
TaskRunner* task_runner,
AudioChannelPushBufferHandler::Client* client,
std::unique_ptr<AudioChannelPushBufferHandler> handler);
// Attempts to push any pending data to |client_|, scheduling another call to
// itself if any further pending data remains.
void TryPushPendingData();
// Schedules a call to TryPushPendingData() in the future.
void ScheduleDataPush();
// The AudioChannelPushBufferHandler to which calls to this instance's methods
// should be delegated.
std::unique_ptr<AudioChannelPushBufferHandler> delegated_handler_;
// Client to use for callbacks.
AudioChannelPushBufferHandler::Client* client_;
// All data which has been pushed to this instance and not yet processed by
// |delegated_handler_|.
std::queue<PushBufferRequest> pushed_data_;
// Signifies whether there is a buffer containing data from a PushBuffer()
// call in the queue (of which there may only be one).
bool has_push_buffer_queued_ = false;
TaskRunner* const task_runner_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<PushBufferPendingHandler> weak_factory_;
};
} // namespace media
} // namespace chromecast
#endif // CHROMECAST_MEDIA_CMA_BACKEND_PROXY_PUSH_BUFFER_PENDING_HANDLER_H_