Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Unified Diff: media/base/state_machine_example.cc

Issue 2568663002: [WIP] - trying out some state machine ideas.
Patch Set: added SimpleStateMachine, updated example Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/base/state_machine_driver.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/state_machine_example.cc
diff --git a/media/base/state_machine_example.cc b/media/base/state_machine_example.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1addce03b13dc6fccfebaa2824abf1b01e31778d
--- /dev/null
+++ b/media/base/state_machine_example.cc
@@ -0,0 +1,136 @@
+// Copyright 2016 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.
+
+#include "media/base/simple_state_machine.h"
+#include "media/base/state.h"
+#include "media/base/state_machine_driver.h"
+
+namespace media {
+
+class MediaCodec {};
+class DecoderBuffer {};
+
+///////////////////// States
+
+class CodecState : public State {
+ public:
+ MediaCodec* GetCodec() const { return media_codec_.get(); };
+ void SetCodec(std::unique_ptr<MediaCodec> media_codec) {
+ media_codec_ = std::move(media_codec);
+ StateChanged();
+ }
+
+ // might have a state variable like okay, error, waiting_for_key. might
+ // also have a flag like 'stop queueing at keyframe', or 'flush', etc.
+ // there might be other things here that QueueInputMachine doesn't care about.
+
+ private:
+ ~CodecState() override {}
+ std::unique_ptr<MediaCodec> media_codec_;
+};
+
+class InputBufferState : public State {
+ public:
+ // causes state to be updated.
+ void QueueBuffer(DecoderBuffer);
+
+ // TODO: does this notify that state has changed? It could, but it's
+ // unclear that we want to. it would force the decoding machine to run
+ // until it can dequeue no more, which might or might not be what we want.
+ // seems like we'd rather have that controlled in some other way.
+ DecoderBuffer DequeueBuffer();
+
+ bool IsQueueEmpty() const;
+
+ private:
+ ~InputBufferState() override {}
+};
+
+class SurfaceState : public State {
+ private:
+ ~SurfaceState() override {}
+};
+
+class CdmState : public State {
+ private:
+ ~CdmState() override {}
+};
+
+///////////////////// State machines
+
+// Tries to queue pending input from Decode calls. Cares that we have a codec,
+// that we're not flushing, and (maybe) checks for things like 'queue until
+// next key frame'.
+// Note that we could derive from StateMachine directly, but this saves some
+// boiler plate.
+using QueueInputMachineBase = SimpleStateMachine<InputBufferState, CodecState>;
+class QueueInputMachine : public QueueInputMachineBase {
+ public:
+ QueueInputMachine(scoped_refptr<InputBufferState>, scoped_refptr<CodecState>);
+
+ void Run() const override;
+};
+
+// CodecGetterMachine might want CodecState, SurfaceState, and CdmState.
+
+// QueueInputMachineBase handles registering the machine with the state as a
+// client, and providing getters for the state objects.
+QueueInputMachine::QueueInputMachine(
+ scoped_refptr<InputBufferState> input_buffer_state,
+ scoped_refptr<CodecState> codec_state)
+ : QueueInputMachineBase(input_buffer_state, codec_state) {}
+
+void QueueInputMachine::Run() const {
+ if (Get<InputBufferState>()->IsQueueEmpty())
+ return;
+
+ MediaCodec* codec = Get<CodecState>()->GetCodec();
+ if (!codec)
+ return;
+
+ // Check for other things, like if we're allowed to queue input.
+
+ // Pretty much do what QueueInput does.
+ // if this is an eos, we'd update the codec state to indicate that a flush
+ // is in progress.
+}
+
+using CodecGetterMachineBase =
+ SimpleStateMachine<CodecState, SurfaceState, CdmState>;
+class CodecGetterMachine : public CodecGetterMachineBase {
+ public:
+ CodecGetterMachine(scoped_refptr<CodecState> codec_state,
+ scoped_refptr<SurfaceState> surface_state,
+ scoped_refptr<CdmState> cdm_state)
+ : CodecGetterMachineBase(codec_state, surface_state, cdm_state) {}
+
+ void Run() const override {}
+};
+
+///////////////////// Setup code.
+
+void RunSomeExample() {
+ scoped_refptr<InputBufferState> input_buffer_state(new InputBufferState);
+ scoped_refptr<CodecState> codec_state(new CodecState);
+ scoped_refptr<SurfaceState> surface_state(new SurfaceState);
+ scoped_refptr<CdmState> cdm_state(new CdmState);
+
+ std::unique_ptr<QueueInputMachine> queue_input_machine(
+ new QueueInputMachine(input_buffer_state, codec_state));
+ std::unique_ptr<CodecGetterMachine> codec_getter_machine(
+ new CodecGetterMachine(codec_state, surface_state, cdm_state));
+
+ std::unique_ptr<StateMachineDriver> driver(new StateMachineDriver);
+ driver->AddStateMachine(std::move(queue_input_machine));
+ driver->AddStateMachine(std::move(codec_getter_machine));
+ // Note that we no longer have ptrs to the machines; |driver| has them.
+ // That's a little inconvenient if we want to refer to them, such as for
+ // giving a raw ptr to a timer, for it to call RunImmediately.
+ // Perhaps AddStateMachine could return a weak ref or raw ptr?
+
+ // This will cause the driver to post a task to run the state machine.
+ input_buffer_state->QueueBuffer(DecoderBuffer());
+}
+
+} // namespace media
« no previous file with comments | « media/base/state_machine_driver.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698