| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "TIHardwareRenderer" |
| #include <utils/Log.h> |
| |
| #include "TIHardwareRenderer.h" |
| |
| #include <media/stagefright/MediaDebug.h> |
| #include <ui/ISurface.h> |
| #include <ui/Overlay.h> |
| |
| #include "v4l2_utils.h" |
| |
| #define CACHEABLE_BUFFERS 0x1 |
| |
| namespace android { |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| TIHardwareRenderer::TIHardwareRenderer( |
| const sp<ISurface> &surface, |
| size_t displayWidth, size_t displayHeight, |
| size_t decodedWidth, size_t decodedHeight) |
| : mISurface(surface), |
| mDisplayWidth(displayWidth), |
| mDisplayHeight(displayHeight), |
| mDecodedWidth(decodedWidth), |
| mDecodedHeight(decodedHeight), |
| mFrameSize(mDecodedWidth * mDecodedHeight * 2), |
| mIsFirstFrame(true), |
| mIndex(0) { |
| CHECK(mISurface.get() != NULL); |
| CHECK(mDecodedWidth > 0); |
| CHECK(mDecodedHeight > 0); |
| |
| sp<OverlayRef> ref = mISurface->createOverlay( |
| mDisplayWidth, mDisplayHeight, OVERLAY_FORMAT_CbYCrY_422_I); |
| |
| if (ref.get() == NULL) { |
| LOGE("Unable to create the overlay!"); |
| return; |
| } |
| |
| mOverlay = new Overlay(ref); |
| mOverlay->setParameter(CACHEABLE_BUFFERS, 0); |
| |
| for (size_t i = 0; i < (size_t)mOverlay->getBufferCount(); ++i) { |
| mapping_data_t *data = |
| (mapping_data_t *)mOverlay->getBufferAddress((void *)i); |
| |
| mOverlayAddresses.push(data->ptr); |
| } |
| } |
| |
| TIHardwareRenderer::~TIHardwareRenderer() { |
| if (mOverlay.get() != NULL) { |
| mOverlay->destroy(); |
| mOverlay.clear(); |
| |
| // XXX apparently destroying an overlay is an asynchronous process... |
| sleep(1); |
| } |
| } |
| |
| void TIHardwareRenderer::render( |
| const void *data, size_t size, void *platformPrivate) { |
| // CHECK_EQ(size, mFrameSize); |
| |
| if (mOverlay.get() == NULL) { |
| return; |
| } |
| |
| #if 0 |
| size_t i = 0; |
| for (; i < mOverlayAddresses.size(); ++i) { |
| if (mOverlayAddresses[i] == data) { |
| break; |
| } |
| |
| if (mIsFirstFrame) { |
| LOGI("overlay buffer #%d: %p", i, mOverlayAddresses[i]); |
| } |
| } |
| |
| if (i == mOverlayAddresses.size()) { |
| LOGE("No suitable overlay buffer found."); |
| return; |
| } |
| |
| mOverlay->queueBuffer((void *)i); |
| |
| overlay_buffer_t overlay_buffer; |
| if (!mIsFirstFrame) { |
| CHECK_EQ(mOverlay->dequeueBuffer(&overlay_buffer), OK); |
| } else { |
| mIsFirstFrame = false; |
| } |
| #else |
| memcpy(mOverlayAddresses[mIndex], data, size); |
| |
| mOverlay->queueBuffer((void *)mIndex); |
| |
| if (++mIndex == mOverlayAddresses.size()) { |
| mIndex = 0; |
| } |
| |
| overlay_buffer_t overlay_buffer; |
| if (!mIsFirstFrame) { |
| CHECK_EQ(mOverlay->dequeueBuffer(&overlay_buffer), OK); |
| } else { |
| mIsFirstFrame = false; |
| } |
| #endif |
| } |
| |
| } // namespace android |
| |