Merge change 21340 into eclair

* changes:
  Squashed commit of the following:
This commit is contained in:
Android (Google) Code Review
2009-08-17 10:27:41 -07:00
34 changed files with 3028 additions and 363 deletions

View File

@@ -10,8 +10,7 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_C_INCLUDES:= \ LOCAL_C_INCLUDES:= \
frameworks/base/media/libstagefright \ frameworks/base/media/libstagefright \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
$(TOP)/external/opencore/android
LOCAL_CFLAGS += -Wno-multichar LOCAL_CFLAGS += -Wno-multichar
@@ -31,8 +30,7 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_C_INCLUDES:= \ LOCAL_C_INCLUDES:= \
frameworks/base/media/libstagefright \ frameworks/base/media/libstagefright \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
$(TOP)/external/opencore/android
LOCAL_CFLAGS += -Wno-multichar LOCAL_CFLAGS += -Wno-multichar
@@ -52,8 +50,7 @@ include $(BUILD_EXECUTABLE)
# #
# LOCAL_C_INCLUDES:= \ # LOCAL_C_INCLUDES:= \
# frameworks/base/media/libstagefright \ # frameworks/base/media/libstagefright \
# $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \ # $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
# $(TOP)/external/opencore/android
# #
# LOCAL_CFLAGS += -Wno-multichar # LOCAL_CFLAGS += -Wno-multichar
# #

View File

@@ -25,6 +25,7 @@
#include <media/stagefright/MPEG4Writer.h> #include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/MmapSource.h> #include <media/stagefright/MmapSource.h>
#include <media/stagefright/OMXClient.h> #include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/OMXDecoder.h> #include <media/stagefright/OMXDecoder.h>
using namespace android; using namespace android;
@@ -32,18 +33,38 @@ using namespace android;
class DummySource : public MediaSource { class DummySource : public MediaSource {
public: public:
DummySource(int width, int height) DummySource(int width, int height)
: mSize((width * height * 3) / 2) { : mWidth(width),
mHeight(height),
mSize((width * height * 3) / 2) {
mGroup.add_buffer(new MediaBuffer(mSize)); mGroup.add_buffer(new MediaBuffer(mSize));
} }
virtual ::status_t getMaxSampleSize(size_t *max_size) { virtual sp<MetaData> getFormat() {
*max_size = mSize; sp<MetaData> meta = new MetaData;
return ::OK; meta->setInt32(kKeyWidth, mWidth);
meta->setInt32(kKeyHeight, mHeight);
meta->setCString(kKeyMIMEType, "video/raw");
return meta;
} }
virtual ::status_t read(MediaBuffer **buffer) { virtual status_t getMaxSampleSize(size_t *max_size) {
::status_t err = mGroup.acquire_buffer(buffer); *max_size = mSize;
if (err != ::OK) { return OK;
}
virtual status_t start(MetaData *params) {
return OK;
}
virtual status_t stop() {
return OK;
}
virtual status_t read(
MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
status_t err = mGroup.acquire_buffer(buffer);
if (err != OK) {
return err; return err;
} }
@@ -51,34 +72,34 @@ public:
memset((*buffer)->data(), x, mSize); memset((*buffer)->data(), x, mSize);
(*buffer)->set_range(0, mSize); (*buffer)->set_range(0, mSize);
return ::OK; return OK;
} }
protected:
virtual ~DummySource() {}
private: private:
MediaBufferGroup mGroup; MediaBufferGroup mGroup;
int mWidth, mHeight;
size_t mSize; size_t mSize;
DummySource(const DummySource &); DummySource(const DummySource &);
DummySource &operator=(const DummySource &); DummySource &operator=(const DummySource &);
}; };
int main(int argc, char **argv) { #define USE_OMX_CODEC 1
android::ProcessState::self()->startThreadPool();
#if 1 sp<MediaSource> createSource(const char *filename) {
if (argc != 2) { sp<MediaSource> source;
fprintf(stderr, "usage: %s filename\n", argv[0]);
return 1;
}
MPEG4Extractor extractor(new MmapSource(argv[1])); sp<MPEG4Extractor> extractor =
int num_tracks; new MPEG4Extractor(new MmapSource(filename));
assert(extractor.countTracks(&num_tracks) == ::OK);
size_t num_tracks = extractor->countTracks();
MediaSource *source = NULL;
sp<MetaData> meta; sp<MetaData> meta;
for (int i = 0; i < num_tracks; ++i) { for (size_t i = 0; i < num_tracks; ++i) {
meta = extractor.getTrackMetaData(i); meta = extractor->getTrackMetaData(i);
assert(meta.get() != NULL); assert(meta.get() != NULL);
const char *mime; const char *mime;
@@ -90,48 +111,75 @@ int main(int argc, char **argv) {
continue; continue;
} }
if (extractor.getTrack(i, &source) != ::OK) { source = extractor->getTrack(i);
source = NULL;
continue;
}
break; break;
} }
if (source == NULL) { return source;
fprintf(stderr, "Unable to find a suitable video track.\n"); }
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
#if 1
if (argc != 2) {
fprintf(stderr, "usage: %s filename\n", argv[0]);
return 1; return 1;
} }
OMXClient client; OMXClient client;
assert(client.connect() == android::OK); assert(client.connect() == android::OK);
OMXDecoder *decoder = OMXDecoder::Create(&client, meta); #if 0
decoder->setSource(source); sp<MediaSource> source = createSource(argv[1]);
if (source == NULL) {
fprintf(stderr, "Unable to find a suitable video track.\n");
return 1;
}
sp<MetaData> meta = source->getFormat();
#if USE_OMX_CODEC
sp<OMXCodec> decoder = OMXCodec::Create(
client.interface(), meta, false /* createEncoder */, source);
#else
sp<OMXDecoder> decoder = OMXDecoder::Create(
&client, meta, false /* createEncoder */, source);
#endif
int width, height; int width, height;
bool success = meta->findInt32(kKeyWidth, &width); bool success = meta->findInt32(kKeyWidth, &width);
success = success && meta->findInt32(kKeyHeight, &height); success = success && meta->findInt32(kKeyHeight, &height);
assert(success); assert(success);
#else
int width = 320;
int height = 240;
sp<MediaSource> decoder = new DummySource(width, height);
#endif
sp<MetaData> enc_meta = new MetaData; sp<MetaData> enc_meta = new MetaData;
enc_meta->setCString(kKeyMIMEType, "video/3gpp"); // enc_meta->setCString(kKeyMIMEType, "video/3gpp");
// enc_meta->setCString(kKeyMIMEType, "video/mp4v-es"); enc_meta->setCString(kKeyMIMEType, "video/mp4v-es");
enc_meta->setInt32(kKeyWidth, width); enc_meta->setInt32(kKeyWidth, width);
enc_meta->setInt32(kKeyHeight, height); enc_meta->setInt32(kKeyHeight, height);
OMXDecoder *encoder = #if USE_OMX_CODEC
OMXDecoder::Create(&client, enc_meta, true /* createEncoder */); sp<OMXCodec> encoder =
OMXCodec::Create(
encoder->setSource(decoder); client.interface(), enc_meta, true /* createEncoder */, decoder);
// encoder->setSource(meta, new DummySource(width, height)); #else
sp<OMXDecoder> encoder = OMXDecoder::Create(
&client, enc_meta, true /* createEncoder */, decoder);
#endif
#if 1 #if 1
MPEG4Writer writer("/sdcard/output.mp4"); sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
writer.addSource(enc_meta, encoder); writer->addSource(enc_meta, encoder);
writer.start(); writer->start();
sleep(20); sleep(20);
printf("stopping now.\n"); printf("stopping now.\n");
writer.stop(); writer->stop();
#else #else
encoder->start(); encoder->start();
@@ -146,16 +194,7 @@ int main(int argc, char **argv) {
encoder->stop(); encoder->stop();
#endif #endif
delete encoder;
encoder = NULL;
delete decoder;
decoder = NULL;
client.disconnect(); client.disconnect();
delete source;
source = NULL;
#endif #endif
#if 0 #if 0

View File

@@ -16,9 +16,6 @@
#include <sys/time.h> #include <sys/time.h>
#undef NDEBUG
#include <assert.h>
#include <pthread.h> #include <pthread.h>
#include <stdlib.h> #include <stdlib.h>
@@ -30,12 +27,15 @@
#include <media/stagefright/ESDS.h> #include <media/stagefright/ESDS.h>
#include <media/stagefright/FileSource.h> #include <media/stagefright/FileSource.h>
#include <media/stagefright/MediaBuffer.h> #include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.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>
#include <media/stagefright/MediaSource.h> #include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h> #include <media/stagefright/MetaData.h>
#include <media/stagefright/MmapSource.h> #include <media/stagefright/MmapSource.h>
#include <media/stagefright/OMXClient.h> #include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/OMXDecoder.h> #include <media/stagefright/OMXDecoder.h>
#include "WaveWriter.h" #include "WaveWriter.h"
@@ -44,50 +44,236 @@ using namespace android;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static bool convertToWav( struct JPEGSource : public MediaSource {
OMXClient *client, const sp<MetaData> &meta, MediaSource *source) { // Assumes ownership of "source".
printf("convertToWav\n"); JPEGSource(const sp<DataSource> &source);
OMXDecoder *decoder = OMXDecoder::Create(client, meta); virtual status_t start(MetaData *params = NULL);
virtual status_t stop();
virtual sp<MetaData> getFormat();
int32_t sampleRate; virtual status_t read(
bool success = meta->findInt32(kKeySampleRate, &sampleRate); MediaBuffer **buffer, const ReadOptions *options = NULL);
assert(success);
int32_t numChannels; protected:
success = meta->findInt32(kKeyChannelCount, &numChannels); virtual ~JPEGSource();
assert(success);
const char *mime; private:
success = meta->findCString(kKeyMIMEType, &mime); sp<DataSource> mSource;
assert(success); MediaBufferGroup *mGroup;
bool mStarted;
off_t mSize;
int32_t mWidth, mHeight;
off_t mOffset;
if (!strcasecmp("audio/3gpp", mime)) { status_t parseJPEG();
numChannels = 1; // XXX
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;
} }
WaveWriter writer("/sdcard/Music/shoutcast.wav", numChannels, sampleRate); if (mSource->getSize(&mSize) != OK) {
return UNKNOWN_ERROR;
}
decoder->setSource(source); mGroup = new MediaBufferGroup;
for (int i = 0; i < 100; ++i) { mGroup->add_buffer(new MediaBuffer(mSize));
MediaBuffer *buffer;
::status_t err = decoder->read(&buffer); mOffset = 0;
if (err != ::OK) {
break;
}
writer.Append((const char *)buffer->data() + buffer->range_offset(), mStarted = true;
buffer->range_length());
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->release();
buffer = NULL; buffer = NULL;
return UNKNOWN_ERROR;
} }
delete decoder; buffer->set_range(0, n);
decoder = NULL;
return true; 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;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -99,6 +285,48 @@ static int64_t getNowUs() {
return (int64_t)tv.tv_usec + tv.tv_sec * 1000000; return (int64_t)tv.tv_usec + tv.tv_sec * 1000000;
} }
#define USE_OMX_CODEC 1
static void playSource(OMXClient *client, const sp<MediaSource> &source) {
sp<MetaData> meta = source->getFormat();
#if !USE_OMX_CODEC
sp<OMXDecoder> decoder = OMXDecoder::Create(
client, meta, false /* createEncoder */, source);
#else
sp<OMXCodec> decoder = OMXCodec::Create(
client->interface(), meta, false /* createEncoder */, source);
#endif
if (decoder == NULL) {
return;
}
decoder->start();
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);
}
buffer->release();
buffer = NULL;
}
decoder->stop();
printf("\n");
int64_t delay = getNowUs() - startTime;
printf("avg. %.2f fps\n", n * 1E6 / delay);
printf("decoded a total of %d frame(s).\n", n);
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool(); android::ProcessState::self()->startThreadPool();
@@ -108,10 +336,10 @@ int main(int argc, char **argv) {
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);
assert(service.get() != NULL); CHECK(service.get() != NULL);
sp<IOMX> omx = service->createOMX(); sp<IOMX> omx = service->createOMX();
assert(omx.get() != NULL); CHECK(omx.get() != NULL);
List<String8> list; List<String8> list;
omx->list_nodes(&list); omx->list_nodes(&list);
@@ -128,82 +356,52 @@ int main(int argc, char **argv) {
--argc; --argc;
} }
#if 0
MediaPlayerImpl player(argv[1]);
player.play();
sleep(10000);
#else
DataSource::RegisterDefaultSniffers(); DataSource::RegisterDefaultSniffers();
OMXClient client; OMXClient client;
status_t err = client.connect(); status_t err = client.connect();
MmapSource *dataSource = new MmapSource(argv[1]); sp<MmapSource> dataSource = new MmapSource(argv[1]);
MediaExtractor *extractor = MediaExtractor::Create(dataSource);
dataSource = NULL;
int numTracks; bool isJPEG = false;
err = extractor->countTracks(&numTracks);
sp<MetaData> meta; size_t len = strlen(argv[1]);
int i; if (len >= 4 && !strcasecmp(argv[1] + len - 4, ".jpg")) {
for (i = 0; i < numTracks; ++i) { isJPEG = true;
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;
}
} }
OMXDecoder *decoder = OMXDecoder::Create(&client, meta); sp<MediaSource> mediaSource;
if (decoder != NULL) { if (isJPEG) {
MediaSource *source; mediaSource = new JPEGSource(dataSource);
err = extractor->getTrack(i, &source); } else {
sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
decoder->setSource(source); size_t numTracks = extractor->countTracks();
decoder->start(); sp<MetaData> meta;
size_t i;
for (i = 0; i < numTracks; ++i) {
meta = extractor->getTrackMetaData(i);
int64_t startTime = getNowUs(); const char *mime;
meta->findCString(kKeyMIMEType, &mime);
int n = 0; if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
MediaBuffer *buffer; break;
while ((err = decoder->read(&buffer)) == OK) {
if ((++n % 16) == 0) {
printf(".");
fflush(stdout);
} }
buffer->release(); if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
buffer = NULL; break;
}
} }
decoder->stop();
printf("\n");
int64_t delay = getNowUs() - startTime; mediaSource = extractor->getTrack(i);
printf("avg. %.2f fps\n", n * 1E6 / delay);
delete decoder;
decoder = NULL;
delete source;
source = NULL;
} }
delete extractor; playSource(&client, mediaSource);
extractor = NULL;
client.disconnect(); client.disconnect();
#endif
return 0; return 0;
} }

View File

@@ -56,6 +56,14 @@ public:
node_id node, OMX_INDEXTYPE index, node_id node, OMX_INDEXTYPE index,
const void *params, size_t size) = 0; const void *params, size_t size) = 0;
virtual status_t get_config(
node_id node, OMX_INDEXTYPE index,
void *params, size_t size) = 0;
virtual status_t set_config(
node_id node, OMX_INDEXTYPE index,
const void *params, size_t size) = 0;
virtual status_t use_buffer( virtual status_t use_buffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params, node_id node, OMX_U32 port_index, const sp<IMemory> &params,
buffer_id *buffer) = 0; buffer_id *buffer) = 0;
@@ -82,6 +90,11 @@ public:
OMX_U32 range_offset, OMX_U32 range_length, OMX_U32 range_offset, OMX_U32 range_length,
OMX_U32 flags, OMX_TICKS timestamp) = 0; OMX_U32 flags, OMX_TICKS timestamp) = 0;
virtual status_t get_extension_index(
node_id node,
const char *parameter_name,
OMX_INDEXTYPE *index) = 0;
virtual sp<IOMXRenderer> createRenderer( virtual sp<IOMXRenderer> createRenderer(
const sp<ISurface> &surface, const sp<ISurface> &surface,
const char *componentName, const char *componentName,
@@ -114,10 +127,11 @@ struct omx_message {
QUIT_OBSERVER, QUIT_OBSERVER,
} type; } type;
IOMX::node_id node;
union { union {
// if type == EVENT // if type == EVENT
struct { struct {
IOMX::node_id node;
OMX_EVENTTYPE event; OMX_EVENTTYPE event;
OMX_U32 data1; OMX_U32 data1;
OMX_U32 data2; OMX_U32 data2;
@@ -126,13 +140,11 @@ struct omx_message {
// if type == EMPTY_BUFFER_DONE || type == FILL_BUFFER // if type == EMPTY_BUFFER_DONE || type == FILL_BUFFER
// || type == INITIAL_FILL_BUFFER // || type == INITIAL_FILL_BUFFER
struct { struct {
IOMX::node_id node;
IOMX::buffer_id buffer; IOMX::buffer_id buffer;
} buffer_data; } buffer_data;
// if type == EMPTY_BUFFER || type == FILL_BUFFER_DONE // if type == EMPTY_BUFFER || type == FILL_BUFFER_DONE
struct { struct {
IOMX::node_id node;
IOMX::buffer_id buffer; IOMX::buffer_id buffer;
OMX_U32 range_offset; OMX_U32 range_offset;
OMX_U32 range_length; OMX_U32 range_length;
@@ -143,7 +155,6 @@ struct omx_message {
// if type == SEND_COMMAND // if type == SEND_COMMAND
struct { struct {
IOMX::node_id node;
OMX_COMMANDTYPE cmd; OMX_COMMANDTYPE cmd;
OMX_S32 param; OMX_S32 param;
} send_command_data; } send_command_data;

View File

@@ -31,10 +31,10 @@ class AudioTrack;
class AudioPlayer : public TimeSource { class AudioPlayer : public TimeSource {
public: public:
AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink); AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink);
~AudioPlayer(); virtual ~AudioPlayer();
// Caller retains ownership of "source". // Caller retains ownership of "source".
void setSource(MediaSource *source); void setSource(const sp<MediaSource> &source);
// Return time in us. // Return time in us.
virtual int64_t getRealTimeUs(); virtual int64_t getRealTimeUs();
@@ -56,7 +56,7 @@ public:
status_t seekTo(int64_t time_us); status_t seekTo(int64_t time_us);
private: private:
MediaSource *mSource; sp<MediaSource> mSource;
AudioTrack *mAudioTrack; AudioTrack *mAudioTrack;
MediaBuffer *mInputBuffer; MediaBuffer *mInputBuffer;

View File

@@ -26,14 +26,16 @@ namespace android {
class CachingDataSource : public DataSource { class CachingDataSource : public DataSource {
public: public:
// Assumes ownership of "source". CachingDataSource(
CachingDataSource(DataSource *source, size_t pageSize, int numPages); const sp<DataSource> &source, size_t pageSize, int numPages);
virtual ~CachingDataSource();
status_t InitCheck() const; status_t InitCheck() const;
virtual ssize_t read_at(off_t offset, void *data, size_t size); virtual ssize_t read_at(off_t offset, void *data, size_t size);
protected:
virtual ~CachingDataSource();
private: private:
struct Page { struct Page {
Page *mPrev, *mNext; Page *mPrev, *mNext;
@@ -42,7 +44,7 @@ private:
void *mData; void *mData;
}; };
DataSource *mSource; sp<DataSource> mSource;
void *mData; void *mData;
size_t mPageSize; size_t mPageSize;
Page *mFirst, *mLast; Page *mFirst, *mLast;

View File

@@ -22,19 +22,22 @@
#include <utils/Errors.h> #include <utils/Errors.h>
#include <utils/List.h> #include <utils/List.h>
#include <utils/RefBase.h>
#include <utils/threads.h> #include <utils/threads.h>
namespace android { namespace android {
class String8; class String8;
class DataSource { class DataSource : public RefBase {
public: public:
DataSource() {} DataSource() {}
virtual ~DataSource() {}
virtual ssize_t read_at(off_t offset, void *data, size_t size) = 0; virtual ssize_t read_at(off_t offset, void *data, size_t size) = 0;
// Convenience methods:
bool getUInt16(off_t offset, uint16_t *x);
// May return ERROR_UNSUPPORTED. // May return ERROR_UNSUPPORTED.
virtual status_t getSize(off_t *size); virtual status_t getSize(off_t *size);
@@ -43,11 +46,14 @@ public:
bool sniff(String8 *mimeType, float *confidence); bool sniff(String8 *mimeType, float *confidence);
typedef bool (*SnifferFunc)( typedef bool (*SnifferFunc)(
DataSource *source, String8 *mimeType, float *confidence); const sp<DataSource> &source, String8 *mimeType, float *confidence);
static void RegisterSniffer(SnifferFunc func); static void RegisterSniffer(SnifferFunc func);
static void RegisterDefaultSniffers(); static void RegisterDefaultSniffers();
protected:
virtual ~DataSource() {}
private: private:
static Mutex gSnifferMutex; static Mutex gSnifferMutex;
static List<SnifferFunc> gSniffers; static List<SnifferFunc> gSniffers;

View File

@@ -28,16 +28,17 @@ class String8;
class MP3Extractor : public MediaExtractor { class MP3Extractor : public MediaExtractor {
public: public:
// Extractor assumes ownership of "source". // Extractor assumes ownership of "source".
MP3Extractor(DataSource *source); MP3Extractor(const sp<DataSource> &source);
~MP3Extractor(); size_t countTracks();
sp<MediaSource> getTrack(size_t index);
sp<MetaData> getTrackMetaData(size_t index);
status_t countTracks(int *num_tracks); protected:
status_t getTrack(int index, MediaSource **source); virtual ~MP3Extractor();
sp<MetaData> getTrackMetaData(int index);
private: private:
DataSource *mDataSource; sp<DataSource> mDataSource;
off_t mFirstFramePos; off_t mFirstFramePos;
sp<MetaData> mMeta; sp<MetaData> mMeta;
uint32_t mFixedHeader; uint32_t mFixedHeader;
@@ -46,7 +47,8 @@ private:
MP3Extractor &operator=(const MP3Extractor &); MP3Extractor &operator=(const MP3Extractor &);
}; };
bool SniffMP3(DataSource *source, String8 *mimeType, float *confidence); bool SniffMP3(
const sp<DataSource> &source, String8 *mimeType, float *confidence);
} // namespace android } // namespace android

View File

@@ -29,22 +29,24 @@ class String8;
class MPEG4Extractor : public MediaExtractor { class MPEG4Extractor : public MediaExtractor {
public: public:
// Extractor assumes ownership of "source". // Extractor assumes ownership of "source".
MPEG4Extractor(DataSource *source); MPEG4Extractor(const sp<DataSource> &source);
~MPEG4Extractor();
status_t countTracks(int *num_tracks); size_t countTracks();
status_t getTrack(int index, MediaSource **source); sp<MediaSource> getTrack(size_t index);
sp<MetaData> getTrackMetaData(int index); sp<MetaData> getTrackMetaData(size_t index);
protected:
virtual ~MPEG4Extractor();
private: private:
struct Track { struct Track {
Track *next; Track *next;
sp<MetaData> meta; sp<MetaData> meta;
uint32_t timescale; uint32_t timescale;
SampleTable *sampleTable; sp<SampleTable> sampleTable;
}; };
DataSource *mDataSource; sp<DataSource> mDataSource;
bool mHaveMetadata; bool mHaveMetadata;
Track *mFirstTrack, *mLastTrack; Track *mFirstTrack, *mLastTrack;
@@ -58,7 +60,8 @@ private:
MPEG4Extractor &operator=(const MPEG4Extractor &); MPEG4Extractor &operator=(const MPEG4Extractor &);
}; };
bool SniffMPEG4(DataSource *source, String8 *mimeType, float *confidence); bool SniffMPEG4(
const sp<DataSource> &source, String8 *mimeType, float *confidence);
} // namespace android } // namespace android

View File

@@ -30,13 +30,12 @@ class MediaBuffer;
class MediaSource; class MediaSource;
class MetaData; class MetaData;
class MPEG4Writer { class MPEG4Writer : public RefBase {
public: public:
MPEG4Writer(const char *filename); MPEG4Writer(const char *filename);
~MPEG4Writer();
// Caller retains ownership of both meta and source. // Caller retains ownership of both meta and source.
void addSource(const sp<MetaData> &meta, MediaSource *source); void addSource(const sp<MetaData> &meta, const sp<MediaSource> &source);
void start(); void start();
void stop(); void stop();
@@ -50,6 +49,9 @@ public:
void write(const void *data, size_t size); void write(const void *data, size_t size);
void endBox(); void endBox();
protected:
virtual ~MPEG4Writer();
private: private:
class Track; class Track;

View File

@@ -75,6 +75,8 @@ public:
// MetaData. // MetaData.
MediaBuffer *clone(); MediaBuffer *clone();
int refcount() const;
protected: protected:
virtual ~MediaBuffer(); virtual ~MediaBuffer();
@@ -102,8 +104,6 @@ private:
void setNextBuffer(MediaBuffer *buffer); void setNextBuffer(MediaBuffer *buffer);
MediaBuffer *nextBuffer(); MediaBuffer *nextBuffer();
int refcount() const;
MediaBuffer(const MediaBuffer &); MediaBuffer(const MediaBuffer &);
MediaBuffer &operator=(const MediaBuffer &); MediaBuffer &operator=(const MediaBuffer &);
}; };

View File

@@ -0,0 +1,18 @@
#ifndef MEDIA_DEBUG_H_
#define MEDIA_DEBUG_H_
#define LITERAL_TO_STRING_INTERNAL(x) #x
#define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)
#define CHECK_EQ(x,y) \
LOG_ALWAYS_FATAL_IF( \
(x) != (y), \
__FILE__ ":" LITERAL_TO_STRING(__LINE__) " " #x " != " #y)
#define CHECK(x) \
LOG_ALWAYS_FATAL_IF( \
!(x), \
__FILE__ ":" LITERAL_TO_STRING(__LINE__) " " #x)
#endif // MEDIA_DEBUG_H_

View File

@@ -26,18 +26,18 @@ class DataSource;
class MediaSource; class MediaSource;
class MetaData; class MetaData;
class MediaExtractor { class MediaExtractor : public RefBase {
public: public:
static MediaExtractor *Create(DataSource *source, const char *mime = NULL); static sp<MediaExtractor> Create(
const sp<DataSource> &source, const char *mime = NULL);
virtual ~MediaExtractor() {} virtual size_t countTracks() = 0;
virtual sp<MediaSource> getTrack(size_t index) = 0;
virtual status_t countTracks(int *num_tracks) = 0; virtual sp<MetaData> getTrackMetaData(size_t index) = 0;
virtual status_t getTrack(int index, MediaSource **source) = 0;
virtual sp<MetaData> getTrackMetaData(int index) = 0;
protected: protected:
MediaExtractor() {} MediaExtractor() {}
virtual ~MediaExtractor() {}
private: private:
MediaExtractor(const MediaExtractor &); MediaExtractor(const MediaExtractor &);

View File

@@ -35,7 +35,6 @@ class MediaBuffer;
class MediaSource; class MediaSource;
class MemoryHeapPmem; class MemoryHeapPmem;
class MetaData; class MetaData;
class OMXDecoder;
class Surface; class Surface;
class TimeSource; class TimeSource;
@@ -71,16 +70,16 @@ private:
OMXClient mClient; OMXClient mClient;
MediaExtractor *mExtractor; sp<MediaExtractor> mExtractor;
TimeSource *mTimeSource; TimeSource *mTimeSource;
MediaSource *mAudioSource; sp<MediaSource> mAudioSource;
OMXDecoder *mAudioDecoder; sp<MediaSource> mAudioDecoder;
AudioPlayer *mAudioPlayer; AudioPlayer *mAudioPlayer;
MediaSource *mVideoSource; sp<MediaSource> mVideoSource;
MediaSource *mVideoDecoder; sp<MediaSource> mVideoDecoder;
int32_t mVideoWidth, mVideoHeight; int32_t mVideoWidth, mVideoHeight;
int64_t mVideoPosition; int64_t mVideoPosition;
@@ -103,16 +102,13 @@ private:
bool mSeeking; bool mSeeking;
int64_t mSeekTimeUs; int64_t mSeekTimeUs;
size_t mFrameSize;
bool mUseSoftwareColorConversion;
void init(); void init();
static void *VideoWrapper(void *me); static void *VideoWrapper(void *me);
void videoEntry(); void videoEntry();
void setAudioSource(MediaSource *source); void setAudioSource(const sp<MediaSource> &source);
void setVideoSource(MediaSource *source); void setVideoSource(const sp<MediaSource> &source);
MediaSource *makeShoutcastSource(const char *path); MediaSource *makeShoutcastSource(const char *path);

View File

@@ -27,9 +27,8 @@ namespace android {
class MediaBuffer; class MediaBuffer;
class MetaData; class MetaData;
struct MediaSource { struct MediaSource : public RefBase {
MediaSource(); MediaSource();
virtual ~MediaSource();
// To be called before any other methods on this object, except // To be called before any other methods on this object, except
// getFormat(). // getFormat().
@@ -81,6 +80,9 @@ struct MediaSource {
int64_t mLatenessUs; int64_t mLatenessUs;
}; };
protected:
virtual ~MediaSource();
private: private:
MediaSource(const MediaSource &); MediaSource(const MediaSource &);
MediaSource &operator=(const MediaSource &); MediaSource &operator=(const MediaSource &);

View File

@@ -0,0 +1,190 @@
/*
* 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 OMX_CODEC_H_
#define OMX_CODEC_H_
#include <media/IOMX.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaSource.h>
#include <utils/threads.h>
namespace android {
class MemoryDealer;
struct OMXCodecObserver;
struct OMXCodec : public MediaSource,
public MediaBufferObserver {
static sp<OMXCodec> Create(
const sp<IOMX> &omx,
const sp<MetaData> &meta, bool createEncoder,
const sp<MediaSource> &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);
void on_message(const omx_message &msg);
// from MediaBufferObserver
virtual void signalBufferReturned(MediaBuffer *buffer);
protected:
virtual ~OMXCodec();
private:
enum State {
DEAD,
LOADED,
LOADED_TO_IDLE,
IDLE_TO_EXECUTING,
EXECUTING,
EXECUTING_TO_IDLE,
IDLE_TO_LOADED,
RECONFIGURING,
ERROR
};
enum {
kPortIndexInput = 0,
kPortIndexOutput = 1
};
enum PortStatus {
ENABLED,
DISABLING,
DISABLED,
ENABLING,
SHUTTING_DOWN,
};
enum Quirks {
kNeedsFlushBeforeDisable = 1,
kWantsRawNALFrames = 2,
kRequiresLoadedToIdleAfterAllocation = 4,
kRequiresAllocateBufferOnInputPorts = 8,
};
struct BufferInfo {
IOMX::buffer_id mBuffer;
bool mOwnedByComponent;
sp<IMemory> mMem;
MediaBuffer *mMediaBuffer;
};
struct CodecSpecificData {
size_t mSize;
uint8_t mData[1];
};
sp<IOMX> mOMX;
IOMX::node_id mNode;
sp<OMXCodecObserver> mObserver;
uint32_t mQuirks;
bool mIsEncoder;
char *mMIME;
char *mComponentName;
sp<MetaData> mOutputFormat;
sp<MediaSource> mSource;
Vector<CodecSpecificData *> mCodecSpecificData;
size_t mCodecSpecificDataIndex;
sp<MemoryDealer> mDealer;
State mState;
Vector<BufferInfo> mPortBuffers[2];
PortStatus mPortStatus[2];
bool mSignalledEOS;
bool mNoMoreOutputData;
int64_t mSeekTimeUs;
Mutex mLock;
Condition mAsyncCompletion;
// A list of indices into mPortStatus[kPortIndexOutput] filled with data.
List<size_t> mFilledBuffers;
Condition mBufferFilled;
OMXCodec(const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
bool isEncoder, const char *mime, const char *componentName,
const sp<MediaSource> &source);
void addCodecSpecificData(const void *data, size_t size);
void clearCodecSpecificData();
void setAMRFormat();
void setAACFormat();
status_t setVideoPortFormatType(
OMX_U32 portIndex,
OMX_VIDEO_CODINGTYPE compressionFormat,
OMX_COLOR_FORMATTYPE colorFormat);
void setVideoInputFormat(
const char *mime, OMX_U32 width, OMX_U32 height);
void setVideoOutputFormat(
const char *mime, OMX_U32 width, OMX_U32 height);
void setImageOutputFormat(
OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height);
status_t allocateBuffers();
status_t allocateBuffersOnPort(OMX_U32 portIndex);
status_t freeBuffersOnPort(
OMX_U32 portIndex, bool onlyThoseWeOwn = false);
void drainInputBuffer(IOMX::buffer_id buffer);
void fillOutputBuffer(IOMX::buffer_id buffer);
void drainInputBuffer(BufferInfo *info);
void fillOutputBuffer(BufferInfo *info);
void drainInputBuffers();
void fillOutputBuffers();
void flushPortAsync(OMX_U32 portIndex);
void disablePortAsync(OMX_U32 portIndex);
void enablePortAsync(OMX_U32 portIndex);
static size_t countBuffersWeOwn(const Vector<BufferInfo> &buffers);
static bool isIntermediateState(State state);
void onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
void onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data);
void onStateChange(OMX_STATETYPE newState);
void onPortSettingsChanged(OMX_U32 portIndex);
void setState(State newState);
status_t init();
void initOutputFormat(const sp<MetaData> &inputFormat);
void dumpPortStatus(OMX_U32 portIndex);
OMXCodec(const OMXCodec &);
OMXCodec &operator=(const OMXCodec &);
};
} // namespace android
#endif // OMX_CODEC_H_

View File

@@ -36,14 +36,10 @@ class OMXDecoder : public MediaSource,
public OMXObserver, public OMXObserver,
public MediaBufferObserver { public MediaBufferObserver {
public: public:
static OMXDecoder *Create( static sp<OMXDecoder> Create(
OMXClient *client, const sp<MetaData> &data, OMXClient *client, const sp<MetaData> &data,
bool createEncoder = false); bool createEncoder,
const sp<MediaSource> &source);
virtual ~OMXDecoder();
// Caller retains ownership of "source".
void setSource(MediaSource *source);
virtual status_t start(MetaData *params = NULL); virtual status_t start(MetaData *params = NULL);
virtual status_t stop(); virtual status_t stop();
@@ -61,6 +57,9 @@ public:
// from MediaBufferObserver // from MediaBufferObserver
virtual void signalBufferReturned(MediaBuffer *buffer); virtual void signalBufferReturned(MediaBuffer *buffer);
protected:
virtual ~OMXDecoder();
private: private:
enum { enum {
kPortIndexInput = 0, kPortIndexInput = 0,
@@ -97,7 +96,7 @@ private:
bool mIsEncoder; bool mIsEncoder;
uint32_t mQuirks; uint32_t mQuirks;
MediaSource *mSource; sp<MediaSource> mSource;
sp<MetaData> mOutputFormat; sp<MetaData> mOutputFormat;
Mutex mLock; Mutex mLock;
@@ -135,7 +134,8 @@ private:
OMXDecoder(OMXClient *client, IOMX::node_id node, OMXDecoder(OMXClient *client, IOMX::node_id node,
const char *mime, const char *codec, const char *mime, const char *codec,
bool is_encoder, bool is_encoder,
uint32_t quirks); uint32_t quirks,
const sp<MediaSource> &source);
void setPortStatus(OMX_U32 port_index, PortStatus status); void setPortStatus(OMX_U32 port_index, PortStatus status);
PortStatus getPortStatus(OMX_U32 port_index) const; PortStatus getPortStatus(OMX_U32 port_index) const;

View File

@@ -22,17 +22,16 @@
#include <stdint.h> #include <stdint.h>
#include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaErrors.h>
#include <utils/RefBase.h>
#include <utils/threads.h> #include <utils/threads.h>
namespace android { namespace android {
class DataSource; class DataSource;
class SampleTable { class SampleTable : public RefBase {
public: public:
// Caller retains ownership of "source". SampleTable(const sp<DataSource> &source);
SampleTable(DataSource *source);
~SampleTable();
// type can be 'stco' or 'co64'. // type can be 'stco' or 'co64'.
status_t setChunkOffsetParams( status_t setChunkOffsetParams(
@@ -76,8 +75,11 @@ public:
status_t findClosestSyncSample( status_t findClosestSyncSample(
uint32_t start_sample_index, uint32_t *sample_index); uint32_t start_sample_index, uint32_t *sample_index);
protected:
~SampleTable();
private: private:
DataSource *mDataSource; sp<DataSource> mDataSource;
Mutex mLock; Mutex mLock;
off_t mChunkOffsetOffset; off_t mChunkOffsetOffset;

View File

@@ -18,6 +18,8 @@ enum {
SEND_COMMAND, SEND_COMMAND,
GET_PARAMETER, GET_PARAMETER,
SET_PARAMETER, SET_PARAMETER,
GET_CONFIG,
SET_CONFIG,
USE_BUFFER, USE_BUFFER,
ALLOC_BUFFER, ALLOC_BUFFER,
ALLOC_BUFFER_WITH_BACKUP, ALLOC_BUFFER_WITH_BACKUP,
@@ -25,6 +27,7 @@ enum {
OBSERVE_NODE, OBSERVE_NODE,
FILL_BUFFER, FILL_BUFFER,
EMPTY_BUFFER, EMPTY_BUFFER,
GET_EXTENSION_INDEX,
CREATE_RENDERER, CREATE_RENDERER,
OBSERVER_ON_MSG, OBSERVER_ON_MSG,
RENDERER_RENDER, RENDERER_RENDER,
@@ -147,6 +150,41 @@ public:
return reply.readInt32(); return reply.readInt32();
} }
virtual status_t get_config(
node_id node, OMX_INDEXTYPE index,
void *params, size_t size) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
writeVoidStar(node, &data);
data.writeInt32(index);
data.writeInt32(size);
data.write(params, size);
remote()->transact(GET_CONFIG, data, &reply);
status_t err = reply.readInt32();
if (err != OK) {
return err;
}
reply.read(params, size);
return OK;
}
virtual status_t set_config(
node_id node, OMX_INDEXTYPE index,
const void *params, size_t size) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
writeVoidStar(node, &data);
data.writeInt32(index);
data.writeInt32(size);
data.write(params, size);
remote()->transact(SET_CONFIG, data, &reply);
return reply.readInt32();
}
virtual status_t use_buffer( virtual status_t use_buffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params, node_id node, OMX_U32 port_index, const sp<IMemory> &params,
buffer_id *buffer) { buffer_id *buffer) {
@@ -260,6 +298,27 @@ public:
remote()->transact(EMPTY_BUFFER, data, &reply, IBinder::FLAG_ONEWAY); remote()->transact(EMPTY_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
} }
virtual status_t get_extension_index(
node_id node,
const char *parameter_name,
OMX_INDEXTYPE *index) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
writeVoidStar(node, &data);
data.writeCString(parameter_name);
remote()->transact(GET_EXTENSION_INDEX, data, &reply);
status_t err = reply.readInt32();
if (err == OK) {
*index = static_cast<OMX_INDEXTYPE>(reply.readInt32());
} else {
*index = OMX_IndexComponentStartUnused;
}
return err;
}
virtual sp<IOMXRenderer> createRenderer( virtual sp<IOMXRenderer> createRenderer(
const sp<ISurface> &surface, const sp<ISurface> &surface,
const char *componentName, const char *componentName,
@@ -394,6 +453,48 @@ status_t BnOMX::onTransact(
return NO_ERROR; return NO_ERROR;
} }
case GET_CONFIG:
{
CHECK_INTERFACE(IOMX, data, reply);
node_id node = readVoidStar(&data);
OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
size_t size = data.readInt32();
// XXX I am not happy with this but Parcel::readInplace didn't work.
void *params = malloc(size);
data.read(params, size);
status_t err = get_config(node, index, params, size);
reply->writeInt32(err);
if (err == OK) {
reply->write(params, size);
}
free(params);
params = NULL;
return NO_ERROR;
}
case SET_CONFIG:
{
CHECK_INTERFACE(IOMX, data, reply);
node_id node = readVoidStar(&data);
OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
size_t size = data.readInt32();
void *params = const_cast<void *>(data.readInplace(size));
reply->writeInt32(set_config(node, index, params, size));
return NO_ERROR;
}
case USE_BUFFER: case USE_BUFFER:
{ {
CHECK_INTERFACE(IOMX, data, reply); CHECK_INTERFACE(IOMX, data, reply);
@@ -508,6 +609,25 @@ status_t BnOMX::onTransact(
return NO_ERROR; return NO_ERROR;
} }
case GET_EXTENSION_INDEX:
{
CHECK_INTERFACE(IOMX, data, reply);
node_id node = readVoidStar(&data);
const char *parameter_name = data.readCString();
OMX_INDEXTYPE index;
status_t err = get_extension_index(node, parameter_name, &index);
reply->writeInt32(err);
if (err == OK) {
reply->writeInt32(index);
}
return OK;
}
case CREATE_RENDERER: case CREATE_RENDERER:
{ {
CHECK_INTERFACE(IOMX, data, reply); CHECK_INTERFACE(IOMX, data, reply);

View File

@@ -17,6 +17,7 @@ LOCAL_SRC_FILES:= \
MediaSource.cpp \ MediaSource.cpp \
MetaData.cpp \ MetaData.cpp \
MmapSource.cpp \ MmapSource.cpp \
OMXCodec.cpp \
SampleTable.cpp \ SampleTable.cpp \
ShoutcastSource.cpp \ ShoutcastSource.cpp \
TimeSource.cpp \ TimeSource.cpp \

View File

@@ -28,8 +28,7 @@
namespace android { namespace android {
AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink) AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink)
: mSource(NULL), : mAudioTrack(NULL),
mAudioTrack(NULL),
mInputBuffer(NULL), mInputBuffer(NULL),
mSampleRate(0), mSampleRate(0),
mLatencyUs(0), mLatencyUs(0),
@@ -48,7 +47,7 @@ AudioPlayer::~AudioPlayer() {
} }
} }
void AudioPlayer::setSource(MediaSource *source) { void AudioPlayer::setSource(const sp<MediaSource> &source) {
assert(mSource == NULL); assert(mSource == NULL);
mSource = source; mSource = source;
} }

View File

@@ -25,7 +25,7 @@
namespace android { namespace android {
CachingDataSource::CachingDataSource( CachingDataSource::CachingDataSource(
DataSource *source, size_t pageSize, int numPages) const sp<DataSource> &source, size_t pageSize, int numPages)
: mSource(source), : mSource(source),
mData(malloc(pageSize * numPages)), mData(malloc(pageSize * numPages)),
mPageSize(pageSize), mPageSize(pageSize),
@@ -61,9 +61,6 @@ CachingDataSource::~CachingDataSource() {
free(mData); free(mData);
mData = NULL; mData = NULL;
delete mSource;
mSource = NULL;
} }
status_t CachingDataSource::InitCheck() const { status_t CachingDataSource::InitCheck() const {
@@ -78,7 +75,7 @@ ssize_t CachingDataSource::read_at(off_t offset, void *data, size_t size) {
Page *page = mFirst; Page *page = mFirst;
while (page != NULL) { while (page != NULL) {
if (page->mOffset >= 0 && offset >= page->mOffset if (page->mOffset >= 0 && offset >= page->mOffset
&& offset < page->mOffset + page->mLength) { && offset < page->mOffset + (off_t)page->mLength) {
break; break;
} }
page = page->mNext; page = page->mNext;
@@ -102,7 +99,7 @@ ssize_t CachingDataSource::read_at(off_t offset, void *data, size_t size) {
return n; return n;
} }
if (offset >= page->mOffset + page->mLength) { if (offset >= page->mOffset + (off_t)page->mLength) {
break; break;
} }
} else { } else {

View File

@@ -22,6 +22,19 @@
namespace android { namespace android {
bool DataSource::getUInt16(off_t offset, uint16_t *x) {
*x = 0;
uint8_t byte[2];
if (read_at(offset, byte, 2) != 2) {
return false;
}
*x = (byte[0] << 8) | byte[1];
return true;
}
status_t DataSource::getSize(off_t *size) { status_t DataSource::getSize(off_t *size) {
*size = 0; *size = 0;

View File

@@ -165,7 +165,7 @@ static bool get_mp3_frame_size(
} }
static bool Resync( static bool Resync(
DataSource *source, uint32_t match_header, const sp<DataSource> &source, uint32_t match_header,
off_t *inout_pos, uint32_t *out_header) { off_t *inout_pos, uint32_t *out_header) {
// Everything must match except for // Everything must match except for
// protection, bitrate, padding, private bits and mode extension. // protection, bitrate, padding, private bits and mode extension.
@@ -281,11 +281,9 @@ static bool Resync(
class MP3Source : public MediaSource { class MP3Source : public MediaSource {
public: public:
MP3Source( MP3Source(
const sp<MetaData> &meta, DataSource *source, const sp<MetaData> &meta, const sp<DataSource> &source,
off_t first_frame_pos, uint32_t fixed_header); off_t first_frame_pos, uint32_t fixed_header);
virtual ~MP3Source();
virtual status_t start(MetaData *params = NULL); virtual status_t start(MetaData *params = NULL);
virtual status_t stop(); virtual status_t stop();
@@ -294,9 +292,12 @@ public:
virtual status_t read( virtual status_t read(
MediaBuffer **buffer, const ReadOptions *options = NULL); MediaBuffer **buffer, const ReadOptions *options = NULL);
protected:
virtual ~MP3Source();
private: private:
sp<MetaData> mMeta; sp<MetaData> mMeta;
DataSource *mDataSource; sp<DataSource> mDataSource;
off_t mFirstFramePos; off_t mFirstFramePos;
uint32_t mFixedHeader; uint32_t mFixedHeader;
off_t mCurrentPos; off_t mCurrentPos;
@@ -309,7 +310,7 @@ private:
MP3Source &operator=(const MP3Source &); MP3Source &operator=(const MP3Source &);
}; };
MP3Extractor::MP3Extractor(DataSource *source) MP3Extractor::MP3Extractor(const sp<DataSource> &source)
: mDataSource(source), : mDataSource(source),
mFirstFramePos(-1), mFirstFramePos(-1),
mFixedHeader(0) { mFixedHeader(0) {
@@ -347,28 +348,22 @@ MP3Extractor::MP3Extractor(DataSource *source)
} }
MP3Extractor::~MP3Extractor() { MP3Extractor::~MP3Extractor() {
delete mDataSource;
mDataSource = NULL;
} }
status_t MP3Extractor::countTracks(int *num_tracks) { size_t MP3Extractor::countTracks() {
*num_tracks = mFirstFramePos < 0 ? 0 : 1; return (mFirstFramePos < 0) ? 0 : 1;
return OK;
} }
status_t MP3Extractor::getTrack(int index, MediaSource **source) { sp<MediaSource> MP3Extractor::getTrack(size_t index) {
if (mFirstFramePos < 0 || index != 0) { if (mFirstFramePos < 0 || index != 0) {
return ERROR_OUT_OF_RANGE; return NULL;
} }
*source = new MP3Source( return new MP3Source(
mMeta, mDataSource, mFirstFramePos, mFixedHeader); mMeta, mDataSource, mFirstFramePos, mFixedHeader);
return OK;
} }
sp<MetaData> MP3Extractor::getTrackMetaData(int index) { sp<MetaData> MP3Extractor::getTrackMetaData(size_t index) {
if (mFirstFramePos < 0 || index != 0) { if (mFirstFramePos < 0 || index != 0) {
return NULL; return NULL;
} }
@@ -379,7 +374,7 @@ sp<MetaData> MP3Extractor::getTrackMetaData(int index) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
MP3Source::MP3Source( MP3Source::MP3Source(
const sp<MetaData> &meta, DataSource *source, const sp<MetaData> &meta, const sp<DataSource> &source,
off_t first_frame_pos, uint32_t fixed_header) off_t first_frame_pos, uint32_t fixed_header)
: mMeta(meta), : mMeta(meta),
mDataSource(source), mDataSource(source),
@@ -509,7 +504,8 @@ status_t MP3Source::read(
return OK; return OK;
} }
bool SniffMP3(DataSource *source, String8 *mimeType, float *confidence) { bool SniffMP3(
const sp<DataSource> &source, String8 *mimeType, float *confidence) {
off_t pos = 0; off_t pos = 0;
uint32_t header; uint32_t header;
if (!Resync(source, 0, &pos, &header)) { if (!Resync(source, 0, &pos, &header)) {

View File

@@ -42,10 +42,9 @@ namespace android {
class MPEG4Source : public MediaSource { class MPEG4Source : public MediaSource {
public: public:
// Caller retains ownership of both "dataSource" and "sampleTable". // Caller retains ownership of both "dataSource" and "sampleTable".
MPEG4Source(const sp<MetaData> &format, DataSource *dataSource, MPEG4Source(const sp<MetaData> &format,
SampleTable *sampleTable); const sp<DataSource> &dataSource,
const sp<SampleTable> &sampleTable);
virtual ~MPEG4Source();
virtual status_t start(MetaData *params = NULL); virtual status_t start(MetaData *params = NULL);
virtual status_t stop(); virtual status_t stop();
@@ -55,11 +54,14 @@ public:
virtual status_t read( virtual status_t read(
MediaBuffer **buffer, const ReadOptions *options = NULL); MediaBuffer **buffer, const ReadOptions *options = NULL);
protected:
virtual ~MPEG4Source();
private: private:
sp<MetaData> mFormat; sp<MetaData> mFormat;
DataSource *mDataSource; sp<DataSource> mDataSource;
int32_t mTimescale; int32_t mTimescale;
SampleTable *mSampleTable; sp<SampleTable> mSampleTable;
uint32_t mCurrentSampleIndex; uint32_t mCurrentSampleIndex;
bool mIsAVC; bool mIsAVC;
@@ -141,7 +143,7 @@ static const char *const FourCC2MIME(uint32_t fourcc) {
} }
} }
MPEG4Extractor::MPEG4Extractor(DataSource *source) MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
: mDataSource(source), : mDataSource(source),
mHaveMetadata(false), mHaveMetadata(false),
mFirstTrack(NULL), mFirstTrack(NULL),
@@ -153,39 +155,29 @@ MPEG4Extractor::~MPEG4Extractor() {
while (track) { while (track) {
Track *next = track->next; Track *next = track->next;
delete track->sampleTable;
track->sampleTable = NULL;
delete track; delete track;
track = next; track = next;
} }
mFirstTrack = mLastTrack = NULL; mFirstTrack = mLastTrack = NULL;
delete mDataSource;
mDataSource = NULL;
} }
status_t MPEG4Extractor::countTracks(int *num_tracks) { size_t MPEG4Extractor::countTracks() {
status_t err; status_t err;
if ((err = readMetaData()) != OK) { if ((err = readMetaData()) != OK) {
return err; return 0;
} }
*num_tracks = 0; size_t n = 0;
Track *track = mFirstTrack; Track *track = mFirstTrack;
while (track) { while (track) {
++*num_tracks; ++n;
track = track->next; track = track->next;
} }
return OK; return n;
} }
sp<MetaData> MPEG4Extractor::getTrackMetaData(int index) { sp<MetaData> MPEG4Extractor::getTrackMetaData(size_t index) {
if (index < 0) {
return NULL;
}
status_t err; status_t err;
if ((err = readMetaData()) != OK) { if ((err = readMetaData()) != OK) {
return NULL; return NULL;
@@ -701,39 +693,32 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
return OK; return OK;
} }
status_t MPEG4Extractor::getTrack(int index, MediaSource **source) { sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
*source = NULL;
if (index < 0) {
return ERROR_OUT_OF_RANGE;
}
status_t err; status_t err;
if ((err = readMetaData()) != OK) { if ((err = readMetaData()) != OK) {
return err; return NULL;
} }
Track *track = mFirstTrack; Track *track = mFirstTrack;
while (index > 0) { while (index > 0) {
if (track == NULL) { if (track == NULL) {
return ERROR_OUT_OF_RANGE; return NULL;
} }
track = track->next; track = track->next;
--index; --index;
} }
*source = new MPEG4Source( return new MPEG4Source(
track->meta, mDataSource, track->sampleTable); track->meta, mDataSource, track->sampleTable);
return OK;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
MPEG4Source::MPEG4Source( MPEG4Source::MPEG4Source(
const sp<MetaData> &format, const sp<MetaData> &format,
DataSource *dataSource, SampleTable *sampleTable) const sp<DataSource> &dataSource,
const sp<SampleTable> &sampleTable)
: mFormat(format), : mFormat(format),
mDataSource(dataSource), mDataSource(dataSource),
mTimescale(0), mTimescale(0),
@@ -935,7 +920,8 @@ status_t MPEG4Source::read(
return OK; return OK;
} }
bool SniffMPEG4(DataSource *source, String8 *mimeType, float *confidence) { bool SniffMPEG4(
const sp<DataSource> &source, String8 *mimeType, float *confidence) {
uint8_t header[8]; uint8_t header[8];
ssize_t n = source->read_at(4, header, sizeof(header)); ssize_t n = source->read_at(4, header, sizeof(header));

View File

@@ -32,7 +32,8 @@ namespace android {
class MPEG4Writer::Track { class MPEG4Writer::Track {
public: public:
Track(MPEG4Writer *owner, const sp<MetaData> &meta, MediaSource *source); Track(MPEG4Writer *owner,
const sp<MetaData> &meta, const sp<MediaSource> &source);
~Track(); ~Track();
void start(); void start();
@@ -44,7 +45,7 @@ public:
private: private:
MPEG4Writer *mOwner; MPEG4Writer *mOwner;
sp<MetaData> mMeta; sp<MetaData> mMeta;
MediaSource *mSource; sp<MediaSource> mSource;
volatile bool mDone; volatile bool mDone;
pthread_t mThread; pthread_t mThread;
@@ -83,7 +84,8 @@ MPEG4Writer::~MPEG4Writer() {
mTracks.clear(); mTracks.clear();
} }
void MPEG4Writer::addSource(const sp<MetaData> &meta, MediaSource *source) { void MPEG4Writer::addSource(
const sp<MetaData> &meta, const sp<MediaSource> &source) {
Track *track = new Track(this, meta, source); Track *track = new Track(this, meta, source);
mTracks.push_back(track); mTracks.push_back(track);
} }
@@ -255,7 +257,8 @@ void MPEG4Writer::write(const void *data, size_t size) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
MPEG4Writer::Track::Track( MPEG4Writer::Track::Track(
MPEG4Writer *owner, const sp<MetaData> &meta, MediaSource *source) MPEG4Writer *owner,
const sp<MetaData> &meta, const sp<MediaSource> &source)
: mOwner(owner), : mOwner(owner),
mMeta(meta), mMeta(meta),
mSource(source), mSource(source),

View File

@@ -27,7 +27,8 @@
namespace android { namespace android {
// static // static
MediaExtractor *MediaExtractor::Create(DataSource *source, const char *mime) { sp<MediaExtractor> MediaExtractor::Create(
const sp<DataSource> &source, const char *mime) {
String8 tmp; String8 tmp;
if (mime == NULL) { if (mime == NULL) {
float confidence; float confidence;

View File

@@ -34,32 +34,28 @@
#include <media/stagefright/MediaPlayerImpl.h> #include <media/stagefright/MediaPlayerImpl.h>
#include <media/stagefright/MetaData.h> #include <media/stagefright/MetaData.h>
#include <media/stagefright/MmapSource.h> #include <media/stagefright/MmapSource.h>
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/OMXDecoder.h> #include <media/stagefright/OMXDecoder.h>
#include <media/stagefright/ShoutcastSource.h> #include <media/stagefright/ShoutcastSource.h>
#include <media/stagefright/TimeSource.h> #include <media/stagefright/TimeSource.h>
#include <ui/PixelFormat.h> #include <ui/PixelFormat.h>
#include <ui/Surface.h> #include <ui/Surface.h>
#define USE_OMX_CODEC 1
namespace android { namespace android {
MediaPlayerImpl::MediaPlayerImpl(const char *uri) MediaPlayerImpl::MediaPlayerImpl(const char *uri)
: mInitCheck(NO_INIT), : mInitCheck(NO_INIT),
mExtractor(NULL),
mTimeSource(NULL), mTimeSource(NULL),
mAudioSource(NULL),
mAudioDecoder(NULL),
mAudioPlayer(NULL), mAudioPlayer(NULL),
mVideoSource(NULL),
mVideoDecoder(NULL),
mVideoWidth(0), mVideoWidth(0),
mVideoHeight(0), mVideoHeight(0),
mVideoPosition(0), mVideoPosition(0),
mDuration(0), mDuration(0),
mPlaying(false), mPlaying(false),
mPaused(false), mPaused(false),
mSeeking(false), mSeeking(false) {
mFrameSize(0),
mUseSoftwareColorConversion(false) {
LOGI("MediaPlayerImpl(%s)", uri); LOGI("MediaPlayerImpl(%s)", uri);
DataSource::RegisterDefaultSniffers(); DataSource::RegisterDefaultSniffers();
@@ -78,7 +74,7 @@ MediaPlayerImpl::MediaPlayerImpl(const char *uri)
mVideoDecoder = CameraSource::Create(); mVideoDecoder = CameraSource::Create();
#endif #endif
} else { } else {
DataSource *source = NULL; sp<DataSource> source;
if (!strncasecmp("file://", uri, 7)) { if (!strncasecmp("file://", uri, 7)) {
source = new MmapSource(uri + 7); source = new MmapSource(uri + 7);
} else if (!strncasecmp("http://", uri, 7)) { } else if (!strncasecmp("http://", uri, 7)) {
@@ -103,22 +99,15 @@ MediaPlayerImpl::MediaPlayerImpl(const char *uri)
MediaPlayerImpl::MediaPlayerImpl(int fd, int64_t offset, int64_t length) MediaPlayerImpl::MediaPlayerImpl(int fd, int64_t offset, int64_t length)
: mInitCheck(NO_INIT), : mInitCheck(NO_INIT),
mExtractor(NULL),
mTimeSource(NULL), mTimeSource(NULL),
mAudioSource(NULL),
mAudioDecoder(NULL),
mAudioPlayer(NULL), mAudioPlayer(NULL),
mVideoSource(NULL),
mVideoDecoder(NULL),
mVideoWidth(0), mVideoWidth(0),
mVideoHeight(0), mVideoHeight(0),
mVideoPosition(0), mVideoPosition(0),
mDuration(0), mDuration(0),
mPlaying(false), mPlaying(false),
mPaused(false), mPaused(false),
mSeeking(false), mSeeking(false) {
mFrameSize(0),
mUseSoftwareColorConversion(false) {
LOGI("MediaPlayerImpl(%d, %lld, %lld)", fd, offset, length); LOGI("MediaPlayerImpl(%d, %lld, %lld)", fd, offset, length);
DataSource::RegisterDefaultSniffers(); DataSource::RegisterDefaultSniffers();
@@ -148,23 +137,6 @@ MediaPlayerImpl::~MediaPlayerImpl() {
stop(); stop();
setSurface(NULL); setSurface(NULL);
LOGV("Shutting down audio.");
delete mAudioDecoder;
mAudioDecoder = NULL;
delete mAudioSource;
mAudioSource = NULL;
LOGV("Shutting down video.");
delete mVideoDecoder;
mVideoDecoder = NULL;
delete mVideoSource;
mVideoSource = NULL;
delete mExtractor;
mExtractor = NULL;
if (mInitCheck == OK) { if (mInitCheck == OK) {
mClient.disconnect(); mClient.disconnect();
} }
@@ -384,12 +356,11 @@ void MediaPlayerImpl::displayOrDiscardFrame(
void MediaPlayerImpl::init() { void MediaPlayerImpl::init() {
if (mExtractor != NULL) { if (mExtractor != NULL) {
int num_tracks; size_t num_tracks = mExtractor->countTracks();
assert(mExtractor->countTracks(&num_tracks) == OK);
mDuration = 0; mDuration = 0;
for (int i = 0; i < num_tracks; ++i) { for (size_t i = 0; i < num_tracks; ++i) {
const sp<MetaData> meta = mExtractor->getTrackMetaData(i); const sp<MetaData> meta = mExtractor->getTrackMetaData(i);
assert(meta != NULL); assert(meta != NULL);
@@ -411,10 +382,7 @@ void MediaPlayerImpl::init() {
continue; continue;
} }
MediaSource *source; sp<MediaSource> source = mExtractor->getTrack(i);
if (mExtractor->getTrack(i, &source) != OK) {
continue;
}
int32_t units, scale; int32_t units, scale;
if (meta->findInt32(kKeyDuration, &units) if (meta->findInt32(kKeyDuration, &units)
@@ -434,17 +402,22 @@ void MediaPlayerImpl::init() {
} }
} }
void MediaPlayerImpl::setAudioSource(MediaSource *source) { void MediaPlayerImpl::setAudioSource(const sp<MediaSource> &source) {
LOGI("setAudioSource"); LOGI("setAudioSource");
mAudioSource = source; mAudioSource = source;
sp<MetaData> meta = source->getFormat(); sp<MetaData> meta = source->getFormat();
mAudioDecoder = OMXDecoder::Create(&mClient, meta); #if !USE_OMX_CODEC
mAudioDecoder->setSource(source); mAudioDecoder = OMXDecoder::Create(
&mClient, meta, false /* createEncoder */, source);
#else
mAudioDecoder = OMXCodec::Create(
mClient.interface(), meta, false /* createEncoder */, source);
#endif
} }
void MediaPlayerImpl::setVideoSource(MediaSource *source) { void MediaPlayerImpl::setVideoSource(const sp<MediaSource> &source) {
LOGI("setVideoSource"); LOGI("setVideoSource");
mVideoSource = source; mVideoSource = source;
@@ -456,8 +429,13 @@ void MediaPlayerImpl::setVideoSource(MediaSource *source) {
success = meta->findInt32(kKeyHeight, &mVideoHeight); success = meta->findInt32(kKeyHeight, &mVideoHeight);
assert(success); assert(success);
mVideoDecoder = OMXDecoder::Create(&mClient, meta); #if !USE_OMX_CODEC
((OMXDecoder *)mVideoDecoder)->setSource(source); mVideoDecoder = OMXDecoder::Create(
&mClient, meta, false /* createEncoder */, source);
#else
mVideoDecoder = OMXCodec::Create(
mClient.interface(), meta, false /* createEncoder */, source);
#endif
if (mISurface.get() != NULL || mSurface.get() != NULL) { if (mISurface.get() != NULL || mSurface.get() != NULL) {
depopulateISurface(); depopulateISurface();

View File

@@ -132,7 +132,7 @@ bool OMXClient::onOMXMessage(const omx_message &msg) {
} }
Mutex::Autolock autoLock(mLock); Mutex::Autolock autoLock(mLock);
ssize_t index = mObservers.indexOfKey(msg.u.buffer_data.node); ssize_t index = mObservers.indexOfKey(msg.node);
if (index >= 0) { if (index >= 0) {
mObservers.editValueAt(index)->postMessage(msg); mObservers.editValueAt(index)->postMessage(msg);

File diff suppressed because it is too large Load Diff

View File

@@ -102,9 +102,10 @@ static const char *GetCodec(const CodecInfo *info, size_t numInfos,
} }
// static // static
OMXDecoder *OMXDecoder::Create( sp<OMXDecoder> OMXDecoder::Create(
OMXClient *client, const sp<MetaData> &meta, OMXClient *client, const sp<MetaData> &meta,
bool createEncoder) { bool createEncoder,
const sp<MediaSource> &source) {
const char *mime; const char *mime;
bool success = meta->findCString(kKeyMIMEType, &mime); bool success = meta->findCString(kKeyMIMEType, &mime);
assert(success); assert(success);
@@ -158,8 +159,9 @@ OMXDecoder *OMXDecoder::Create(
quirks |= kRequiresLoadedToIdleAfterAllocation; quirks |= kRequiresLoadedToIdleAfterAllocation;
} }
OMXDecoder *decoder = new OMXDecoder( sp<OMXDecoder> decoder = new OMXDecoder(
client, node, mime, codec, createEncoder, quirks); client, node, mime, codec, createEncoder, quirks,
source);
uint32_t type; uint32_t type;
const void *data; const void *data;
@@ -213,7 +215,8 @@ OMXDecoder *OMXDecoder::Create(
OMXDecoder::OMXDecoder(OMXClient *client, IOMX::node_id node, OMXDecoder::OMXDecoder(OMXClient *client, IOMX::node_id node,
const char *mime, const char *codec, const char *mime, const char *codec,
bool is_encoder, bool is_encoder,
uint32_t quirks) uint32_t quirks,
const sp<MediaSource> &source)
: mClient(client), : mClient(client),
mOMX(mClient->interface()), mOMX(mClient->interface()),
mNode(node), mNode(node),
@@ -223,7 +226,7 @@ OMXDecoder::OMXDecoder(OMXClient *client, IOMX::node_id node,
mIsAVC(!strcasecmp(mime, "video/avc")), mIsAVC(!strcasecmp(mime, "video/avc")),
mIsEncoder(is_encoder), mIsEncoder(is_encoder),
mQuirks(quirks), mQuirks(quirks),
mSource(NULL), mSource(source),
mCodecSpecificDataIterator(mCodecSpecificData.begin()), mCodecSpecificDataIterator(mCodecSpecificData.begin()),
mState(OMX_StateLoaded), mState(OMX_StateLoaded),
mPortStatusMask(kPortStatusActive << 2 | kPortStatusActive), mPortStatusMask(kPortStatusActive << 2 | kPortStatusActive),
@@ -237,6 +240,8 @@ OMXDecoder::OMXDecoder(OMXClient *client, IOMX::node_id node,
mBuffers.push(); // input buffers mBuffers.push(); // input buffers
mBuffers.push(); // output buffers mBuffers.push(); // output buffers
setup();
} }
OMXDecoder::~OMXDecoder() { OMXDecoder::~OMXDecoder() {
@@ -263,15 +268,6 @@ OMXDecoder::~OMXDecoder() {
mComponentName = NULL; mComponentName = NULL;
} }
void OMXDecoder::setSource(MediaSource *source) {
Mutex::Autolock autoLock(mLock);
assert(mSource == NULL);
mSource = source;
setup();
}
status_t OMXDecoder::start(MetaData *) { status_t OMXDecoder::start(MetaData *) {
assert(!mStarted); assert(!mStarted);
@@ -580,6 +576,10 @@ void OMXDecoder::setVideoInputFormat(
OMX_COLOR_FORMATTYPE colorFormat = OMX_COLOR_FORMATTYPE colorFormat =
0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY; 0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY;
if (!strncmp("OMX.qcom.video.encoder.", mComponentName, 23)) {
colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
}
setVideoPortFormatType( setVideoPortFormatType(
kPortIndexInput, OMX_VIDEO_CodingUnused, kPortIndexInput, OMX_VIDEO_CodingUnused,
colorFormat); colorFormat);
@@ -1621,7 +1621,7 @@ void OMXDecoder::postStart() {
void OMXDecoder::postEmptyBufferDone(IOMX::buffer_id buffer) { void OMXDecoder::postEmptyBufferDone(IOMX::buffer_id buffer) {
omx_message msg; omx_message msg;
msg.type = omx_message::EMPTY_BUFFER_DONE; msg.type = omx_message::EMPTY_BUFFER_DONE;
msg.u.buffer_data.node = mNode; msg.node = mNode;
msg.u.buffer_data.buffer = buffer; msg.u.buffer_data.buffer = buffer;
postMessage(msg); postMessage(msg);
} }
@@ -1629,7 +1629,7 @@ void OMXDecoder::postEmptyBufferDone(IOMX::buffer_id buffer) {
void OMXDecoder::postInitialFillBuffer(IOMX::buffer_id buffer) { void OMXDecoder::postInitialFillBuffer(IOMX::buffer_id buffer) {
omx_message msg; omx_message msg;
msg.type = omx_message::INITIAL_FILL_BUFFER; msg.type = omx_message::INITIAL_FILL_BUFFER;
msg.u.buffer_data.node = mNode; msg.node = mNode;
msg.u.buffer_data.buffer = buffer; msg.u.buffer_data.buffer = buffer;
postMessage(msg); postMessage(msg);
} }

View File

@@ -31,7 +31,7 @@ static const uint32_t kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
static const uint32_t kSampleSizeType32 = FOURCC('s', 't', 's', 'z'); static const uint32_t kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
static const uint32_t kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2'); static const uint32_t kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
SampleTable::SampleTable(DataSource *source) SampleTable::SampleTable(const sp<DataSource> &source)
: mDataSource(source), : mDataSource(source),
mChunkOffsetOffset(-1), mChunkOffsetOffset(-1),
mChunkOffsetType(0), mChunkOffsetType(0),

View File

@@ -75,6 +75,102 @@ private:
NodeMeta &operator=(const NodeMeta &); NodeMeta &operator=(const NodeMeta &);
}; };
////////////////////////////////////////////////////////////////////////////////
struct OMX::CallbackDispatcher : public RefBase {
CallbackDispatcher();
void post(const omx_message &msg);
protected:
virtual ~CallbackDispatcher();
private:
Mutex mLock;
bool mDone;
Condition mQueueChanged;
List<omx_message> mQueue;
pthread_t mThread;
void dispatch(const omx_message &msg);
static void *ThreadWrapper(void *me);
void threadEntry();
CallbackDispatcher(const CallbackDispatcher &);
CallbackDispatcher &operator=(const CallbackDispatcher &);
};
OMX::CallbackDispatcher::CallbackDispatcher()
: mDone(false) {
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&mThread, &attr, ThreadWrapper, this);
pthread_attr_destroy(&attr);
}
OMX::CallbackDispatcher::~CallbackDispatcher() {
{
Mutex::Autolock autoLock(mLock);
mDone = true;
mQueueChanged.signal();
}
void *dummy;
pthread_join(mThread, &dummy);
}
void OMX::CallbackDispatcher::post(const omx_message &msg) {
Mutex::Autolock autoLock(mLock);
mQueue.push_back(msg);
mQueueChanged.signal();
}
void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
NodeMeta *meta = static_cast<NodeMeta *>(msg.node);
sp<IOMXObserver> observer = meta->observer();
if (observer.get() != NULL) {
observer->on_message(msg);
}
}
// static
void *OMX::CallbackDispatcher::ThreadWrapper(void *me) {
static_cast<CallbackDispatcher *>(me)->threadEntry();
return NULL;
}
void OMX::CallbackDispatcher::threadEntry() {
for (;;) {
omx_message msg;
{
Mutex::Autolock autoLock(mLock);
while (!mDone && mQueue.empty()) {
mQueueChanged.wait(mLock);
}
if (mDone) {
break;
}
msg = *mQueue.begin();
mQueue.erase(mQueue.begin());
}
dispatch(msg);
}
}
////////////////////////////////////////////////////////////////////////////////
class BufferMeta { class BufferMeta {
public: public:
BufferMeta(OMX *owner, const sp<IMemory> &mem, bool is_backup = false) BufferMeta(OMX *owner, const sp<IMemory> &mem, bool is_backup = false)
@@ -154,7 +250,8 @@ OMX_ERRORTYPE OMX::OnFillBufferDone(
return meta->owner()->OnFillBufferDone(meta, pBuffer); return meta->owner()->OnFillBufferDone(meta, pBuffer);
} }
OMX::OMX() { OMX::OMX()
: mDispatcher(new CallbackDispatcher) {
} }
status_t OMX::list_nodes(List<String8> *list) { status_t OMX::list_nodes(List<String8> *list) {
@@ -249,6 +346,29 @@ status_t OMX::set_parameter(
return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK; return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
} }
status_t OMX::get_config(
node_id node, OMX_INDEXTYPE index,
void *params, size_t size) {
Mutex::Autolock autoLock(mLock);
NodeMeta *meta = static_cast<NodeMeta *>(node);
OMX_ERRORTYPE err = OMX_GetConfig(meta->handle(), index, params);
return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
}
status_t OMX::set_config(
node_id node, OMX_INDEXTYPE index,
const void *params, size_t size) {
Mutex::Autolock autoLock(mLock);
NodeMeta *meta = static_cast<NodeMeta *>(node);
OMX_ERRORTYPE err =
OMX_SetConfig(meta->handle(), index, const_cast<void *>(params));
return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
}
status_t OMX::use_buffer( status_t OMX::use_buffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params, node_id node, OMX_U32 port_index, const sp<IMemory> &params,
buffer_id *buffer) { buffer_id *buffer) {
@@ -357,15 +477,12 @@ OMX_ERRORTYPE OMX::OnEvent(
omx_message msg; omx_message msg;
msg.type = omx_message::EVENT; msg.type = omx_message::EVENT;
msg.u.event_data.node = meta; msg.node = meta;
msg.u.event_data.event = eEvent; msg.u.event_data.event = eEvent;
msg.u.event_data.data1 = nData1; msg.u.event_data.data1 = nData1;
msg.u.event_data.data2 = nData2; msg.u.event_data.data2 = nData2;
sp<IOMXObserver> observer = meta->observer(); mDispatcher->post(msg);
if (observer.get() != NULL) {
observer->on_message(msg);
}
return OMX_ErrorNone; return OMX_ErrorNone;
} }
@@ -376,13 +493,10 @@ OMX_ERRORTYPE OMX::OnEmptyBufferDone(
omx_message msg; omx_message msg;
msg.type = omx_message::EMPTY_BUFFER_DONE; msg.type = omx_message::EMPTY_BUFFER_DONE;
msg.u.buffer_data.node = meta; msg.node = meta;
msg.u.buffer_data.buffer = pBuffer; msg.u.buffer_data.buffer = pBuffer;
sp<IOMXObserver> observer = meta->observer(); mDispatcher->post(msg);
if (observer.get() != NULL) {
observer->on_message(msg);
}
return OMX_ErrorNone; return OMX_ErrorNone;
} }
@@ -395,7 +509,7 @@ OMX_ERRORTYPE OMX::OnFillBufferDone(
omx_message msg; omx_message msg;
msg.type = omx_message::FILL_BUFFER_DONE; msg.type = omx_message::FILL_BUFFER_DONE;
msg.u.extended_buffer_data.node = meta; msg.node = meta;
msg.u.extended_buffer_data.buffer = pBuffer; msg.u.extended_buffer_data.buffer = pBuffer;
msg.u.extended_buffer_data.range_offset = pBuffer->nOffset; msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen; msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
@@ -403,10 +517,7 @@ OMX_ERRORTYPE OMX::OnFillBufferDone(
msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp; msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate; msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate;
sp<IOMXObserver> observer = meta->observer(); mDispatcher->post(msg);
if (observer.get() != NULL) {
observer->on_message(msg);
}
return OMX_ErrorNone; return OMX_ErrorNone;
} }
@@ -455,6 +566,20 @@ void OMX::empty_buffer(
assert(err == OMX_ErrorNone); assert(err == OMX_ErrorNone);
} }
status_t OMX::get_extension_index(
node_id node,
const char *parameter_name,
OMX_INDEXTYPE *index) {
NodeMeta *node_meta = static_cast<NodeMeta *>(node);
OMX_ERRORTYPE err =
OMX_GetExtensionIndex(
node_meta->handle(),
const_cast<char *>(parameter_name), index);
return err == OMX_ErrorNone ? OK : UNKNOWN_ERROR;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
sp<IOMXRenderer> OMX::createRenderer( sp<IOMXRenderer> OMX::createRenderer(

View File

@@ -44,6 +44,14 @@ public:
node_id node, OMX_INDEXTYPE index, node_id node, OMX_INDEXTYPE index,
const void *params, size_t size); const void *params, size_t size);
virtual status_t get_config(
node_id node, OMX_INDEXTYPE index,
void *params, size_t size);
virtual status_t set_config(
node_id node, OMX_INDEXTYPE index,
const void *params, size_t size);
virtual status_t use_buffer( virtual status_t use_buffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params, node_id node, OMX_U32 port_index, const sp<IMemory> &params,
buffer_id *buffer); buffer_id *buffer);
@@ -70,6 +78,11 @@ public:
OMX_U32 range_offset, OMX_U32 range_length, OMX_U32 range_offset, OMX_U32 range_length,
OMX_U32 flags, OMX_TICKS timestamp); OMX_U32 flags, OMX_TICKS timestamp);
virtual status_t get_extension_index(
node_id node,
const char *parameter_name,
OMX_INDEXTYPE *index);
virtual sp<IOMXRenderer> createRenderer( virtual sp<IOMXRenderer> createRenderer(
const sp<ISurface> &surface, const sp<ISurface> &surface,
const char *componentName, const char *componentName,
@@ -82,6 +95,9 @@ private:
Mutex mLock; Mutex mLock;
struct CallbackDispatcher;
sp<CallbackDispatcher> mDispatcher;
static OMX_ERRORTYPE OnEvent( static OMX_ERRORTYPE OnEvent(
OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_PTR pAppData, OMX_IN OMX_PTR pAppData,