Merge change 21745 into eclair
* changes: Refactored "stagefright" commandline app, split off JPEGSource.
This commit is contained in:
@@ -2,7 +2,8 @@ LOCAL_PATH:= $(call my-dir)
|
|||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
LOCAL_SRC_FILES:= \
|
LOCAL_SRC_FILES:= \
|
||||||
|
JPEGSource.cpp \
|
||||||
stagefright.cpp
|
stagefright.cpp
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
|
|||||||
235
cmds/stagefright/JPEGSource.cpp
Normal file
235
cmds/stagefright/JPEGSource.cpp
Normal file
@@ -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
|
||||||
59
cmds/stagefright/JPEGSource.h
Normal file
59
cmds/stagefright/JPEGSource.h
Normal file
@@ -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_
|
||||||
|
|
||||||
@@ -16,18 +16,13 @@
|
|||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <binder/IServiceManager.h>
|
#include <binder/IServiceManager.h>
|
||||||
#include <binder/ProcessState.h>
|
#include <binder/ProcessState.h>
|
||||||
#include <media/IMediaPlayerService.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/MediaDebug.h>
|
||||||
#include <media/stagefright/MediaPlayerImpl.h>
|
#include <media/stagefright/MediaPlayerImpl.h>
|
||||||
#include <media/stagefright/MediaExtractor.h>
|
#include <media/stagefright/MediaExtractor.h>
|
||||||
@@ -38,245 +33,11 @@
|
|||||||
#include <media/stagefright/OMXCodec.h>
|
#include <media/stagefright/OMXCodec.h>
|
||||||
#include <media/stagefright/OMXDecoder.h>
|
#include <media/stagefright/OMXDecoder.h>
|
||||||
|
|
||||||
#include "WaveWriter.h"
|
#include "JPEGSource.h"
|
||||||
|
|
||||||
using namespace android;
|
using namespace android;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
static long gNumRepetitions;
|
||||||
|
|
||||||
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 int64_t getNowUs() {
|
static int64_t getNowUs() {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@@ -304,20 +65,38 @@ static void playSource(OMXClient *client, const sp<MediaSource> &source) {
|
|||||||
|
|
||||||
decoder->start();
|
decoder->start();
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
int64_t startTime = getNowUs();
|
int64_t startTime = getNowUs();
|
||||||
|
|
||||||
int n = 0;
|
long numIterationsLeft = gNumRepetitions;
|
||||||
MediaBuffer *buffer;
|
MediaSource::ReadOptions options;
|
||||||
status_t err;
|
while (numIterationsLeft-- > 0) {
|
||||||
while ((err = decoder->read(&buffer)) == OK) {
|
MediaBuffer *buffer;
|
||||||
if ((++n % 16) == 0) {
|
|
||||||
printf(".");
|
for (;;) {
|
||||||
fflush(stdout);
|
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();
|
printf("$");
|
||||||
buffer = NULL;
|
fflush(stdout);
|
||||||
|
|
||||||
|
options.setSeekTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
decoder->stop();
|
decoder->stop();
|
||||||
printf("\n");
|
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);
|
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) {
|
int main(int argc, char **argv) {
|
||||||
android::ProcessState::self()->startThreadPool();
|
android::ProcessState::self()->startThreadPool();
|
||||||
|
|
||||||
bool audioOnly = false;
|
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<IServiceManager> sm = defaultServiceManager();
|
||||||
sp<IBinder> binder = sm->getService(String16("media.player"));
|
sp<IBinder> binder = sm->getService(String16("media.player"));
|
||||||
sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
|
sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
|
||||||
@@ -348,12 +180,6 @@ int main(int argc, char **argv) {
|
|||||||
it != list.end(); ++it) {
|
it != list.end(); ++it) {
|
||||||
printf("%s\n", (*it).string());
|
printf("%s\n", (*it).string());
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
} else if (argc > 1 && !strcmp(argv[1], "--audio")) {
|
|
||||||
audioOnly = true;
|
|
||||||
++argv;
|
|
||||||
--argc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataSource::RegisterDefaultSniffers();
|
DataSource::RegisterDefaultSniffers();
|
||||||
@@ -361,45 +187,49 @@ int main(int argc, char **argv) {
|
|||||||
OMXClient client;
|
OMXClient client;
|
||||||
status_t err = client.connect();
|
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]);
|
bool isJPEG = false;
|
||||||
if (len >= 4 && !strcasecmp(argv[1] + len - 4, ".jpg")) {
|
|
||||||
isJPEG = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp<MediaSource> mediaSource;
|
size_t len = strlen(filename);
|
||||||
|
if (len >= 4 && !strcasecmp(filename + len - 4, ".jpg")) {
|
||||||
if (isJPEG) {
|
isJPEG = true;
|
||||||
mediaSource = new JPEGSource(dataSource);
|
|
||||||
} else {
|
|
||||||
sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
|
|
||||||
|
|
||||||
size_t numTracks = extractor->countTracks();
|
|
||||||
|
|
||||||
sp<MetaData> meta;
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < numTracks; ++i) {
|
|
||||||
meta = extractor->getTrackMetaData(i);
|
|
||||||
|
|
||||||
const char *mime;
|
|
||||||
meta->findCString(kKeyMIMEType, &mime);
|
|
||||||
|
|
||||||
if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaSource = extractor->getTrack(i);
|
sp<MediaSource> mediaSource;
|
||||||
}
|
|
||||||
|
|
||||||
playSource(&client, mediaSource);
|
if (isJPEG) {
|
||||||
|
mediaSource = new JPEGSource(dataSource);
|
||||||
|
} else {
|
||||||
|
sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
|
||||||
|
|
||||||
|
size_t numTracks = extractor->countTracks();
|
||||||
|
|
||||||
|
sp<MetaData> meta;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < numTracks; ++i) {
|
||||||
|
meta = extractor->getTrackMetaData(i);
|
||||||
|
|
||||||
|
const char *mime;
|
||||||
|
meta->findCString(kKeyMIMEType, &mime);
|
||||||
|
|
||||||
|
if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaSource = extractor->getTrack(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
playSource(&client, mediaSource);
|
||||||
|
}
|
||||||
|
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#define MEDIA_BUFFER_GROUP_H_
|
#define MEDIA_BUFFER_GROUP_H_
|
||||||
|
|
||||||
|
#include <media/stagefright/MediaBuffer.h>
|
||||||
#include <utils/Errors.h>
|
#include <utils/Errors.h>
|
||||||
#include <utils/threads.h>
|
#include <utils/threads.h>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user