summaryrefslogtreecommitdiffstats
path: root/cmds/stagefright
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2009-08-18 11:27:32 -0700
committerAndreas Huber <andih@google.com>2009-08-18 11:27:32 -0700
commit2d7d46fb2d7f5f80afbf060f25ed049079fb0fc9 (patch)
treee3b1437b4f6d81497e5da9aae05aa1ddc2dc09c6 /cmds/stagefright
parent3781a13f6853abf2b47b6b8d7f4fcabc10c1c804 (diff)
downloadframeworks_av-2d7d46fb2d7f5f80afbf060f25ed049079fb0fc9.zip
frameworks_av-2d7d46fb2d7f5f80afbf060f25ed049079fb0fc9.tar.gz
frameworks_av-2d7d46fb2d7f5f80afbf060f25ed049079fb0fc9.tar.bz2
Refactored "stagefright" commandline app, split off JPEGSource.
Diffstat (limited to 'cmds/stagefright')
-rw-r--r--cmds/stagefright/Android.mk3
-rw-r--r--cmds/stagefright/JPEGSource.cpp235
-rw-r--r--cmds/stagefright/JPEGSource.h59
-rw-r--r--cmds/stagefright/stagefright.cpp400
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;