diff options
author | Andreas Huber <andih@google.com> | 2009-08-18 11:27:32 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2009-08-18 11:27:32 -0700 |
commit | 2d7d46fb2d7f5f80afbf060f25ed049079fb0fc9 (patch) | |
tree | e3b1437b4f6d81497e5da9aae05aa1ddc2dc09c6 /cmds | |
parent | 3781a13f6853abf2b47b6b8d7f4fcabc10c1c804 (diff) | |
download | frameworks_av-2d7d46fb2d7f5f80afbf060f25ed049079fb0fc9.zip frameworks_av-2d7d46fb2d7f5f80afbf060f25ed049079fb0fc9.tar.gz frameworks_av-2d7d46fb2d7f5f80afbf060f25ed049079fb0fc9.tar.bz2 |
Refactored "stagefright" commandline app, split off JPEGSource.
Diffstat (limited to 'cmds')
-rw-r--r-- | cmds/stagefright/Android.mk | 3 | ||||
-rw-r--r-- | cmds/stagefright/JPEGSource.cpp | 235 | ||||
-rw-r--r-- | cmds/stagefright/JPEGSource.h | 59 | ||||
-rw-r--r-- | cmds/stagefright/stagefright.cpp | 400 |
4 files changed, 411 insertions, 286 deletions
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk index 4576b8e..697d67a 100644 --- a/cmds/stagefright/Android.mk +++ b/cmds/stagefright/Android.mk @@ -2,7 +2,8 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES:= \ +LOCAL_SRC_FILES:= \ + JPEGSource.cpp \ stagefright.cpp LOCAL_SHARED_LIBRARIES := \ diff --git a/cmds/stagefright/JPEGSource.cpp b/cmds/stagefright/JPEGSource.cpp new file mode 100644 index 0000000..338a3d5 --- /dev/null +++ b/cmds/stagefright/JPEGSource.cpp @@ -0,0 +1,235 @@ +/* + * 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 <utils/Log.h> + +#include "JPEGSource.h" + +#include <media/stagefright/DataSource.h> +#include <media/stagefright/MediaBufferGroup.h> +#include <media/stagefright/MediaDebug.h> +#include <media/stagefright/MediaErrors.h> +#include <media/stagefright/MetaData.h> + +#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<DataSource> &source) + : mSource(source), + mGroup(NULL), + mStarted(false), + mSize(0), + mWidth(0), + mHeight(0), + mOffset(0) { + CHECK_EQ(parseJPEG(), OK); +} + +JPEGSource::~JPEGSource() { + if (mStarted) { + stop(); + } +} + +status_t JPEGSource::start(MetaData *) { + if (mStarted) { + return UNKNOWN_ERROR; + } + + if (mSource->getSize(&mSize) != OK) { + 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<MetaData> JPEGSource::getFormat() { + sp<MetaData> meta = new MetaData; + meta->setCString(kKeyMIMEType, "image/jpeg"); + meta->setInt32(kKeyWidth, mWidth); + meta->setInt32(kKeyHeight, mHeight); + + 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 diff --git a/cmds/stagefright/JPEGSource.h b/cmds/stagefright/JPEGSource.h new file mode 100644 index 0000000..051c034 --- /dev/null +++ b/cmds/stagefright/JPEGSource.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#ifndef JPEG_SOURCE_H_ + +#define JPEG_SOURCE_H_ + +#include <media/stagefright/MediaSource.h> + +namespace android { + +class DataSource; +class MediaBufferGroup; + +struct JPEGSource : public MediaSource { + // Assumes ownership of "source". + JPEGSource(const sp<DataSource> &source); + + virtual status_t start(MetaData *params = NULL); + virtual status_t stop(); + virtual sp<MetaData> getFormat(); + + virtual status_t read( + MediaBuffer **buffer, const ReadOptions *options = NULL); + +protected: + virtual ~JPEGSource(); + +private: + sp<DataSource> mSource; + MediaBufferGroup *mGroup; + bool mStarted; + off_t mSize; + int32_t mWidth, mHeight; + off_t mOffset; + + status_t parseJPEG(); + + JPEGSource(const JPEGSource &); + JPEGSource &operator=(const JPEGSource &); +}; + +} // namespace android + +#endif // JPEG_SOURCE_H_ + diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index b2de67a..56f6338 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -16,18 +16,13 @@ #include <sys/time.h> -#include <pthread.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/AudioPlayer.h> -#include <media/stagefright/CachingDataSource.h> -#include <media/stagefright/ESDS.h> -#include <media/stagefright/FileSource.h> -#include <media/stagefright/MediaBuffer.h> -#include <media/stagefright/MediaBufferGroup.h> #include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaPlayerImpl.h> #include <media/stagefright/MediaExtractor.h> @@ -38,245 +33,11 @@ #include <media/stagefright/OMXCodec.h> #include <media/stagefright/OMXDecoder.h> -#include "WaveWriter.h" +#include "JPEGSource.h" using namespace android; -//////////////////////////////////////////////////////////////////////////////// - -struct JPEGSource : public MediaSource { - // Assumes ownership of "source". - JPEGSource(const sp<DataSource> &source); - - virtual status_t start(MetaData *params = NULL); - virtual status_t stop(); - virtual sp<MetaData> getFormat(); - - virtual status_t read( - MediaBuffer **buffer, const ReadOptions *options = NULL); - -protected: - virtual ~JPEGSource(); - -private: - sp<DataSource> mSource; - MediaBufferGroup *mGroup; - bool mStarted; - off_t mSize; - int32_t mWidth, mHeight; - off_t mOffset; - - status_t parseJPEG(); - - JPEGSource(const JPEGSource &); - JPEGSource &operator=(const JPEGSource &); -}; - -JPEGSource::JPEGSource(const sp<DataSource> &source) - : mSource(source), - mGroup(NULL), - mStarted(false), - mSize(0), - mWidth(0), - mHeight(0), - mOffset(0) { - CHECK_EQ(parseJPEG(), OK); -} - -JPEGSource::~JPEGSource() { - if (mStarted) { - stop(); - } -} - -status_t JPEGSource::start(MetaData *) { - if (mStarted) { - return UNKNOWN_ERROR; - } - - if (mSource->getSize(&mSize) != OK) { - 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<MetaData> JPEGSource::getFormat() { - sp<MetaData> meta = new MetaData; - meta->setCString(kKeyMIMEType, "image/jpeg"); - meta->setInt32(kKeyWidth, mWidth); - meta->setInt32(kKeyHeight, mHeight); - - 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; -} - -#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 - -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; -} - -//////////////////////////////////////////////////////////////////////////////// +static long gNumRepetitions; static int64_t getNowUs() { struct timeval tv; @@ -304,20 +65,38 @@ static void playSource(OMXClient *client, const sp<MediaSource> &source) { decoder->start(); + int n = 0; int64_t startTime = getNowUs(); - int n = 0; - MediaBuffer *buffer; - status_t err; - while ((err = decoder->read(&buffer)) == OK) { - if ((++n % 16) == 0) { - printf("."); - fflush(stdout); + long numIterationsLeft = gNumRepetitions; + MediaSource::ReadOptions options; + while (numIterationsLeft-- > 0) { + MediaBuffer *buffer; + + for (;;) { + status_t err = decoder->read(&buffer, &options); + options.clearSeekTo(); + + if (err != OK) { + CHECK_EQ(buffer, NULL); + break; + } + + if ((n++ % 16) == 0) { + printf("."); + fflush(stdout); + } + + buffer->release(); + buffer = NULL; } - buffer->release(); - buffer = NULL; + printf("$"); + fflush(stdout); + + options.setSeekTo(0); } + decoder->stop(); printf("\n"); @@ -327,11 +106,64 @@ static void playSource(OMXClient *client, const sp<MediaSource> &source) { printf("decoded a total of %d frame(s).\n", n); } +static void usage(const char *me) { + fprintf(stderr, "usage: %s\n", me); + fprintf(stderr, " -h(elp)\n"); + fprintf(stderr, " -a(udio)\n"); + fprintf(stderr, " -n repetitions\n"); + fprintf(stderr, " -l(ist) components\n"); +} + int main(int argc, char **argv) { android::ProcessState::self()->startThreadPool(); bool audioOnly = false; - if (argc > 1 && !strcmp(argv[1], "--list")) { + bool listComponents = false; + gNumRepetitions = 1; + + int res; + while ((res = getopt(argc, argv, "han:l")) >= 0) { + switch (res) { + case 'a': + { + audioOnly = true; + break; + } + + case 'l': + { + listComponents = true; + break; + } + + case 'n': + { + char *end; + long x = strtol(optarg, &end, 10); + + if (*end != '\0' || end == optarg || x <= 0) { + x = 1; + } + + gNumRepetitions = x; + break; + } + + case '?': + case 'h': + default: + { + usage(argv[0]); + exit(1); + break; + } + } + } + + argc -= optind; + argv += optind; + + if (listComponents) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->getService(String16("media.player")); sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); @@ -348,12 +180,6 @@ int main(int argc, char **argv) { it != list.end(); ++it) { printf("%s\n", (*it).string()); } - - return 0; - } else if (argc > 1 && !strcmp(argv[1], "--audio")) { - audioOnly = true; - ++argv; - --argc; } DataSource::RegisterDefaultSniffers(); @@ -361,46 +187,50 @@ int main(int argc, char **argv) { OMXClient client; status_t err = client.connect(); - sp<MmapSource> dataSource = new MmapSource(argv[1]); + for (int k = 0; k < argc; ++k) { + const char *filename = argv[k]; - bool isJPEG = false; + sp<MmapSource> dataSource = new MmapSource(filename); - size_t len = strlen(argv[1]); - if (len >= 4 && !strcasecmp(argv[1] + len - 4, ".jpg")) { - isJPEG = true; - } + bool isJPEG = false; - sp<MediaSource> mediaSource; + size_t len = strlen(filename); + if (len >= 4 && !strcasecmp(filename + len - 4, ".jpg")) { + isJPEG = true; + } - if (isJPEG) { - mediaSource = new JPEGSource(dataSource); - } else { - sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); + sp<MediaSource> mediaSource; - size_t numTracks = extractor->countTracks(); + if (isJPEG) { + mediaSource = new JPEGSource(dataSource); + } else { + sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource); - sp<MetaData> meta; - size_t i; - for (i = 0; i < numTracks; ++i) { - meta = extractor->getTrackMetaData(i); + size_t numTracks = extractor->countTracks(); - const char *mime; - meta->findCString(kKeyMIMEType, &mime); + sp<MetaData> meta; + size_t i; + for (i = 0; i < numTracks; ++i) { + meta = extractor->getTrackMetaData(i); - if (audioOnly && !strncasecmp(mime, "audio/", 6)) { - break; - } + const char *mime; + meta->findCString(kKeyMIMEType, &mime); - if (!audioOnly && !strncasecmp(mime, "video/", 6)) { - break; + if (audioOnly && !strncasecmp(mime, "audio/", 6)) { + break; + } + + if (!audioOnly && !strncasecmp(mime, "video/", 6)) { + break; + } } + + mediaSource = extractor->getTrack(i); } - mediaSource = extractor->getTrack(i); + playSource(&client, mediaSource); } - playSource(&client, mediaSource); - client.disconnect(); return 0; |