|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 //#define LOG_NDEBUG 0 |
|
8 #define LOG_TAG "OMXCodecProxy" |
|
9 |
|
10 #include <binder/IPCThreadState.h> |
|
11 #include <cutils/properties.h> |
|
12 #include <stagefright/foundation/ADebug.h> |
|
13 #include <stagefright/MetaData.h> |
|
14 #include <stagefright/OMXCodec.h> |
|
15 #include <utils/Log.h> |
|
16 |
|
17 #include "nsDebug.h" |
|
18 |
|
19 #include "IMediaResourceManagerService.h" |
|
20 |
|
21 #include "OMXCodecProxy.h" |
|
22 |
|
23 namespace android { |
|
24 |
|
25 // static |
|
26 sp<OMXCodecProxy> OMXCodecProxy::Create( |
|
27 const sp<IOMX> &omx, |
|
28 const sp<MetaData> &meta, bool createEncoder, |
|
29 const sp<MediaSource> &source, |
|
30 const char *matchComponentName, |
|
31 uint32_t flags, |
|
32 const sp<ANativeWindow> &nativeWindow) |
|
33 { |
|
34 sp<OMXCodecProxy> proxy; |
|
35 |
|
36 const char *mime; |
|
37 if (!meta->findCString(kKeyMIMEType, &mime)) { |
|
38 return nullptr; |
|
39 } |
|
40 |
|
41 if (!strncasecmp(mime, "video/", 6)) { |
|
42 proxy = new OMXCodecProxy(omx, meta, createEncoder, source, matchComponentName, flags, nativeWindow); |
|
43 } |
|
44 return proxy; |
|
45 } |
|
46 |
|
47 |
|
48 OMXCodecProxy::OMXCodecProxy( |
|
49 const sp<IOMX> &omx, |
|
50 const sp<MetaData> &meta, |
|
51 bool createEncoder, |
|
52 const sp<MediaSource> &source, |
|
53 const char *matchComponentName, |
|
54 uint32_t flags, |
|
55 const sp<ANativeWindow> &nativeWindow) |
|
56 : mOMX(omx), |
|
57 mSrcMeta(meta), |
|
58 mIsEncoder(createEncoder), |
|
59 mSource(source), |
|
60 mComponentName(nullptr), |
|
61 mFlags(flags), |
|
62 mNativeWindow(nativeWindow), |
|
63 mState(MediaResourceManagerClient::CLIENT_STATE_WAIT_FOR_RESOURCE) |
|
64 { |
|
65 } |
|
66 |
|
67 OMXCodecProxy::~OMXCodecProxy() |
|
68 { |
|
69 mState = MediaResourceManagerClient::CLIENT_STATE_SHUTDOWN; |
|
70 |
|
71 if (mOMXCodec.get()) { |
|
72 wp<MediaSource> tmp = mOMXCodec; |
|
73 mOMXCodec.clear(); |
|
74 while (tmp.promote() != nullptr) { |
|
75 // this value come from stagefrigh's AwesomePlayer. |
|
76 usleep(1000); |
|
77 } |
|
78 } |
|
79 // Complete all pending Binder ipc transactions |
|
80 IPCThreadState::self()->flushCommands(); |
|
81 |
|
82 if (mManagerService.get() && mClient.get()) { |
|
83 mManagerService->cancelClient(mClient); |
|
84 } |
|
85 |
|
86 mSource.clear(); |
|
87 free(mComponentName); |
|
88 mComponentName = nullptr; |
|
89 } |
|
90 |
|
91 MediaResourceManagerClient::State OMXCodecProxy::getState() |
|
92 { |
|
93 Mutex::Autolock autoLock(mLock); |
|
94 return mState; |
|
95 } |
|
96 |
|
97 void OMXCodecProxy::setEventListener(const wp<OMXCodecProxy::EventListener>& listener) |
|
98 { |
|
99 Mutex::Autolock autoLock(mLock); |
|
100 mEventListener = listener; |
|
101 } |
|
102 |
|
103 void OMXCodecProxy::notifyStatusChangedLocked() |
|
104 { |
|
105 if (mEventListener != nullptr) { |
|
106 sp<EventListener> listener = mEventListener.promote(); |
|
107 if (listener != nullptr) { |
|
108 listener->statusChanged(); |
|
109 } |
|
110 } |
|
111 } |
|
112 |
|
113 void OMXCodecProxy::requestResource() |
|
114 { |
|
115 Mutex::Autolock autoLock(mLock); |
|
116 |
|
117 if (mClient.get()) { |
|
118 return; |
|
119 } |
|
120 sp<MediaResourceManagerClient::EventListener> listener = this; |
|
121 mClient = new MediaResourceManagerClient(listener); |
|
122 |
|
123 mManagerService = mClient->getMediaResourceManagerService(); |
|
124 if (!mManagerService.get()) { |
|
125 mClient = nullptr; |
|
126 return; |
|
127 } |
|
128 |
|
129 mManagerService->requestMediaResource(mClient, MediaResourceManagerClient::HW_VIDEO_DECODER); |
|
130 } |
|
131 |
|
132 bool OMXCodecProxy::IsWaitingResources() |
|
133 { |
|
134 Mutex::Autolock autoLock(mLock); |
|
135 return mState == MediaResourceManagerClient::CLIENT_STATE_WAIT_FOR_RESOURCE; |
|
136 } |
|
137 |
|
138 // called on Binder ipc thread |
|
139 void OMXCodecProxy::statusChanged(int event) |
|
140 { |
|
141 Mutex::Autolock autoLock(mLock); |
|
142 |
|
143 if (mState != MediaResourceManagerClient::CLIENT_STATE_WAIT_FOR_RESOURCE) { |
|
144 return; |
|
145 } |
|
146 |
|
147 mState = (MediaResourceManagerClient::State) event; |
|
148 if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { |
|
149 return; |
|
150 } |
|
151 |
|
152 const char *mime; |
|
153 if (!mSrcMeta->findCString(kKeyMIMEType, &mime)) { |
|
154 mState = MediaResourceManagerClient::CLIENT_STATE_SHUTDOWN; |
|
155 notifyStatusChangedLocked(); |
|
156 return; |
|
157 } |
|
158 |
|
159 if (!strncasecmp(mime, "video/", 6)) { |
|
160 sp<MediaSource> codec; |
|
161 mOMXCodec = OMXCodec::Create(mOMX, mSrcMeta, mIsEncoder, mSource, mComponentName, mFlags, mNativeWindow); |
|
162 if (mOMXCodec == nullptr) { |
|
163 mState = MediaResourceManagerClient::CLIENT_STATE_SHUTDOWN; |
|
164 notifyStatusChangedLocked(); |
|
165 return; |
|
166 } |
|
167 // Check if this video is sized such that we're comfortable |
|
168 // possibly using an OMX decoder. |
|
169 int32_t maxWidth, maxHeight; |
|
170 char propValue[PROPERTY_VALUE_MAX]; |
|
171 property_get("ro.moz.omx.hw.max_width", propValue, "-1"); |
|
172 maxWidth = atoi(propValue); |
|
173 property_get("ro.moz.omx.hw.max_height", propValue, "-1"); |
|
174 maxHeight = atoi(propValue); |
|
175 |
|
176 int32_t width = -1, height = -1; |
|
177 if (maxWidth > 0 && maxHeight > 0 && |
|
178 !(mOMXCodec->getFormat()->findInt32(kKeyWidth, &width) && |
|
179 mOMXCodec->getFormat()->findInt32(kKeyHeight, &height) && |
|
180 width * height <= maxWidth * maxHeight)) { |
|
181 printf_stderr("Failed to get video size, or it was too large for HW decoder (<w=%d, h=%d> but <maxW=%d, maxH=%d>)", |
|
182 width, height, maxWidth, maxHeight); |
|
183 mOMXCodec.clear(); |
|
184 mState = MediaResourceManagerClient::CLIENT_STATE_SHUTDOWN; |
|
185 notifyStatusChangedLocked(); |
|
186 return; |
|
187 } |
|
188 |
|
189 if (mOMXCodec->start() != OK) { |
|
190 NS_WARNING("Couldn't start OMX video source"); |
|
191 mOMXCodec.clear(); |
|
192 mState = MediaResourceManagerClient::CLIENT_STATE_SHUTDOWN; |
|
193 notifyStatusChangedLocked(); |
|
194 return; |
|
195 } |
|
196 } |
|
197 notifyStatusChangedLocked(); |
|
198 } |
|
199 |
|
200 status_t OMXCodecProxy::start(MetaData *params) |
|
201 { |
|
202 Mutex::Autolock autoLock(mLock); |
|
203 |
|
204 if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { |
|
205 return NO_INIT; |
|
206 } |
|
207 CHECK(mOMXCodec.get() != nullptr); |
|
208 return mOMXCodec->start(); |
|
209 } |
|
210 |
|
211 status_t OMXCodecProxy::stop() |
|
212 { |
|
213 Mutex::Autolock autoLock(mLock); |
|
214 |
|
215 if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { |
|
216 return NO_INIT; |
|
217 } |
|
218 CHECK(mOMXCodec.get() != nullptr); |
|
219 return mOMXCodec->stop(); |
|
220 } |
|
221 |
|
222 sp<MetaData> OMXCodecProxy::getFormat() |
|
223 { |
|
224 Mutex::Autolock autoLock(mLock); |
|
225 |
|
226 if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { |
|
227 sp<MetaData> meta = new MetaData; |
|
228 return meta; |
|
229 } |
|
230 CHECK(mOMXCodec.get() != nullptr); |
|
231 return mOMXCodec->getFormat(); |
|
232 } |
|
233 |
|
234 status_t OMXCodecProxy::read(MediaBuffer **buffer, const ReadOptions *options) |
|
235 { |
|
236 Mutex::Autolock autoLock(mLock); |
|
237 |
|
238 if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { |
|
239 return NO_INIT; |
|
240 } |
|
241 CHECK(mOMXCodec.get() != nullptr); |
|
242 return mOMXCodec->read(buffer, options); |
|
243 } |
|
244 |
|
245 status_t OMXCodecProxy::pause() |
|
246 { |
|
247 Mutex::Autolock autoLock(mLock); |
|
248 |
|
249 if (mState != MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED) { |
|
250 return NO_INIT; |
|
251 } |
|
252 CHECK(mOMXCodec.get() != nullptr); |
|
253 return mOMXCodec->pause(); |
|
254 } |
|
255 |
|
256 } // namespace android |