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