1/* 2 * Copyright (C) 2010 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 "VideoSourceDownSampler" 19 20#include <media/stagefright/VideoSourceDownSampler.h> 21#include <media/stagefright/MediaBuffer.h> 22#include <media/stagefright/MediaDebug.h> 23#include <media/stagefright/MetaData.h> 24#include <media/stagefright/YUVImage.h> 25#include <media/stagefright/YUVCanvas.h> 26#include "OMX_Video.h" 27 28namespace android { 29 30VideoSourceDownSampler::VideoSourceDownSampler(const sp<MediaSource> &videoSource, 31 int32_t width, int32_t height) { 32 LOGV("Construct VideoSourceDownSampler"); 33 CHECK(width > 0); 34 CHECK(height > 0); 35 36 mRealVideoSource = videoSource; 37 mWidth = width; 38 mHeight = height; 39 40 mMeta = new MetaData(*(mRealVideoSource->getFormat())); 41 CHECK(mMeta->findInt32(kKeyWidth, &mRealSourceWidth)); 42 CHECK(mMeta->findInt32(kKeyHeight, &mRealSourceHeight)); 43 44 if ((mWidth != mRealSourceWidth) || (mHeight != mRealSourceHeight)) { 45 // Change meta data for width and height. 46 CHECK(mWidth <= mRealSourceWidth); 47 CHECK(mHeight <= mRealSourceHeight); 48 49 mNeedDownSampling = true; 50 computeDownSamplingParameters(); 51 mMeta->setInt32(kKeyWidth, mWidth); 52 mMeta->setInt32(kKeyHeight, mHeight); 53 } else { 54 mNeedDownSampling = false; 55 } 56} 57 58VideoSourceDownSampler::~VideoSourceDownSampler() { 59} 60 61void VideoSourceDownSampler::computeDownSamplingParameters() { 62 mDownSampleSkipX = mRealSourceWidth / mWidth; 63 mDownSampleSkipY = mRealSourceHeight / mHeight; 64 65 mDownSampleOffsetX = mRealSourceWidth - mDownSampleSkipX * mWidth; 66 mDownSampleOffsetY = mRealSourceHeight - mDownSampleSkipY * mHeight; 67} 68 69void VideoSourceDownSampler::downSampleYUVImage( 70 const MediaBuffer &sourceBuffer, MediaBuffer **buffer) const { 71 // find the YUV format 72 int32_t srcFormat; 73 CHECK(mMeta->findInt32(kKeyColorFormat, &srcFormat)); 74 YUVImage::YUVFormat yuvFormat; 75 if (srcFormat == OMX_COLOR_FormatYUV420SemiPlanar) { 76 yuvFormat = YUVImage::YUV420SemiPlanar; 77 } else if (srcFormat == OMX_COLOR_FormatYUV420Planar) { 78 yuvFormat = YUVImage::YUV420Planar; 79 } 80 81 // allocate mediaBuffer for down sampled image and setup a canvas. 82 *buffer = new MediaBuffer(YUVImage::bufferSize(yuvFormat, mWidth, mHeight)); 83 YUVImage yuvDownSampledImage(yuvFormat, 84 mWidth, mHeight, 85 (uint8_t *)(*buffer)->data()); 86 YUVCanvas yuvCanvasDownSample(yuvDownSampledImage); 87 88 YUVImage yuvImageSource(yuvFormat, 89 mRealSourceWidth, mRealSourceHeight, 90 (uint8_t *)sourceBuffer.data()); 91 yuvCanvasDownSample.downsample(mDownSampleOffsetX, mDownSampleOffsetY, 92 mDownSampleSkipX, mDownSampleSkipY, 93 yuvImageSource); 94} 95 96status_t VideoSourceDownSampler::start(MetaData *params) { 97 LOGV("start"); 98 return mRealVideoSource->start(); 99} 100 101status_t VideoSourceDownSampler::stop() { 102 LOGV("stop"); 103 return mRealVideoSource->stop(); 104} 105 106sp<MetaData> VideoSourceDownSampler::getFormat() { 107 LOGV("getFormat"); 108 return mMeta; 109} 110 111status_t VideoSourceDownSampler::read( 112 MediaBuffer **buffer, const ReadOptions *options) { 113 LOGV("read"); 114 MediaBuffer *realBuffer; 115 status_t err = mRealVideoSource->read(&realBuffer, options); 116 117 if (mNeedDownSampling) { 118 downSampleYUVImage(*realBuffer, buffer); 119 120 int64_t frameTime; 121 realBuffer->meta_data()->findInt64(kKeyTime, &frameTime); 122 (*buffer)->meta_data()->setInt64(kKeyTime, frameTime); 123 124 // We just want this buffer to be deleted when the encoder releases it. 125 // So don't add a reference to it and set the observer to NULL. 126 (*buffer)->setObserver(NULL); 127 128 // The original buffer is no longer required. Release it. 129 realBuffer->release(); 130 } else { 131 *buffer = realBuffer; 132 } 133 134 return err; 135} 136 137status_t VideoSourceDownSampler::pause() { 138 LOGV("pause"); 139 return mRealVideoSource->pause(); 140} 141 142} // namespace android 143