Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit df64839f authored by Andreas Huber's avatar Andreas Huber Committed by Android Git Automerger
Browse files

am ffbd2426: Merge change 21340 into eclair

Merge commit 'ffbd2426f07474a95fefa3b2f4fe7eb4d4329af5'

* commit 'ffbd2426f07474a95fefa3b2f4fe7eb4d4329af5':
  Squashed commit of the following:
parents e99fc320 693d271e
Loading
Loading
Loading
Loading
+3 −6
Original line number Diff line number Diff line
@@ -10,8 +10,7 @@ LOCAL_SHARED_LIBRARIES := \

LOCAL_C_INCLUDES:= \
	frameworks/base/media/libstagefright \
	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
        $(TOP)/external/opencore/android
	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include

LOCAL_CFLAGS += -Wno-multichar

@@ -31,8 +30,7 @@ LOCAL_SHARED_LIBRARIES := \

LOCAL_C_INCLUDES:= \
	frameworks/base/media/libstagefright \
	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
        $(TOP)/external/opencore/android
	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include

LOCAL_CFLAGS += -Wno-multichar

@@ -52,8 +50,7 @@ include $(BUILD_EXECUTABLE)
# 
# LOCAL_C_INCLUDES:= \
# 	frameworks/base/media/libstagefright \
# 	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
#         $(TOP)/external/opencore/android
# 	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
# 
# LOCAL_CFLAGS += -Wno-multichar
# 
+87 −48
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/MmapSource.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/OMXDecoder.h>

using namespace android;
@@ -32,18 +33,38 @@ using namespace android;
class DummySource : public MediaSource {
public:
    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));
    }

    virtual ::status_t getMaxSampleSize(size_t *max_size) {
    virtual sp<MetaData> getFormat() {
        sp<MetaData> meta = new MetaData;
        meta->setInt32(kKeyWidth, mWidth);
        meta->setInt32(kKeyHeight, mHeight);
        meta->setCString(kKeyMIMEType, "video/raw");

        return meta;
    }

    virtual status_t getMaxSampleSize(size_t *max_size) {
        *max_size = mSize;
        return ::OK;
        return OK;
    }

    virtual status_t start(MetaData *params) {
        return OK;
    }

    virtual status_t stop() {
        return OK;
    }

    virtual ::status_t read(MediaBuffer **buffer) {
        ::status_t err = mGroup.acquire_buffer(buffer);
        if (err != ::OK) {
    virtual status_t read(
            MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
        status_t err = mGroup.acquire_buffer(buffer);
        if (err != OK) {
            return err;
        }

@@ -51,34 +72,34 @@ public:
        memset((*buffer)->data(), x, mSize);
        (*buffer)->set_range(0, mSize);

        return ::OK;
        return OK;
    }

protected:
    virtual ~DummySource() {}

private:
    MediaBufferGroup mGroup;
    int mWidth, mHeight;
    size_t mSize;

    DummySource(const DummySource &);
    DummySource &operator=(const DummySource &);
};

int main(int argc, char **argv) {
    android::ProcessState::self()->startThreadPool();
#define USE_OMX_CODEC   1

#if 1
    if (argc != 2) {
        fprintf(stderr, "usage: %s filename\n", argv[0]);
        return 1;
    }
sp<MediaSource> createSource(const char *filename) {
    sp<MediaSource> source;

    sp<MPEG4Extractor> extractor =
        new MPEG4Extractor(new MmapSource(filename));

    MPEG4Extractor extractor(new MmapSource(argv[1]));
    int num_tracks;
    assert(extractor.countTracks(&num_tracks) == ::OK);
    size_t num_tracks = extractor->countTracks();

    MediaSource *source = NULL;
    sp<MetaData> meta;
    for (int i = 0; i < num_tracks; ++i) {
        meta = extractor.getTrackMetaData(i);
    for (size_t i = 0; i < num_tracks; ++i) {
        meta = extractor->getTrackMetaData(i);
        assert(meta.get() != NULL);

        const char *mime;
@@ -90,48 +111,75 @@ int main(int argc, char **argv) {
            continue;
        }

        if (extractor.getTrack(i, &source) != ::OK) {
            source = NULL;
            continue;
        }
        source = extractor->getTrack(i);
        break;
    }

    if (source == NULL) {
        fprintf(stderr, "Unable to find a suitable video track.\n");
    return source;
}

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;
    }

    OMXClient client;
    assert(client.connect() == android::OK);

    OMXDecoder *decoder = OMXDecoder::Create(&client, meta);
    decoder->setSource(source);
#if 0
    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;
    bool success = meta->findInt32(kKeyWidth, &width);
    success = success && meta->findInt32(kKeyHeight, &height);
    assert(success);
#else
    int width = 320;
    int height = 240;
    sp<MediaSource> decoder = new DummySource(width, height);
#endif

    sp<MetaData> enc_meta = new MetaData;
    enc_meta->setCString(kKeyMIMEType, "video/3gpp");
    // enc_meta->setCString(kKeyMIMEType, "video/mp4v-es");
    // enc_meta->setCString(kKeyMIMEType, "video/3gpp");
    enc_meta->setCString(kKeyMIMEType, "video/mp4v-es");
    enc_meta->setInt32(kKeyWidth, width);
    enc_meta->setInt32(kKeyHeight, height);

    OMXDecoder *encoder =
        OMXDecoder::Create(&client, enc_meta, true /* createEncoder */);

    encoder->setSource(decoder);
    // encoder->setSource(meta, new DummySource(width, height));
#if USE_OMX_CODEC
    sp<OMXCodec> encoder =
        OMXCodec::Create(
                client.interface(), enc_meta, true /* createEncoder */, decoder);
#else
    sp<OMXDecoder> encoder = OMXDecoder::Create(
            &client, enc_meta, true /* createEncoder */, decoder);
#endif

#if 1
    MPEG4Writer writer("/sdcard/output.mp4");
    writer.addSource(enc_meta, encoder);
    writer.start();
    sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
    writer->addSource(enc_meta, encoder);
    writer->start();
    sleep(20);
    printf("stopping now.\n");
    writer.stop();
    writer->stop();
#else
    encoder->start();

@@ -146,16 +194,7 @@ int main(int argc, char **argv) {
    encoder->stop();
#endif

    delete encoder;
    encoder = NULL;

    delete decoder;
    decoder = NULL;

    client.disconnect();

    delete source;
    source = NULL;
#endif

#if 0
+285 −87
Original line number Diff line number Diff line
@@ -16,9 +16,6 @@

#include <sys/time.h>

#undef NDEBUG
#include <assert.h>

#include <pthread.h>
#include <stdlib.h>

@@ -30,12 +27,15 @@
#include <media/stagefright/ESDS.h>
#include <media/stagefright/FileSource.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaPlayerImpl.h>
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MmapSource.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/OMXDecoder.h>

#include "WaveWriter.h"
@@ -44,50 +44,236 @@ using namespace android;

////////////////////////////////////////////////////////////////////////////////

static bool convertToWav(
        OMXClient *client, const sp<MetaData> &meta, MediaSource *source) {
    printf("convertToWav\n");
struct JPEGSource : public MediaSource {
    // Assumes ownership of "source".
    JPEGSource(const sp<DataSource> &source);

    virtual status_t start(MetaData *params = NULL);
    virtual status_t stop();
    virtual sp<MetaData> getFormat();

    virtual status_t read(
            MediaBuffer **buffer, const ReadOptions *options = NULL);

protected:
    virtual ~JPEGSource();

private:
    sp<DataSource> mSource;
    MediaBufferGroup *mGroup;
    bool mStarted;
    off_t mSize;
    int32_t mWidth, mHeight;
    off_t mOffset;

    status_t parseJPEG();

    JPEGSource(const JPEGSource &);
    JPEGSource &operator=(const JPEGSource &);
};

JPEGSource::JPEGSource(const sp<DataSource> &source)
    : mSource(source),
      mGroup(NULL),
      mStarted(false),
      mSize(0),
      mWidth(0),
      mHeight(0),
      mOffset(0) {
    CHECK_EQ(parseJPEG(), OK);
}

JPEGSource::~JPEGSource() {
    if (mStarted) {
        stop();
    }
}

    OMXDecoder *decoder = OMXDecoder::Create(client, meta);
status_t JPEGSource::start(MetaData *) {
    if (mStarted) {
        return UNKNOWN_ERROR;
    }

    int32_t sampleRate;
    bool success = meta->findInt32(kKeySampleRate, &sampleRate);
    assert(success);
    if (mSource->getSize(&mSize) != OK) {
        return UNKNOWN_ERROR;
    }

    int32_t numChannels;
    success = meta->findInt32(kKeyChannelCount, &numChannels);
    assert(success);
    mGroup = new MediaBufferGroup;
    mGroup->add_buffer(new MediaBuffer(mSize));

    const char *mime;
    success = meta->findCString(kKeyMIMEType, &mime);
    assert(success);
    mOffset = 0;

    if (!strcasecmp("audio/3gpp", mime)) {
        numChannels = 1;  // XXX
    mStarted = true;
    
    return OK;
}

    WaveWriter writer("/sdcard/Music/shoutcast.wav", numChannels, sampleRate);
status_t JPEGSource::stop() {
    if (!mStarted) {
        return UNKNOWN_ERROR;
    }

    decoder->setSource(source);
    for (int i = 0; i < 100; ++i) {
        MediaBuffer *buffer;
    delete mGroup;
    mGroup = NULL;

        ::status_t err = decoder->read(&buffer);
        if (err != ::OK) {
            break;
    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;
}

        writer.Append((const char *)buffer->data() + buffer->range_offset(),
                      buffer->range_length());
status_t JPEGSource::read(
        MediaBuffer **out, const ReadOptions *options) {
    *out = NULL;

    int64_t seekTimeUs;
    if (options != NULL && options->getSeekTo(&seekTimeUs)) {
        return UNKNOWN_ERROR;
    }

    MediaBuffer *buffer;
    mGroup->acquire_buffer(&buffer);

    ssize_t n = mSource->read_at(mOffset, buffer->data(), mSize - mOffset);

    if (n <= 0) {
        buffer->release();
        buffer = NULL;

        return UNKNOWN_ERROR;
    }

    delete decoder;
    decoder = NULL;
    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;
    }

    return true;
    for (;;) {
        uint8_t marker;
        if (mSource->read_at(i++, &marker, 1) != 1) {
            return ERROR_IO;
        }

        CHECK_EQ(marker, 0xff);

        if (mSource->read_at(i++, &marker, 1) != 1) {
            return ERROR_IO;
        }

        CHECK(marker != 0xff);

        uint16_t chunkSize;
        if (!mSource->getUInt16(i, &chunkSize)) {
            return ERROR_IO;
        }

        i += 2;

        if (chunkSize < 2) {
            return UNKNOWN_ERROR;
        }

        switch (marker) {
            case JPEG_SOS:
            {
                return (mWidth > 0 && mHeight > 0) ? OK : UNKNOWN_ERROR;
            }

            case JPEG_EOI:
            {
                return UNKNOWN_ERROR;
            }

            case JPEG_SOF0: 
            case JPEG_SOF1: 
            case JPEG_SOF3: 
            case JPEG_SOF5: 
            case JPEG_SOF6: 
            case JPEG_SOF7: 
            case JPEG_SOF9: 
            case JPEG_SOF10:
            case JPEG_SOF11:
            case JPEG_SOF13:
            case JPEG_SOF14:
            case JPEG_SOF15:
            {
                uint16_t width, height;
                if (!mSource->getUInt16(i + 1, &height)
                    || !mSource->getUInt16(i + 3, &width)) {
                    return ERROR_IO;
                }

                mWidth = width;
                mHeight = height;

                i += chunkSize - 2;
                break;
            }

            default:
            {
                // Skip chunk

                i += chunkSize - 2;

                break;
            }
        }
    }

    return OK;
}

////////////////////////////////////////////////////////////////////////////////
@@ -99,6 +285,48 @@ static int64_t getNowUs() {
    return (int64_t)tv.tv_usec + tv.tv_sec * 1000000;
}

#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) {
    android::ProcessState::self()->startThreadPool();

@@ -108,10 +336,10 @@ int main(int argc, char **argv) {
        sp<IBinder> binder = sm->getService(String16("media.player"));
        sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);

        assert(service.get() != NULL);
        CHECK(service.get() != NULL);

        sp<IOMX> omx = service->createOMX();
        assert(omx.get() != NULL);
        CHECK(omx.get() != NULL);

        List<String8> list;
        omx->list_nodes(&list);
@@ -128,26 +356,31 @@ int main(int argc, char **argv) {
        --argc;
    }

#if 0
    MediaPlayerImpl player(argv[1]);
    player.play();

    sleep(10000);
#else
    DataSource::RegisterDefaultSniffers();

    OMXClient client;
    status_t err = client.connect();

    MmapSource *dataSource = new MmapSource(argv[1]);
    MediaExtractor *extractor = MediaExtractor::Create(dataSource);
    dataSource = NULL;
    sp<MmapSource> dataSource = new MmapSource(argv[1]);

    int numTracks;
    err = extractor->countTracks(&numTracks);
    bool isJPEG = false;

    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;
    int i;
        size_t i;
        for (i = 0; i < numTracks; ++i) {
            meta = extractor->getTrackMetaData(i);

@@ -163,47 +396,12 @@ int main(int argc, char **argv) {
            }
        }

    OMXDecoder *decoder = OMXDecoder::Create(&client, meta);

    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();
            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;
        mediaSource = extractor->getTrack(i);
    }

    delete extractor;
    extractor = NULL;
    playSource(&client, mediaSource);

    client.disconnect();
#endif

    return 0;
}
+15 −4
Original line number Diff line number Diff line
@@ -56,6 +56,14 @@ public:
            node_id node, OMX_INDEXTYPE index,
            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(
            node_id node, OMX_U32 port_index, const sp<IMemory> &params,
            buffer_id *buffer) = 0;
@@ -82,6 +90,11 @@ public:
            OMX_U32 range_offset, OMX_U32 range_length,
            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(
            const sp<ISurface> &surface,
            const char *componentName,
@@ -114,10 +127,11 @@ struct omx_message {
        QUIT_OBSERVER,
    } type;

    IOMX::node_id node;

    union {
        // if type == EVENT
        struct {
            IOMX::node_id node;
            OMX_EVENTTYPE event;
            OMX_U32 data1;
            OMX_U32 data2;
@@ -126,13 +140,11 @@ struct omx_message {
        // if type == EMPTY_BUFFER_DONE || type == FILL_BUFFER
        //    || type == INITIAL_FILL_BUFFER
        struct {
            IOMX::node_id node;
            IOMX::buffer_id buffer;
        } buffer_data;

        // if type == EMPTY_BUFFER || type == FILL_BUFFER_DONE
        struct {
            IOMX::node_id node;
            IOMX::buffer_id buffer;
            OMX_U32 range_offset;
            OMX_U32 range_length;
@@ -143,7 +155,6 @@ struct omx_message {

        // if type == SEND_COMMAND
        struct {
            IOMX::node_id node;
            OMX_COMMANDTYPE cmd;
            OMX_S32 param;
        } send_command_data;
+3 −3
Original line number Diff line number Diff line
@@ -31,10 +31,10 @@ class AudioTrack;
class AudioPlayer : public TimeSource {
public:
    AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink);
    ~AudioPlayer();
    virtual ~AudioPlayer();

    // Caller retains ownership of "source".
    void setSource(MediaSource *source);
    void setSource(const sp<MediaSource> &source);

    // Return time in us.
    virtual int64_t getRealTimeUs();
@@ -56,7 +56,7 @@ public:
    status_t seekTo(int64_t time_us);

private:
    MediaSource *mSource;
    sp<MediaSource> mSource;
    AudioTrack *mAudioTrack;

    MediaBuffer *mInputBuffer;
Loading