Merge change 21340 into eclair
* changes: Squashed commit of the following:
This commit is contained in:
@@ -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
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
decoder->setSource(source);
|
|
||||||
for (int i = 0; i < 100; ++i) {
|
|
||||||
MediaBuffer *buffer;
|
MediaBuffer *buffer;
|
||||||
|
mGroup->acquire_buffer(&buffer);
|
||||||
|
|
||||||
::status_t err = decoder->read(&buffer);
|
ssize_t n = mSource->read_at(mOffset, buffer->data(), mSize - mOffset);
|
||||||
if (err != ::OK) {
|
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.Append((const char *)buffer->data() + buffer->range_offset(),
|
default:
|
||||||
buffer->range_length());
|
{
|
||||||
|
// Skip chunk
|
||||||
|
|
||||||
buffer->release();
|
i += chunkSize - 2;
|
||||||
buffer = NULL;
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete decoder;
|
return OK;
|
||||||
decoder = NULL;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -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,26 +356,31 @@ 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);
|
|
||||||
|
size_t len = strlen(argv[1]);
|
||||||
|
if (len >= 4 && !strcasecmp(argv[1] + len - 4, ".jpg")) {
|
||||||
|
isJPEG = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp<MediaSource> mediaSource;
|
||||||
|
|
||||||
|
if (isJPEG) {
|
||||||
|
mediaSource = new JPEGSource(dataSource);
|
||||||
|
} else {
|
||||||
|
sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
|
||||||
|
|
||||||
|
size_t numTracks = extractor->countTracks();
|
||||||
|
|
||||||
sp<MetaData> meta;
|
sp<MetaData> meta;
|
||||||
int i;
|
size_t i;
|
||||||
for (i = 0; i < numTracks; ++i) {
|
for (i = 0; i < numTracks; ++i) {
|
||||||
meta = extractor->getTrackMetaData(i);
|
meta = extractor->getTrackMetaData(i);
|
||||||
|
|
||||||
@@ -163,47 +396,12 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OMXDecoder *decoder = OMXDecoder::Create(&client, meta);
|
mediaSource = extractor->getTrack(i);
|
||||||
|
|
||||||
if (decoder != NULL) {
|
|
||||||
MediaSource *source;
|
|
||||||
err = extractor->getTrack(i, &source);
|
|
||||||
|
|
||||||
decoder->setSource(source);
|
|
||||||
|
|
||||||
decoder->start();
|
|
||||||
|
|
||||||
int64_t startTime = getNowUs();
|
|
||||||
|
|
||||||
int n = 0;
|
|
||||||
MediaBuffer *buffer;
|
|
||||||
while ((err = decoder->read(&buffer)) == OK) {
|
|
||||||
if ((++n % 16) == 0) {
|
|
||||||
printf(".");
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer->release();
|
playSource(&client, mediaSource);
|
||||||
buffer = NULL;
|
|
||||||
}
|
|
||||||
decoder->stop();
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
int64_t delay = getNowUs() - startTime;
|
|
||||||
printf("avg. %.2f fps\n", n * 1E6 / delay);
|
|
||||||
|
|
||||||
delete decoder;
|
|
||||||
decoder = NULL;
|
|
||||||
|
|
||||||
delete source;
|
|
||||||
source = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete extractor;
|
|
||||||
extractor = NULL;
|
|
||||||
|
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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> ¶ms,
|
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
|
||||||
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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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 &);
|
||||||
};
|
};
|
||||||
|
|||||||
18
include/media/stagefright/MediaDebug.h
Normal file
18
include/media/stagefright/MediaDebug.h
Normal 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_
|
||||||
@@ -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 &);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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 &);
|
||||||
|
|||||||
190
include/media/stagefright/OMXCodec.h
Normal file
190
include/media/stagefright/OMXCodec.h
Normal 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_
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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> ¶ms,
|
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
|
||||||
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);
|
||||||
|
|||||||
@@ -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 \
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
1962
media/libstagefright/OMXCodec.cpp
Normal file
1962
media/libstagefright/OMXCodec.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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> ¶ms,
|
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
|
||||||
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(
|
||||||
|
|||||||
@@ -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> ¶ms,
|
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
|
||||||
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,
|
||||||
|
|||||||
Reference in New Issue
Block a user