14b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen/* 24b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * Copyright (C) 2009 The Android Open Source Project 34b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * 44b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License"); 54b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * you may not use this file except in compliance with the License. 64b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * You may obtain a copy of the License at 74b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * 84b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * http://www.apache.org/licenses/LICENSE-2.0 94b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * 104b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * Unless required by applicable law or agreed to in writing, software 114b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS, 124b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * See the License for the specific language governing permissions and 144b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen * limitations under the License. 154b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen */ 164b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 174b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#define LOG_TAG "OmxJpegDecoder" 184b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <sys/time.h> 194b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <utils/Log.h> 204b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 214b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <stdlib.h> 224b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <string.h> 234b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <unistd.h> 244b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 254b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <binder/IServiceManager.h> 264b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <binder/ProcessState.h> 274b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <media/IMediaPlayerService.h> 284b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <media/stagefright/MediaDebug.h> 294b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <media/stagefright/MediaSource.h> 304b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <media/stagefright/MetaData.h> 314b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <media/stagefright/OMXClient.h> 324b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <media/stagefright/OMXCodec.h> 334b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include <SkMallocPixelRef.h> 344b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 354b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include "omx_jpeg_decoder.h" 364b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include "SkOmxPixelRef.h" 374b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen#include "StreamSource.h" 384b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 394b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chenusing namespace android; 404b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 41987dbde838014e5f0c55a63acdd2a9a002b140ccAndreas Huberstatic void getJpegOutput(MediaBuffer* buffer, const char* filename) { 424b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int size = buffer->range_length(); 434b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int offset = buffer->range_offset(); 444b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen FILE *pFile = fopen(filename, "w+"); 454b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 464b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen if (pFile == NULL) { 474b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen printf("Error: cannot open %s.\n", filename); 484b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen } else { 494b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen char* data = (char*) buffer->data(); 504b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen data += offset; 514b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen while (size > 0) { 524b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int numChars = fwrite(data, sizeof(char), 1024, pFile); 534b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int numBytes = numChars * sizeof(char); 544b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen size -= numBytes; 554b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen data += numBytes; 564b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen } 574b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen fclose(pFile); 584b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen } 594b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return; 604b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 614b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 62987dbde838014e5f0c55a63acdd2a9a002b140ccAndreas Huberextern int storeBitmapToFile(SkBitmap* bitmap, const char* filename) { 634b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen bitmap->lockPixels(); 64987dbde838014e5f0c55a63acdd2a9a002b140ccAndreas Huber uint8_t* data = (uint8_t *)bitmap->getPixels(); 654b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int size = bitmap->getSize(); 664b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen FILE* fp = fopen(filename, "w+"); 674b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 684b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen if (NULL == fp) { 694b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen printf("Cannot open the output file! \n"); 704b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return -1; 714b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen } else { 724b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen while (size > 0) { 734b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int numChars = fwrite(data, sizeof(char), 1024, fp); 744b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int numBytes = numChars * sizeof(char); 754b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen size -= numBytes; 764b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen data += numBytes; 774b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen } 784b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen fclose(fp); 794b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen } 804b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return 0; 814b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 824b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 834b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chenstatic int64_t getNowUs() { 844b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen struct timeval tv; 854b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen gettimeofday(&tv, NULL); 864b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 874b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return (int64_t)tv.tv_usec + tv.tv_sec * 1000000; 884b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 894b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 904b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta ChenOmxJpegImageDecoder::OmxJpegImageDecoder() { 914b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen status_t err = mClient.connect(); 924b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen CHECK_EQ(err, OK); 934b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 944b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 954b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta ChenOmxJpegImageDecoder::~OmxJpegImageDecoder() { 964b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen mClient.disconnect(); 974b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 984b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 994b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chenbool OmxJpegImageDecoder::onDecode(SkStream* stream, 100945a9df6e31cf951d6f323a85a7e75c19c7f60f6Mike Reed SkBitmap* bm, Mode mode) { 1014b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen sp<MediaSource> source = prepareMediaSource(stream); 1024b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen sp<MetaData> meta = source->getFormat(); 1034b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int width; 1044b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int height; 1054b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen meta->findInt32(kKeyWidth, &width); 1064b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen meta->findInt32(kKeyHeight, &height); 107945a9df6e31cf951d6f323a85a7e75c19c7f60f6Mike Reed configBitmapSize(bm, getPrefConfig(k32Bit_SrcDepth, false), width, height); 1084b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1094b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen // mode == DecodeBounds 1104b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen if (mode == SkImageDecoder::kDecodeBounds_Mode) { 1114b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return true; 1124b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen } 1134b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1144b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen // mode == DecodePixels 1154b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen if (!this->allocPixelRef(bm, NULL)) { 116987dbde838014e5f0c55a63acdd2a9a002b140ccAndreas Huber LOGI("Cannot allocPixelRef()!"); 1174b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return false; 1184b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen } 1194b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 120987dbde838014e5f0c55a63acdd2a9a002b140ccAndreas Huber sp<MediaSource> decoder = getDecoder(&mClient, source); 1214b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return decodeSource(decoder, source, bm); 1224b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 1234b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1244b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta ChenJPEGSource* OmxJpegImageDecoder::prepareMediaSource(SkStream* stream) { 1254b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen DataSource::RegisterDefaultSniffers(); 1264b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen sp<DataSource> dataSource = new StreamSource(stream); 1274b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return new JPEGSource(dataSource); 1284b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 1294b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 130987dbde838014e5f0c55a63acdd2a9a002b140ccAndreas Hubersp<MediaSource> OmxJpegImageDecoder::getDecoder( 1314b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen OMXClient *client, const sp<MediaSource>& source) { 1324b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen sp<MetaData> meta = source->getFormat(); 133987dbde838014e5f0c55a63acdd2a9a002b140ccAndreas Huber sp<MediaSource> decoder = OMXCodec::Create( 1344b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen client->interface(), meta, false /* createEncoder */, source); 1354b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1364b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen CHECK(decoder != NULL); 1374b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return decoder; 1384b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 1394b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 140987dbde838014e5f0c55a63acdd2a9a002b140ccAndreas Huberbool OmxJpegImageDecoder::decodeSource(sp<MediaSource> decoder, 1414b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen const sp<MediaSource>& source, SkBitmap* bm) { 1424b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen status_t rt = decoder->start(); 1434b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen if (rt != OK) { 144987dbde838014e5f0c55a63acdd2a9a002b140ccAndreas Huber LOGE("Cannot start OMX Decoder!"); 1454b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return false; 1464b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen } 1474b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int64_t startTime = getNowUs(); 1484b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen MediaBuffer *buffer; 1494b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1504b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen // decode source 1514b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen status_t err = decoder->read(&buffer, NULL); 1524b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int64_t duration = getNowUs() - startTime; 1534b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1544b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen if (err != OK) { 1554b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen CHECK_EQ(buffer, NULL); 1564b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen } 1574b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen printf("Duration in decoder->read(): %.1f (msecs). \n", 1584b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen duration / 1E3 ); 1594b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1604b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen /* Mark the code for now, since we attend to copy buffer to SkBitmap. 1614b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen // Install pixelRef to Bitmap. 1624b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen installPixelRef(buffer, decoder, bm);*/ 1634b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1644b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen // Copy pixels from buffer to bm. 1654b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen // May need to check buffer->rawBytes() == bm->rawBytes(). 1664b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen CHECK_EQ(buffer->size(), bm->getSize()); 1674b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen memcpy(bm->getPixels(), buffer->data(), buffer->size()); 1684b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen buffer->release(); 1694b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen decoder->stop(); 1704b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1714b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return true; 1724b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 1734b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 174987dbde838014e5f0c55a63acdd2a9a002b140ccAndreas Hubervoid OmxJpegImageDecoder::installPixelRef(MediaBuffer *buffer, sp<MediaSource> decoder, 1754b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen SkBitmap* bm) { 1764b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1774b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen // set bm's pixelref based on the data in buffer. 1784b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen SkAutoLockPixels alp(*bm); 1794b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen SkPixelRef* pr = new SkOmxPixelRef(NULL, buffer, decoder); 1804b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen bm->setPixelRef(pr)->unref(); 1814b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen bm->lockPixels(); 1824b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return; 1834b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 1844b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1854b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chenvoid OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkBitmap::Config pref, 1864b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen int width, int height) { 1874b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen bm->setConfig(getColorSpaceConfig(pref), width, height); 1884b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen bm->setIsOpaque(true); 1894b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 1904b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1914b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta ChenSkBitmap::Config OmxJpegImageDecoder::getColorSpaceConfig( 1924b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen SkBitmap::Config pref) { 1934b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen 1944b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen // Set the color space to ARGB_8888 for now 1954b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen // because of limitation in hardware support. 1964b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen return SkBitmap::kARGB_8888_Config; 1974b6f4942fcef3300b407d9a07a680c07b162333fWei-Ta Chen} 198