1 /*
2  * Copyright 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "stdio.h"
18 #include <algorithm>
19 #include <sys/types.h>
20 #include "FlowGraphNode.h"
21 
22 using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph;
23 
24 /***************************************************************************/
pullData(int32_t numFrames,int64_t callCount)25 int32_t FlowGraphNode::pullData(int32_t numFrames, int64_t callCount) {
26     int32_t frameCount = numFrames;
27     // Prevent recursion and multiple execution of nodes.
28     if (callCount > mLastCallCount) {
29         mLastCallCount = callCount;
30         if (mDataPulledAutomatically) {
31             // Pull from all the upstream nodes.
32             for (auto &port : mInputPorts) {
33                 // TODO fix bug of leaving unused data in some ports if using multiple AudioSource
34                 frameCount = port.get().pullData(callCount, frameCount);
35             }
36         }
37         if (frameCount > 0) {
38             frameCount = onProcess(frameCount);
39         }
40         mLastFrameCount = frameCount;
41     } else {
42         frameCount = mLastFrameCount;
43     }
44     return frameCount;
45 }
46 
pullReset()47 void FlowGraphNode::pullReset() {
48     if (!mBlockRecursion) {
49         mBlockRecursion = true; // for cyclic graphs
50         // Pull reset from all the upstream nodes.
51         for (auto &port : mInputPorts) {
52             port.get().pullReset();
53         }
54         mBlockRecursion = false;
55         reset();
56     }
57 }
58 
reset()59 void FlowGraphNode::reset() {
60     mLastFrameCount = 0;
61     mLastCallCount = kInitialCallCount;
62 }
63 
64 /***************************************************************************/
FlowGraphPortFloat(FlowGraphNode & parent,int32_t samplesPerFrame,int32_t framesPerBuffer)65 FlowGraphPortFloat::FlowGraphPortFloat(FlowGraphNode &parent,
66                                int32_t samplesPerFrame,
67                                int32_t framesPerBuffer)
68         : FlowGraphPort(parent, samplesPerFrame)
69         , mFramesPerBuffer(framesPerBuffer)
70         , mBuffer(nullptr) {
71     size_t numFloats = static_cast<size_t>(framesPerBuffer * getSamplesPerFrame());
72     mBuffer = std::make_unique<float[]>(numFloats);
73 }
74 
75 /***************************************************************************/
pullData(int64_t callCount,int32_t numFrames)76 int32_t FlowGraphPortFloatOutput::pullData(int64_t callCount, int32_t numFrames) {
77     numFrames = std::min(getFramesPerBuffer(), numFrames);
78     return mContainingNode.pullData(numFrames, callCount);
79 }
80 
pullReset()81 void FlowGraphPortFloatOutput::pullReset() {
82     mContainingNode.pullReset();
83 }
84 
85 // These need to be in the .cpp file because of forward cross references.
connect(FlowGraphPortFloatInput * port)86 void FlowGraphPortFloatOutput::connect(FlowGraphPortFloatInput *port) {
87     port->connect(this);
88 }
89 
disconnect(FlowGraphPortFloatInput * port)90 void FlowGraphPortFloatOutput::disconnect(FlowGraphPortFloatInput *port) {
91     port->disconnect(this);
92 }
93 
94 /***************************************************************************/
pullData(int64_t callCount,int32_t numFrames)95 int32_t FlowGraphPortFloatInput::pullData(int64_t callCount, int32_t numFrames) {
96     return (mConnected == nullptr)
97             ? std::min(getFramesPerBuffer(), numFrames)
98             : mConnected->pullData(callCount, numFrames);
99 }
pullReset()100 void FlowGraphPortFloatInput::pullReset() {
101     if (mConnected != nullptr) mConnected->pullReset();
102 }
103 
getBuffer()104 float *FlowGraphPortFloatInput::getBuffer() {
105     if (mConnected == nullptr) {
106         return FlowGraphPortFloat::getBuffer(); // loaded using setValue()
107     } else {
108         return mConnected->getBuffer();
109     }
110 }
111 
pullData(int32_t numFrames)112 int32_t FlowGraphSink::pullData(int32_t numFrames) {
113     return FlowGraphNode::pullData(numFrames, getLastCallCount() + 1);
114 }
115