/* * 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 "OmxJpegDecoder" #include <sys/time.h> #include <utils/Log.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <binder/IServiceManager.h> #include <binder/ProcessState.h> #include <media/IMediaPlayerService.h> #include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaSource.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/OMXClient.h> #include <media/stagefright/OMXCodec.h> #include <SkMallocPixelRef.h> #include "omx_jpeg_decoder.h" #include "SkOmxPixelRef.h" #include "StreamSource.h" using namespace android; static void getJpegOutput(MediaBuffer* buffer, const char* filename) { int size = buffer->range_length(); int offset = buffer->range_offset(); FILE *pFile = fopen(filename, "w+"); if (pFile == NULL) { printf("Error: cannot open %s.\n", filename); } else { char* data = (char*) buffer->data(); data += offset; while (size > 0) { int numChars = fwrite(data, sizeof(char), 1024, pFile); int numBytes = numChars * sizeof(char); size -= numBytes; data += numBytes; } fclose(pFile); } return; } extern int storeBitmapToFile(SkBitmap* bitmap, const char* filename) { bitmap->lockPixels(); uint8_t* data = (uint8_t *)bitmap->getPixels(); int size = bitmap->getSize(); FILE* fp = fopen(filename, "w+"); if (NULL == fp) { printf("Cannot open the output file! \n"); return -1; } else { while (size > 0) { int numChars = fwrite(data, sizeof(char), 1024, fp); int numBytes = numChars * sizeof(char); size -= numBytes; data += numBytes; } fclose(fp); } return 0; } static int64_t getNowUs() { struct timeval tv; gettimeofday(&tv, NULL); return (int64_t)tv.tv_usec + tv.tv_sec * 1000000; } OmxJpegImageDecoder::OmxJpegImageDecoder() { status_t err = mClient.connect(); CHECK_EQ(err, OK); } OmxJpegImageDecoder::~OmxJpegImageDecoder() { mClient.disconnect(); } bool OmxJpegImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) { sp<MediaSource> source = prepareMediaSource(stream); sp<MetaData> meta = source->getFormat(); int width; int height; meta->findInt32(kKeyWidth, &width); meta->findInt32(kKeyHeight, &height); configBitmapSize(bm, getPrefConfig(k32Bit_SrcDepth, false), width, height); // mode == DecodeBounds if (mode == SkImageDecoder::kDecodeBounds_Mode) { return true; } // mode == DecodePixels if (!this->allocPixelRef(bm, NULL)) { LOGI("Cannot allocPixelRef()!"); return false; } sp<MediaSource> decoder = getDecoder(&mClient, source); return decodeSource(decoder, source, bm); } JPEGSource* OmxJpegImageDecoder::prepareMediaSource(SkStream* stream) { DataSource::RegisterDefaultSniffers(); sp<DataSource> dataSource = new StreamSource(stream); return new JPEGSource(dataSource); } sp<MediaSource> OmxJpegImageDecoder::getDecoder( OMXClient *client, const sp<MediaSource>& source) { sp<MetaData> meta = source->getFormat(); sp<MediaSource> decoder = OMXCodec::Create( client->interface(), meta, false /* createEncoder */, source); CHECK(decoder != NULL); return decoder; } bool OmxJpegImageDecoder::decodeSource(sp<MediaSource> decoder, const sp<MediaSource>& source, SkBitmap* bm) { status_t rt = decoder->start(); if (rt != OK) { LOGE("Cannot start OMX Decoder!"); return false; } int64_t startTime = getNowUs(); MediaBuffer *buffer; // decode source status_t err = decoder->read(&buffer, NULL); int64_t duration = getNowUs() - startTime; if (err != OK) { CHECK_EQ(buffer, NULL); } printf("Duration in decoder->read(): %.1f (msecs). \n", duration / 1E3 ); /* Mark the code for now, since we attend to copy buffer to SkBitmap. // Install pixelRef to Bitmap. installPixelRef(buffer, decoder, bm);*/ // Copy pixels from buffer to bm. // May need to check buffer->rawBytes() == bm->rawBytes(). CHECK_EQ(buffer->size(), bm->getSize()); memcpy(bm->getPixels(), buffer->data(), buffer->size()); buffer->release(); decoder->stop(); return true; } void OmxJpegImageDecoder::installPixelRef(MediaBuffer *buffer, sp<MediaSource> decoder, SkBitmap* bm) { // set bm's pixelref based on the data in buffer. SkAutoLockPixels alp(*bm); SkPixelRef* pr = new SkOmxPixelRef(NULL, buffer, decoder); bm->setPixelRef(pr)->unref(); bm->lockPixels(); return; } void OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkBitmap::Config pref, int width, int height) { bm->setConfig(getColorSpaceConfig(pref), width, height); bm->setIsOpaque(true); } SkBitmap::Config OmxJpegImageDecoder::getColorSpaceConfig( SkBitmap::Config pref) { // Set the color space to ARGB_8888 for now // because of limitation in hardware support. return SkBitmap::kARGB_8888_Config; }