From 777893a928680f09e306b4b9efc1d5cf4479a9da Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Fri, 11 Sep 2009 07:47:55 -0700 Subject: Move JPEGSource.{cpp,h} into libstagefright. --- media/libstagefright/JPEGSource.cpp | 233 ++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 media/libstagefright/JPEGSource.cpp (limited to 'media/libstagefright/JPEGSource.cpp') diff --git a/media/libstagefright/JPEGSource.cpp b/media/libstagefright/JPEGSource.cpp new file mode 100644 index 0000000..d1dfd83 --- /dev/null +++ b/media/libstagefright/JPEGSource.cpp @@ -0,0 +1,233 @@ +/* + * 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_NDEBUG 0 +#define LOG_TAG "JPEGSource" +#include + +#include +#include +#include +#include +#include +#include +#include + +#define JPEG_SOF0 0xC0 /* nStart Of Frame N*/ +#define JPEG_SOF1 0xC1 /* N indicates which compression process*/ +#define JPEG_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use*/ +#define JPEG_SOF3 0xC3 +#define JPEG_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers*/ +#define JPEG_SOF6 0xC6 +#define JPEG_SOF7 0xC7 +#define JPEG_SOF9 0xC9 +#define JPEG_SOF10 0xCA +#define JPEG_SOF11 0xCB +#define JPEG_SOF13 0xCD +#define JPEG_SOF14 0xCE +#define JPEG_SOF15 0xCF +#define JPEG_SOI 0xD8 /* nStart Of Image (beginning of datastream)*/ +#define JPEG_EOI 0xD9 /* End Of Image (end of datastream)*/ +#define JPEG_SOS 0xDA /* nStart Of Scan (begins compressed data)*/ +#define JPEG_JFIF 0xE0 /* Jfif marker*/ +#define JPEG_EXIF 0xE1 /* Exif marker*/ +#define JPEG_COM 0xFE /* COMment */ +#define JPEG_DQT 0xDB +#define JPEG_DHT 0xC4 +#define JPEG_DRI 0xDD + +namespace android { + +JPEGSource::JPEGSource(const sp &source) + : mSource(source), + mGroup(NULL), + mStarted(false), + mSize(0), + mWidth(0), + mHeight(0), + mOffset(0) { + CHECK_EQ(parseJPEG(), OK); + CHECK(mSource->getSize(&mSize) == OK); +} + +JPEGSource::~JPEGSource() { + if (mStarted) { + stop(); + } +} + +status_t JPEGSource::start(MetaData *) { + if (mStarted) { + return UNKNOWN_ERROR; + } + + mGroup = new MediaBufferGroup; + mGroup->add_buffer(new MediaBuffer(mSize)); + + mOffset = 0; + + mStarted = true; + + return OK; +} + +status_t JPEGSource::stop() { + if (!mStarted) { + return UNKNOWN_ERROR; + } + + delete mGroup; + mGroup = NULL; + + mStarted = false; + + return OK; +} + +sp JPEGSource::getFormat() { + sp meta = new MetaData; + meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_IMAGE_JPEG); + meta->setInt32(kKeyWidth, mWidth); + meta->setInt32(kKeyHeight, mHeight); + meta->setInt32(kKeyMaxInputSize, mSize); + + return meta; +} + +status_t JPEGSource::read( + MediaBuffer **out, const ReadOptions *options) { + *out = NULL; + + int64_t seekTimeUs; + if (options != NULL && options->getSeekTo(&seekTimeUs)) { + return UNKNOWN_ERROR; + } + + MediaBuffer *buffer; + mGroup->acquire_buffer(&buffer); + + ssize_t n = mSource->read_at(mOffset, buffer->data(), mSize - mOffset); + + if (n <= 0) { + buffer->release(); + buffer = NULL; + + return UNKNOWN_ERROR; + } + + buffer->set_range(0, n); + + mOffset += n; + + *out = buffer; + + return OK; +} + +status_t JPEGSource::parseJPEG() { + mWidth = 0; + mHeight = 0; + + off_t i = 0; + + uint16_t soi; + if (!mSource->getUInt16(i, &soi)) { + return ERROR_IO; + } + + i += 2; + + if (soi != 0xffd8) { + return UNKNOWN_ERROR; + } + + for (;;) { + uint8_t marker; + if (mSource->read_at(i++, &marker, 1) != 1) { + return ERROR_IO; + } + + CHECK_EQ(marker, 0xff); + + if (mSource->read_at(i++, &marker, 1) != 1) { + return ERROR_IO; + } + + CHECK(marker != 0xff); + + uint16_t chunkSize; + if (!mSource->getUInt16(i, &chunkSize)) { + return ERROR_IO; + } + + i += 2; + + if (chunkSize < 2) { + return UNKNOWN_ERROR; + } + + switch (marker) { + case JPEG_SOS: + { + return (mWidth > 0 && mHeight > 0) ? OK : UNKNOWN_ERROR; + } + + case JPEG_EOI: + { + return UNKNOWN_ERROR; + } + + case JPEG_SOF0: + case JPEG_SOF1: + case JPEG_SOF3: + case JPEG_SOF5: + case JPEG_SOF6: + case JPEG_SOF7: + case JPEG_SOF9: + case JPEG_SOF10: + case JPEG_SOF11: + case JPEG_SOF13: + case JPEG_SOF14: + case JPEG_SOF15: + { + uint16_t width, height; + if (!mSource->getUInt16(i + 1, &height) + || !mSource->getUInt16(i + 3, &width)) { + return ERROR_IO; + } + + mWidth = width; + mHeight = height; + + i += chunkSize - 2; + break; + } + + default: + { + // Skip chunk + + i += chunkSize - 2; + + break; + } + } + } + + return OK; +} + +} // namespace android -- cgit v1.1