OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "media/base/simple_state_machine.h" |
| 6 #include "media/base/state.h" |
| 7 #include "media/base/state_machine_driver.h" |
| 8 |
| 9 namespace media { |
| 10 |
| 11 class MediaCodec {}; |
| 12 class DecoderBuffer {}; |
| 13 |
| 14 ///////////////////// States |
| 15 |
| 16 class CodecState : public State { |
| 17 public: |
| 18 MediaCodec* GetCodec() const { return media_codec_.get(); }; |
| 19 void SetCodec(std::unique_ptr<MediaCodec> media_codec) { |
| 20 media_codec_ = std::move(media_codec); |
| 21 StateChanged(); |
| 22 } |
| 23 |
| 24 // might have a state variable like okay, error, waiting_for_key. might |
| 25 // also have a flag like 'stop queueing at keyframe', or 'flush', etc. |
| 26 // there might be other things here that QueueInputMachine doesn't care about. |
| 27 |
| 28 private: |
| 29 ~CodecState() override {} |
| 30 std::unique_ptr<MediaCodec> media_codec_; |
| 31 }; |
| 32 |
| 33 class InputBufferState : public State { |
| 34 public: |
| 35 // causes state to be updated. |
| 36 void QueueBuffer(DecoderBuffer); |
| 37 |
| 38 // TODO: does this notify that state has changed? It could, but it's |
| 39 // unclear that we want to. it would force the decoding machine to run |
| 40 // until it can dequeue no more, which might or might not be what we want. |
| 41 // seems like we'd rather have that controlled in some other way. |
| 42 DecoderBuffer DequeueBuffer(); |
| 43 |
| 44 bool IsQueueEmpty() const; |
| 45 |
| 46 private: |
| 47 ~InputBufferState() override {} |
| 48 }; |
| 49 |
| 50 class SurfaceState : public State { |
| 51 private: |
| 52 ~SurfaceState() override {} |
| 53 }; |
| 54 |
| 55 class CdmState : public State { |
| 56 private: |
| 57 ~CdmState() override {} |
| 58 }; |
| 59 |
| 60 ///////////////////// State machines |
| 61 |
| 62 // Tries to queue pending input from Decode calls. Cares that we have a codec, |
| 63 // that we're not flushing, and (maybe) checks for things like 'queue until |
| 64 // next key frame'. |
| 65 // Note that we could derive from StateMachine directly, but this saves some |
| 66 // boiler plate. |
| 67 using QueueInputMachineBase = SimpleStateMachine<InputBufferState, CodecState>; |
| 68 class QueueInputMachine : public QueueInputMachineBase { |
| 69 public: |
| 70 QueueInputMachine(scoped_refptr<InputBufferState>, scoped_refptr<CodecState>); |
| 71 |
| 72 void Run() const override; |
| 73 }; |
| 74 |
| 75 // CodecGetterMachine might want CodecState, SurfaceState, and CdmState. |
| 76 |
| 77 // QueueInputMachineBase handles registering the machine with the state as a |
| 78 // client, and providing getters for the state objects. |
| 79 QueueInputMachine::QueueInputMachine( |
| 80 scoped_refptr<InputBufferState> input_buffer_state, |
| 81 scoped_refptr<CodecState> codec_state) |
| 82 : QueueInputMachineBase(input_buffer_state, codec_state) {} |
| 83 |
| 84 void QueueInputMachine::Run() const { |
| 85 if (Get<InputBufferState>()->IsQueueEmpty()) |
| 86 return; |
| 87 |
| 88 MediaCodec* codec = Get<CodecState>()->GetCodec(); |
| 89 if (!codec) |
| 90 return; |
| 91 |
| 92 // Check for other things, like if we're allowed to queue input. |
| 93 |
| 94 // Pretty much do what QueueInput does. |
| 95 // if this is an eos, we'd update the codec state to indicate that a flush |
| 96 // is in progress. |
| 97 } |
| 98 |
| 99 using CodecGetterMachineBase = |
| 100 SimpleStateMachine<CodecState, SurfaceState, CdmState>; |
| 101 class CodecGetterMachine : public CodecGetterMachineBase { |
| 102 public: |
| 103 CodecGetterMachine(scoped_refptr<CodecState> codec_state, |
| 104 scoped_refptr<SurfaceState> surface_state, |
| 105 scoped_refptr<CdmState> cdm_state) |
| 106 : CodecGetterMachineBase(codec_state, surface_state, cdm_state) {} |
| 107 |
| 108 void Run() const override {} |
| 109 }; |
| 110 |
| 111 ///////////////////// Setup code. |
| 112 |
| 113 void RunSomeExample() { |
| 114 scoped_refptr<InputBufferState> input_buffer_state(new InputBufferState); |
| 115 scoped_refptr<CodecState> codec_state(new CodecState); |
| 116 scoped_refptr<SurfaceState> surface_state(new SurfaceState); |
| 117 scoped_refptr<CdmState> cdm_state(new CdmState); |
| 118 |
| 119 std::unique_ptr<QueueInputMachine> queue_input_machine( |
| 120 new QueueInputMachine(input_buffer_state, codec_state)); |
| 121 std::unique_ptr<CodecGetterMachine> codec_getter_machine( |
| 122 new CodecGetterMachine(codec_state, surface_state, cdm_state)); |
| 123 |
| 124 std::unique_ptr<StateMachineDriver> driver(new StateMachineDriver); |
| 125 driver->AddStateMachine(std::move(queue_input_machine)); |
| 126 driver->AddStateMachine(std::move(codec_getter_machine)); |
| 127 // Note that we no longer have ptrs to the machines; |driver| has them. |
| 128 // That's a little inconvenient if we want to refer to them, such as for |
| 129 // giving a raw ptr to a timer, for it to call RunImmediately. |
| 130 // Perhaps AddStateMachine could return a weak ref or raw ptr? |
| 131 |
| 132 // This will cause the driver to post a task to run the state machine. |
| 133 input_buffer_state->QueueBuffer(DecoderBuffer()); |
| 134 } |
| 135 |
| 136 } // namespace media |
OLD | NEW |