• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2019 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 #include "omxUtils.h"
17 
18 sp<IMediaPlayerService> mediaPlayerService = NULL;
19 sp<IOMXNode> mOMXNode = 0;
20 sp<IOMX> mOMX;
21 omx_message msg;
22 Mutex mLock;
23 Condition mMessageAddedCondition;
24 int32_t mLastMsgGeneration;
25 int32_t mCurGeneration;
26 List<omx_message> mMessageQueue;
27 int numCallbackEmptyBufferDone;
28 
29 struct CodecObserver : public BnOMXObserver {
30  public:
CodecObserverCodecObserver31     CodecObserver(int32_t gen)
32             : mGeneration(gen) {
33     }
34 
35     void onMessages(const std::list<omx_message> &messages) override;
36     int32_t mGeneration;
37 
38  protected:
~CodecObserverCodecObserver39     virtual ~CodecObserver() {
40     }
41 };
handleMessages(int32_t gen,const std::list<omx_message> & messages)42 void handleMessages(int32_t gen, const std::list<omx_message> &messages) {
43     Mutex::Autolock autoLock(mLock);
44     for (std::list<omx_message>::const_iterator it = messages.cbegin();
45             it != messages.cend();) {
46         mMessageQueue.push_back(*it);
47         const omx_message &msg = *it++;
48         if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
49             numCallbackEmptyBufferDone++;
50         }
51         mLastMsgGeneration = gen;
52     }
53     mMessageAddedCondition.signal();
54 }
onMessages(const std::list<omx_message> & messages)55 void CodecObserver::onMessages(const std::list<omx_message> &messages) {
56     handleMessages(mGeneration, messages);
57 }
58 
59 struct DeathNotifier : public IBinder::DeathRecipient,
60         public ::android::hardware::hidl_death_recipient {
DeathNotifierDeathNotifier61     explicit DeathNotifier() {
62     }
binderDiedDeathNotifier63     virtual void binderDied(const wp<IBinder> &) {
64         ALOGE("Binder Died");
65         exit (EXIT_FAILURE);
66     }
serviceDiedDeathNotifier67     virtual void serviceDied(
68             uint64_t /* cookie */,
69             const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
70         ALOGE("Service Died");
71         exit (EXIT_FAILURE);
72     }
73 };
74 sp<DeathNotifier> mDeathNotifier;
dequeueMessageForNode(omx_message * msg,int64_t timeoutUs)75 status_t dequeueMessageForNode(omx_message *msg, int64_t timeoutUs) {
76     int64_t finishBy = ALooper::GetNowUs() + timeoutUs;
77     status_t err = OK;
78 
79     while (err != TIMED_OUT) {
80         Mutex::Autolock autoLock(mLock);
81         if (mLastMsgGeneration < mCurGeneration) {
82             mMessageQueue.clear();
83         }
84         // Messages are queued in batches, if the last batch queued is
85         // from a node that already expired, discard those messages.
86         List<omx_message>::iterator it = mMessageQueue.begin();
87         while (it != mMessageQueue.end()) {
88             *msg = *it;
89             mMessageQueue.erase(it);
90             return OK;
91         }
92         if (timeoutUs < 0) {
93             err = mMessageAddedCondition.wait(mLock);
94         } else {
95             err = mMessageAddedCondition.waitRelative(
96                     mLock, (finishBy - ALooper::GetNowUs()) * 1000);
97         }
98     }
99     return err;
100 }
omxUtilsCheckCmdExecution(char * name)101 void omxUtilsCheckCmdExecution(char *name) {
102     status_t err = dequeueMessageForNode(&msg, DEFAULT_TIMEOUT);
103     if (err == TIMED_OUT) {
104         ALOGE("[omxUtils] OMX command timed out for %s, exiting the app", name);
105         exit (EXIT_FAILURE);
106     }
107 }
omxExitOnError(status_t ret)108 void omxExitOnError(status_t ret) {
109     if (ret != OK) {
110         exit (EXIT_FAILURE);
111     }
112 }
omxUtilsInit(char * codecName)113 status_t omxUtilsInit(char *codecName) {
114     android::ProcessState::self()->startThreadPool();
115     OMXClient client;
116     if (client.connect() != OK) {
117         ALOGE("Failed to connect to OMX to create persistent input surface.");
118         return NO_INIT;
119     }
120     mOMX = client.interface();
121     sp<CodecObserver> observer = new CodecObserver(++mCurGeneration);
122     status_t ret = mOMX->allocateNode(codecName, observer, &mOMXNode);
123     if (ret == OK) {
124         mDeathNotifier = new DeathNotifier();
125         auto tOmxNode = mOMXNode->getHalInterface<IOmxNode>();
126         if (tOmxNode != NULL) {
127             tOmxNode->linkToDeath(mDeathNotifier, 0);
128         } else {
129             ALOGE("No HAL Interface");
130             exit (EXIT_FAILURE);
131         }
132     }
133     numCallbackEmptyBufferDone = 0;
134     return ret;
135 }
omxUtilsGetParameter(int portIndex,OMX_PARAM_PORTDEFINITIONTYPE * params)136 status_t omxUtilsGetParameter(int portIndex,
137                               OMX_PARAM_PORTDEFINITIONTYPE *params) {
138     InitOMXParams(params);
139     params->nPortIndex = portIndex;
140     return mOMXNode->getParameter(OMX_IndexParamPortDefinition, params,
141                                   sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
142 }
omxUtilsSetParameter(int portIndex,OMX_PARAM_PORTDEFINITIONTYPE * params)143 status_t omxUtilsSetParameter(int portIndex,
144                               OMX_PARAM_PORTDEFINITIONTYPE *params) {
145     InitOMXParams(params);
146     params->nPortIndex = portIndex;
147     return mOMXNode->setParameter(OMX_IndexParamPortDefinition, params,
148                                   sizeof(OMX_PARAM_PORTDEFINITIONTYPE));
149 }
omxUtilsSetPortMode(OMX_U32 portIndex,IOMX::PortMode mode)150 status_t omxUtilsSetPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
151     return mOMXNode->setPortMode(portIndex, mode);
152 }
omxUtilsUseBuffer(OMX_U32 portIndex,const OMXBuffer & omxBuf,android::IOMX::buffer_id * buffer)153 status_t omxUtilsUseBuffer(OMX_U32 portIndex, const OMXBuffer &omxBuf,
154                            android::IOMX::buffer_id *buffer) {
155     return mOMXNode->useBuffer(portIndex, omxBuf, buffer);
156 }
omxUtilsSendCommand(OMX_COMMANDTYPE cmd,OMX_S32 param)157 status_t omxUtilsSendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) {
158     int ret = mOMXNode->sendCommand(cmd, param);
159     omxUtilsCheckCmdExecution((char *) __FUNCTION__);
160     return ret;
161 }
omxUtilsEmptyBuffer(android::IOMX::buffer_id buffer,const OMXBuffer & omxBuf,OMX_U32 flags,OMX_TICKS timestamp,int fenceFd)162 status_t omxUtilsEmptyBuffer(android::IOMX::buffer_id buffer,
163                              const OMXBuffer &omxBuf, OMX_U32 flags,
164                              OMX_TICKS timestamp, int fenceFd) {
165     return mOMXNode->emptyBuffer(buffer, omxBuf, flags, timestamp, fenceFd);
166 }
omxUtilsFillBuffer(android::IOMX::buffer_id buffer,const OMXBuffer & omxBuf,int fenceFd)167 status_t omxUtilsFillBuffer(android::IOMX::buffer_id buffer,
168                             const OMXBuffer &omxBuf, int fenceFd) {
169     return mOMXNode->fillBuffer(buffer, omxBuf, fenceFd);
170 }
omxUtilsFreeBuffer(OMX_U32 portIndex,android::IOMX::buffer_id buffer)171 status_t omxUtilsFreeBuffer(OMX_U32 portIndex,
172                             android::IOMX::buffer_id buffer) {
173     return mOMXNode->freeBuffer(portIndex, buffer);
174 }
omxUtilsFreeNode()175 status_t omxUtilsFreeNode() {
176     return mOMXNode->freeNode();
177 }
178