109daada236c0b4970db44c807d7c29965666c36bAndreas Huber/* 209daada236c0b4970db44c807d7c29965666c36bAndreas Huber * Copyright (C) 2009 The Android Open Source Project 309daada236c0b4970db44c807d7c29965666c36bAndreas Huber * 409daada236c0b4970db44c807d7c29965666c36bAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 509daada236c0b4970db44c807d7c29965666c36bAndreas Huber * you may not use this file except in compliance with the License. 609daada236c0b4970db44c807d7c29965666c36bAndreas Huber * You may obtain a copy of the License at 709daada236c0b4970db44c807d7c29965666c36bAndreas Huber * 809daada236c0b4970db44c807d7c29965666c36bAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 909daada236c0b4970db44c807d7c29965666c36bAndreas Huber * 1009daada236c0b4970db44c807d7c29965666c36bAndreas Huber * Unless required by applicable law or agreed to in writing, software 1109daada236c0b4970db44c807d7c29965666c36bAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1209daada236c0b4970db44c807d7c29965666c36bAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1309daada236c0b4970db44c807d7c29965666c36bAndreas Huber * See the License for the specific language governing permissions and 1409daada236c0b4970db44c807d7c29965666c36bAndreas Huber * limitations under the License. 1509daada236c0b4970db44c807d7c29965666c36bAndreas Huber */ 1609daada236c0b4970db44c807d7c29965666c36bAndreas Huber 1709daada236c0b4970db44c807d7c29965666c36bAndreas Huber// #define LOG_NDEBUG 0 1809daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define LOG_TAG "JPEGSource" 1909daada236c0b4970db44c807d7c29965666c36bAndreas Huber#include <utils/Log.h> 2009daada236c0b4970db44c807d7c29965666c36bAndreas Huber 2109daada236c0b4970db44c807d7c29965666c36bAndreas Huber#include <media/stagefright/DataSource.h> 226026a514248f0c603d0e8c4a3f542abab3fa1509Andreas Huber#include <media/stagefright/JPEGSource.h> 2309daada236c0b4970db44c807d7c29965666c36bAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 2409daada236c0b4970db44c807d7c29965666c36bAndreas Huber#include <media/stagefright/MediaDebug.h> 25e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber#include <media/stagefright/MediaDefs.h> 2609daada236c0b4970db44c807d7c29965666c36bAndreas Huber#include <media/stagefright/MediaErrors.h> 2709daada236c0b4970db44c807d7c29965666c36bAndreas Huber#include <media/stagefright/MetaData.h> 2809daada236c0b4970db44c807d7c29965666c36bAndreas Huber 2909daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF0 0xC0 /* nStart Of Frame N*/ 3009daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF1 0xC1 /* N indicates which compression process*/ 3109daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use*/ 3209daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF3 0xC3 3309daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers*/ 3409daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF6 0xC6 3509daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF7 0xC7 3609daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF9 0xC9 3709daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF10 0xCA 3809daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF11 0xCB 3909daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF13 0xCD 4009daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF14 0xCE 4109daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOF15 0xCF 4209daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOI 0xD8 /* nStart Of Image (beginning of datastream)*/ 4309daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_EOI 0xD9 /* End Of Image (end of datastream)*/ 4409daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_SOS 0xDA /* nStart Of Scan (begins compressed data)*/ 4509daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_JFIF 0xE0 /* Jfif marker*/ 4609daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_EXIF 0xE1 /* Exif marker*/ 4709daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_COM 0xFE /* COMment */ 4809daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_DQT 0xDB 4909daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_DHT 0xC4 5009daada236c0b4970db44c807d7c29965666c36bAndreas Huber#define JPEG_DRI 0xDD 5109daada236c0b4970db44c807d7c29965666c36bAndreas Huber 5209daada236c0b4970db44c807d7c29965666c36bAndreas Hubernamespace android { 5309daada236c0b4970db44c807d7c29965666c36bAndreas Huber 5409daada236c0b4970db44c807d7c29965666c36bAndreas HuberJPEGSource::JPEGSource(const sp<DataSource> &source) 5509daada236c0b4970db44c807d7c29965666c36bAndreas Huber : mSource(source), 5609daada236c0b4970db44c807d7c29965666c36bAndreas Huber mGroup(NULL), 5709daada236c0b4970db44c807d7c29965666c36bAndreas Huber mStarted(false), 5809daada236c0b4970db44c807d7c29965666c36bAndreas Huber mSize(0), 5909daada236c0b4970db44c807d7c29965666c36bAndreas Huber mWidth(0), 6009daada236c0b4970db44c807d7c29965666c36bAndreas Huber mHeight(0), 6109daada236c0b4970db44c807d7c29965666c36bAndreas Huber mOffset(0) { 6209daada236c0b4970db44c807d7c29965666c36bAndreas Huber CHECK_EQ(parseJPEG(), OK); 635c0a9133d2e8049f8952a190df91febf6b92064cAndreas Huber CHECK(mSource->getSize(&mSize) == OK); 6409daada236c0b4970db44c807d7c29965666c36bAndreas Huber} 6509daada236c0b4970db44c807d7c29965666c36bAndreas Huber 6609daada236c0b4970db44c807d7c29965666c36bAndreas HuberJPEGSource::~JPEGSource() { 6709daada236c0b4970db44c807d7c29965666c36bAndreas Huber if (mStarted) { 6809daada236c0b4970db44c807d7c29965666c36bAndreas Huber stop(); 6909daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 7009daada236c0b4970db44c807d7c29965666c36bAndreas Huber} 7109daada236c0b4970db44c807d7c29965666c36bAndreas Huber 7209daada236c0b4970db44c807d7c29965666c36bAndreas Huberstatus_t JPEGSource::start(MetaData *) { 7309daada236c0b4970db44c807d7c29965666c36bAndreas Huber if (mStarted) { 7409daada236c0b4970db44c807d7c29965666c36bAndreas Huber return UNKNOWN_ERROR; 7509daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 7609daada236c0b4970db44c807d7c29965666c36bAndreas Huber 7709daada236c0b4970db44c807d7c29965666c36bAndreas Huber mGroup = new MediaBufferGroup; 7809daada236c0b4970db44c807d7c29965666c36bAndreas Huber mGroup->add_buffer(new MediaBuffer(mSize)); 7909daada236c0b4970db44c807d7c29965666c36bAndreas Huber 8009daada236c0b4970db44c807d7c29965666c36bAndreas Huber mOffset = 0; 8109daada236c0b4970db44c807d7c29965666c36bAndreas Huber 8209daada236c0b4970db44c807d7c29965666c36bAndreas Huber mStarted = true; 8309daada236c0b4970db44c807d7c29965666c36bAndreas Huber 8409daada236c0b4970db44c807d7c29965666c36bAndreas Huber return OK; 8509daada236c0b4970db44c807d7c29965666c36bAndreas Huber} 8609daada236c0b4970db44c807d7c29965666c36bAndreas Huber 8709daada236c0b4970db44c807d7c29965666c36bAndreas Huberstatus_t JPEGSource::stop() { 8809daada236c0b4970db44c807d7c29965666c36bAndreas Huber if (!mStarted) { 8909daada236c0b4970db44c807d7c29965666c36bAndreas Huber return UNKNOWN_ERROR; 9009daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 9109daada236c0b4970db44c807d7c29965666c36bAndreas Huber 9209daada236c0b4970db44c807d7c29965666c36bAndreas Huber delete mGroup; 9309daada236c0b4970db44c807d7c29965666c36bAndreas Huber mGroup = NULL; 9409daada236c0b4970db44c807d7c29965666c36bAndreas Huber 9509daada236c0b4970db44c807d7c29965666c36bAndreas Huber mStarted = false; 9609daada236c0b4970db44c807d7c29965666c36bAndreas Huber 9709daada236c0b4970db44c807d7c29965666c36bAndreas Huber return OK; 9809daada236c0b4970db44c807d7c29965666c36bAndreas Huber} 9909daada236c0b4970db44c807d7c29965666c36bAndreas Huber 10009daada236c0b4970db44c807d7c29965666c36bAndreas Hubersp<MetaData> JPEGSource::getFormat() { 10109daada236c0b4970db44c807d7c29965666c36bAndreas Huber sp<MetaData> meta = new MetaData; 102e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_IMAGE_JPEG); 10309daada236c0b4970db44c807d7c29965666c36bAndreas Huber meta->setInt32(kKeyWidth, mWidth); 10409daada236c0b4970db44c807d7c29965666c36bAndreas Huber meta->setInt32(kKeyHeight, mHeight); 105da050cf206afff082f2a3693a8103a5df67df397Andreas Huber meta->setInt32(kKeyMaxInputSize, mSize); 10609daada236c0b4970db44c807d7c29965666c36bAndreas Huber 10709daada236c0b4970db44c807d7c29965666c36bAndreas Huber return meta; 10809daada236c0b4970db44c807d7c29965666c36bAndreas Huber} 10909daada236c0b4970db44c807d7c29965666c36bAndreas Huber 11009daada236c0b4970db44c807d7c29965666c36bAndreas Huberstatus_t JPEGSource::read( 11109daada236c0b4970db44c807d7c29965666c36bAndreas Huber MediaBuffer **out, const ReadOptions *options) { 11209daada236c0b4970db44c807d7c29965666c36bAndreas Huber *out = NULL; 11309daada236c0b4970db44c807d7c29965666c36bAndreas Huber 11409daada236c0b4970db44c807d7c29965666c36bAndreas Huber int64_t seekTimeUs; 11509daada236c0b4970db44c807d7c29965666c36bAndreas Huber if (options != NULL && options->getSeekTo(&seekTimeUs)) { 11609daada236c0b4970db44c807d7c29965666c36bAndreas Huber return UNKNOWN_ERROR; 11709daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 11809daada236c0b4970db44c807d7c29965666c36bAndreas Huber 11909daada236c0b4970db44c807d7c29965666c36bAndreas Huber MediaBuffer *buffer; 12009daada236c0b4970db44c807d7c29965666c36bAndreas Huber mGroup->acquire_buffer(&buffer); 12109daada236c0b4970db44c807d7c29965666c36bAndreas Huber 1229a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber ssize_t n = mSource->readAt(mOffset, buffer->data(), mSize - mOffset); 12309daada236c0b4970db44c807d7c29965666c36bAndreas Huber 12409daada236c0b4970db44c807d7c29965666c36bAndreas Huber if (n <= 0) { 12509daada236c0b4970db44c807d7c29965666c36bAndreas Huber buffer->release(); 12609daada236c0b4970db44c807d7c29965666c36bAndreas Huber buffer = NULL; 12709daada236c0b4970db44c807d7c29965666c36bAndreas Huber 12809daada236c0b4970db44c807d7c29965666c36bAndreas Huber return UNKNOWN_ERROR; 12909daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 13009daada236c0b4970db44c807d7c29965666c36bAndreas Huber 13109daada236c0b4970db44c807d7c29965666c36bAndreas Huber buffer->set_range(0, n); 13209daada236c0b4970db44c807d7c29965666c36bAndreas Huber 13309daada236c0b4970db44c807d7c29965666c36bAndreas Huber mOffset += n; 13409daada236c0b4970db44c807d7c29965666c36bAndreas Huber 13509daada236c0b4970db44c807d7c29965666c36bAndreas Huber *out = buffer; 13609daada236c0b4970db44c807d7c29965666c36bAndreas Huber 13709daada236c0b4970db44c807d7c29965666c36bAndreas Huber return OK; 13809daada236c0b4970db44c807d7c29965666c36bAndreas Huber} 13909daada236c0b4970db44c807d7c29965666c36bAndreas Huber 14009daada236c0b4970db44c807d7c29965666c36bAndreas Huberstatus_t JPEGSource::parseJPEG() { 14109daada236c0b4970db44c807d7c29965666c36bAndreas Huber mWidth = 0; 14209daada236c0b4970db44c807d7c29965666c36bAndreas Huber mHeight = 0; 14309daada236c0b4970db44c807d7c29965666c36bAndreas Huber 14409daada236c0b4970db44c807d7c29965666c36bAndreas Huber off_t i = 0; 14509daada236c0b4970db44c807d7c29965666c36bAndreas Huber 14609daada236c0b4970db44c807d7c29965666c36bAndreas Huber uint16_t soi; 14709daada236c0b4970db44c807d7c29965666c36bAndreas Huber if (!mSource->getUInt16(i, &soi)) { 14809daada236c0b4970db44c807d7c29965666c36bAndreas Huber return ERROR_IO; 14909daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 15009daada236c0b4970db44c807d7c29965666c36bAndreas Huber 15109daada236c0b4970db44c807d7c29965666c36bAndreas Huber i += 2; 15209daada236c0b4970db44c807d7c29965666c36bAndreas Huber 15309daada236c0b4970db44c807d7c29965666c36bAndreas Huber if (soi != 0xffd8) { 15409daada236c0b4970db44c807d7c29965666c36bAndreas Huber return UNKNOWN_ERROR; 15509daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 15609daada236c0b4970db44c807d7c29965666c36bAndreas Huber 15709daada236c0b4970db44c807d7c29965666c36bAndreas Huber for (;;) { 15809daada236c0b4970db44c807d7c29965666c36bAndreas Huber uint8_t marker; 1599a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mSource->readAt(i++, &marker, 1) != 1) { 16009daada236c0b4970db44c807d7c29965666c36bAndreas Huber return ERROR_IO; 16109daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 16209daada236c0b4970db44c807d7c29965666c36bAndreas Huber 16309daada236c0b4970db44c807d7c29965666c36bAndreas Huber CHECK_EQ(marker, 0xff); 16409daada236c0b4970db44c807d7c29965666c36bAndreas Huber 1659a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mSource->readAt(i++, &marker, 1) != 1) { 16609daada236c0b4970db44c807d7c29965666c36bAndreas Huber return ERROR_IO; 16709daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 16809daada236c0b4970db44c807d7c29965666c36bAndreas Huber 16909daada236c0b4970db44c807d7c29965666c36bAndreas Huber CHECK(marker != 0xff); 17009daada236c0b4970db44c807d7c29965666c36bAndreas Huber 17109daada236c0b4970db44c807d7c29965666c36bAndreas Huber uint16_t chunkSize; 17209daada236c0b4970db44c807d7c29965666c36bAndreas Huber if (!mSource->getUInt16(i, &chunkSize)) { 17309daada236c0b4970db44c807d7c29965666c36bAndreas Huber return ERROR_IO; 17409daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 17509daada236c0b4970db44c807d7c29965666c36bAndreas Huber 17609daada236c0b4970db44c807d7c29965666c36bAndreas Huber i += 2; 17709daada236c0b4970db44c807d7c29965666c36bAndreas Huber 17809daada236c0b4970db44c807d7c29965666c36bAndreas Huber if (chunkSize < 2) { 17909daada236c0b4970db44c807d7c29965666c36bAndreas Huber return UNKNOWN_ERROR; 18009daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 18109daada236c0b4970db44c807d7c29965666c36bAndreas Huber 18209daada236c0b4970db44c807d7c29965666c36bAndreas Huber switch (marker) { 18309daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOS: 18409daada236c0b4970db44c807d7c29965666c36bAndreas Huber { 18509daada236c0b4970db44c807d7c29965666c36bAndreas Huber return (mWidth > 0 && mHeight > 0) ? OK : UNKNOWN_ERROR; 18609daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 18709daada236c0b4970db44c807d7c29965666c36bAndreas Huber 18809daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_EOI: 18909daada236c0b4970db44c807d7c29965666c36bAndreas Huber { 19009daada236c0b4970db44c807d7c29965666c36bAndreas Huber return UNKNOWN_ERROR; 19109daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 19209daada236c0b4970db44c807d7c29965666c36bAndreas Huber 19309daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF0: 19409daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF1: 19509daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF3: 19609daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF5: 19709daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF6: 19809daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF7: 19909daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF9: 20009daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF10: 20109daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF11: 20209daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF13: 20309daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF14: 20409daada236c0b4970db44c807d7c29965666c36bAndreas Huber case JPEG_SOF15: 20509daada236c0b4970db44c807d7c29965666c36bAndreas Huber { 20609daada236c0b4970db44c807d7c29965666c36bAndreas Huber uint16_t width, height; 20709daada236c0b4970db44c807d7c29965666c36bAndreas Huber if (!mSource->getUInt16(i + 1, &height) 20809daada236c0b4970db44c807d7c29965666c36bAndreas Huber || !mSource->getUInt16(i + 3, &width)) { 20909daada236c0b4970db44c807d7c29965666c36bAndreas Huber return ERROR_IO; 21009daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 21109daada236c0b4970db44c807d7c29965666c36bAndreas Huber 21209daada236c0b4970db44c807d7c29965666c36bAndreas Huber mWidth = width; 21309daada236c0b4970db44c807d7c29965666c36bAndreas Huber mHeight = height; 21409daada236c0b4970db44c807d7c29965666c36bAndreas Huber 21509daada236c0b4970db44c807d7c29965666c36bAndreas Huber i += chunkSize - 2; 21609daada236c0b4970db44c807d7c29965666c36bAndreas Huber break; 21709daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 21809daada236c0b4970db44c807d7c29965666c36bAndreas Huber 21909daada236c0b4970db44c807d7c29965666c36bAndreas Huber default: 22009daada236c0b4970db44c807d7c29965666c36bAndreas Huber { 22109daada236c0b4970db44c807d7c29965666c36bAndreas Huber // Skip chunk 22209daada236c0b4970db44c807d7c29965666c36bAndreas Huber 22309daada236c0b4970db44c807d7c29965666c36bAndreas Huber i += chunkSize - 2; 22409daada236c0b4970db44c807d7c29965666c36bAndreas Huber 22509daada236c0b4970db44c807d7c29965666c36bAndreas Huber break; 22609daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 22709daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 22809daada236c0b4970db44c807d7c29965666c36bAndreas Huber } 22909daada236c0b4970db44c807d7c29965666c36bAndreas Huber 23009daada236c0b4970db44c807d7c29965666c36bAndreas Huber return OK; 23109daada236c0b4970db44c807d7c29965666c36bAndreas Huber} 23209daada236c0b4970db44c807d7c29965666c36bAndreas Huber 23309daada236c0b4970db44c807d7c29965666c36bAndreas Huber} // namespace android 234