1/* 2 * Copyright 2016, 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//#define LOG_NDEBUG 0 18#define LOG_TAG "TWGraphicBufferSource" 19 20#include <media/stagefright/omx/1.0/WGraphicBufferSource.h> 21#include <media/stagefright/omx/1.0/WOmxNode.h> 22#include <media/stagefright/omx/1.0/Conversion.h> 23#include <media/stagefright/omx/OMXUtils.h> 24#include <android/hardware/media/omx/1.0/IOmxBufferSource.h> 25#include <android/hardware/media/omx/1.0/IOmxNode.h> 26#include <media/openmax/OMX_Component.h> 27#include <media/openmax/OMX_IndexExt.h> 28 29namespace android { 30namespace hardware { 31namespace media { 32namespace omx { 33namespace V1_0 { 34namespace implementation { 35 36static const OMX_U32 kPortIndexInput = 0; 37 38struct TWGraphicBufferSource::TWOmxNodeWrapper : public IOmxNodeWrapper { 39 sp<IOmxNode> mOmxNode; 40 41 TWOmxNodeWrapper(const sp<IOmxNode> &omxNode): mOmxNode(omxNode) { 42 } 43 44 virtual status_t emptyBuffer( 45 int32_t bufferId, uint32_t flags, 46 const sp<GraphicBuffer> &buffer, 47 int64_t timestamp, int fenceFd) override { 48 CodecBuffer tBuffer; 49 native_handle_t* fenceNh = native_handle_create_from_fd(fenceFd); 50 status_t err = toStatusT(mOmxNode->emptyBuffer( 51 bufferId, 52 *wrapAs(&tBuffer, buffer), 53 flags, 54 toRawTicks(timestamp), 55 fenceNh)); 56 native_handle_close(fenceNh); 57 native_handle_delete(fenceNh); 58 return err; 59 } 60 61 virtual void dispatchDataSpaceChanged( 62 int32_t dataSpace, int32_t aspects, int32_t pixelFormat) override { 63 Message tMsg; 64 tMsg.type = Message::Type::EVENT; 65 tMsg.fence = native_handle_create(0, 0); 66 tMsg.data.eventData.event = uint32_t(OMX_EventDataSpaceChanged); 67 tMsg.data.eventData.data1 = dataSpace; 68 tMsg.data.eventData.data2 = aspects; 69 tMsg.data.eventData.data3 = pixelFormat; 70 if (!mOmxNode->dispatchMessage(tMsg).isOk()) { 71 ALOGE("TWOmxNodeWrapper failed to dispatch message " 72 "OMX_EventDataSpaceChanged: " 73 "dataSpace = %ld, aspects = %ld, pixelFormat = %ld", 74 static_cast<long>(dataSpace), 75 static_cast<long>(aspects), 76 static_cast<long>(pixelFormat)); 77 } 78 } 79}; 80 81struct TWGraphicBufferSource::TWOmxBufferSource : public IOmxBufferSource { 82 sp<OmxGraphicBufferSource> mSource; 83 84 TWOmxBufferSource(const sp<OmxGraphicBufferSource> &source): mSource(source) { 85 } 86 87 Return<void> onOmxExecuting() override { 88 mSource->onOmxExecuting(); 89 return Void(); 90 } 91 92 Return<void> onOmxIdle() override { 93 mSource->onOmxIdle(); 94 return Void(); 95 } 96 97 Return<void> onOmxLoaded() override { 98 mSource->onOmxLoaded(); 99 return Void(); 100 } 101 102 Return<void> onInputBufferAdded(uint32_t bufferId) override { 103 mSource->onInputBufferAdded(static_cast<int32_t>(bufferId)); 104 return Void(); 105 } 106 107 Return<void> onInputBufferEmptied( 108 uint32_t bufferId, hidl_handle const& tFence) override { 109 mSource->onInputBufferEmptied( 110 static_cast<int32_t>(bufferId), 111 native_handle_read_fd(tFence)); 112 return Void(); 113 } 114}; 115 116// TWGraphicBufferSource 117TWGraphicBufferSource::TWGraphicBufferSource( 118 sp<OmxGraphicBufferSource> const& base) : 119 mBase(base), 120 mOmxBufferSource(new TWOmxBufferSource(base)) { 121} 122 123Return<Status> TWGraphicBufferSource::configure( 124 const sp<IOmxNode>& omxNode, Dataspace dataspace) { 125 if (omxNode == NULL) { 126 return toStatus(BAD_VALUE); 127 } 128 129 // Do setInputSurface() first, the node will try to enable metadata 130 // mode on input, and does necessary error checking. If this fails, 131 // we can't use this input surface on the node. 132 Return<Status> err(omxNode->setInputSurface(mOmxBufferSource)); 133 status_t fnStatus = toStatusT(err); 134 if (fnStatus != NO_ERROR) { 135 ALOGE("Unable to set input surface: %d", fnStatus); 136 return err; 137 } 138 139 // use consumer usage bits queried from encoder, but always add 140 // HW_VIDEO_ENCODER for backward compatibility. 141 uint32_t consumerUsage; 142 void *_params = &consumerUsage; 143 uint8_t *params = static_cast<uint8_t*>(_params); 144 fnStatus = UNKNOWN_ERROR; 145 IOmxNode::getParameter_cb _hidl_cb( 146 [&fnStatus, ¶ms](Status status, hidl_vec<uint8_t> const& outParams) { 147 fnStatus = toStatusT(status); 148 std::copy( 149 outParams.data(), 150 outParams.data() + outParams.size(), 151 params); 152 }); 153 auto transStatus = omxNode->getParameter( 154 static_cast<uint32_t>(OMX_IndexParamConsumerUsageBits), 155 inHidlBytes(&consumerUsage, sizeof(consumerUsage)), 156 _hidl_cb); 157 if (!transStatus.isOk()) { 158 return toStatus(FAILED_TRANSACTION); 159 } 160 if (fnStatus != OK) { 161 consumerUsage = 0; 162 } 163 164 OMX_PARAM_PORTDEFINITIONTYPE def; 165 InitOMXParams(&def); 166 def.nPortIndex = kPortIndexInput; 167 168 _params = &def; 169 params = static_cast<uint8_t*>(_params); 170 transStatus = omxNode->getParameter( 171 static_cast<uint32_t>(OMX_IndexParamPortDefinition), 172 inHidlBytes(&def, sizeof(def)), 173 _hidl_cb); 174 if (!transStatus.isOk()) { 175 return toStatus(FAILED_TRANSACTION); 176 } 177 if (fnStatus != NO_ERROR) { 178 ALOGE("Failed to get port definition: %d", fnStatus); 179 return toStatus(fnStatus); 180 } 181 182 183 return toStatus(mBase->configure( 184 new TWOmxNodeWrapper(omxNode), 185 toRawDataspace(dataspace), 186 def.nBufferCountActual, 187 def.format.video.nFrameWidth, 188 def.format.video.nFrameHeight, 189 consumerUsage)); 190} 191 192Return<Status> TWGraphicBufferSource::setSuspend( 193 bool suspend, int64_t timeUs) { 194 return toStatus(mBase->setSuspend(suspend, timeUs)); 195} 196 197Return<Status> TWGraphicBufferSource::setRepeatPreviousFrameDelayUs( 198 int64_t repeatAfterUs) { 199 return toStatus(mBase->setRepeatPreviousFrameDelayUs(repeatAfterUs)); 200} 201 202Return<Status> TWGraphicBufferSource::setMaxFps(float maxFps) { 203 return toStatus(mBase->setMaxFps(maxFps)); 204} 205 206Return<Status> TWGraphicBufferSource::setTimeLapseConfig( 207 double fps, double captureFps) { 208 return toStatus(mBase->setTimeLapseConfig(fps, captureFps)); 209} 210 211Return<Status> TWGraphicBufferSource::setStartTimeUs(int64_t startTimeUs) { 212 return toStatus(mBase->setStartTimeUs(startTimeUs)); 213} 214 215Return<Status> TWGraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) { 216 return toStatus(mBase->setStopTimeUs(stopTimeUs)); 217} 218 219Return<void> TWGraphicBufferSource::getStopTimeOffsetUs( 220 getStopTimeOffsetUs_cb _hidl_cb) { 221 status_t status; 222 int64_t stopTimeOffsetUs; 223 status = mBase->getStopTimeOffsetUs(&stopTimeOffsetUs); 224 _hidl_cb(toStatus(status), stopTimeOffsetUs); 225 return Void(); 226} 227 228Return<Status> TWGraphicBufferSource::setColorAspects( 229 const ColorAspects& aspects) { 230 return toStatus(mBase->setColorAspects(toCompactColorAspects(aspects))); 231} 232 233Return<Status> TWGraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) { 234 return toStatus(mBase->setTimeOffsetUs(timeOffsetUs)); 235} 236 237Return<Status> TWGraphicBufferSource::signalEndOfInputStream() { 238 return toStatus(mBase->signalEndOfInputStream()); 239} 240 241} // namespace implementation 242} // namespace V1_0 243} // namespace omx 244} // namespace media 245} // namespace hardware 246} // namespace android 247