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