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

Commit bf03e42c authored by Lajos Molnar's avatar Lajos Molnar
Browse files

cmds/stagefright: use MediaCodec* instead of OMXCodec

OneShotDecodingSource is a lightweight replacement for OMXCodec
for decoding use. It does not support pause, secure content or
precise seeking.

'stagefright' now lists the codec profiles for all OMX codecs,
not just the regular ones.

Change-Id: I99f0f79af852a8a16607218acd9fdd83457b7f70
parent 25a21c4b
Loading
Loading
Loading
Loading
+15 −15
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ LOCAL_SRC_FILES:= \

LOCAL_SHARED_LIBRARIES := \
	libstagefright libmedia libutils libbinder libstagefright_foundation \
        libjpeg libgui libcutils liblog libui
	libjpeg libgui libcutils liblog

LOCAL_C_INCLUDES:= \
	frameworks/av/media/libstagefright \
+18 −20
Original line number Diff line number Diff line
@@ -23,13 +23,14 @@
#include <binder/ProcessState.h>
#include <media/mediarecorder.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/AMRWriter.h>
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/AudioSource.h>
#include <media/stagefright/MediaCodecSource.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/SimpleDecodingSource.h>
#include "SineSource.h"

using namespace android;
@@ -79,8 +80,6 @@ int main(int argc, char* argv[])
    const int32_t kBitRate = outputWBAMR ? 16000 : 8000;

    android::ProcessState::self()->startThreadPool();
    OMXClient client;
    CHECK_EQ(client.connect(), (status_t)OK);
    sp<MediaSource> source;

    if (useMic) {
@@ -95,24 +94,25 @@ int main(int argc, char* argv[])
        source = new SineSource(kSampleRate, channels);
    }

    sp<MetaData> meta = new MetaData;
    meta->setCString(
            kKeyMIMEType,
    sp<AMessage> meta = new AMessage;
    meta->setString(
            "mime",
            outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
                    : MEDIA_MIMETYPE_AUDIO_AMR_NB);

    meta->setInt32(kKeyChannelCount, channels);
    meta->setInt32(kKeySampleRate, kSampleRate);
    meta->setInt32(kKeyBitRate, kBitRate);
    meta->setInt32("channel-count", channels);
    meta->setInt32("sample-rate", kSampleRate);
    meta->setInt32("bitrate", kBitRate);
    int32_t maxInputSize;
    if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) {
        meta->setInt32(kKeyMaxInputSize, maxInputSize);
        meta->setInt32("max-input-size", maxInputSize);
    }

    sp<IMediaSource> encoder = OMXCodec::Create(
            client.interface(),
            meta, true /* createEncoder */,
            source);
    sp<ALooper> looper = new ALooper;
    looper->setName("audioloop");
    looper->start();

    sp<IMediaSource> encoder = MediaCodecSource::Create(looper, meta, source);

    if (fileOut != NULL) {
        // target file specified, write encoded AMR output
@@ -128,17 +128,15 @@ int main(int argc, char* argv[])
        writer->stop();
    } else {
        // otherwise decode to speaker
        sp<IMediaSource> decoder = OMXCodec::Create(
                client.interface(),
                meta, false /* createEncoder */,
                encoder);
        sp<IMediaSource> decoder = SimpleDecodingSource::Create(encoder);

        if (playToSpeaker) {
            AudioPlayer *player = new AudioPlayer(NULL);
            player->setSource(decoder);
            player->start();
            sleep(duration);
            source->stop(); // must stop source otherwise delete player will hang

            decoder.clear(); // must clear |decoder| otherwise delete player will hang.
            delete player; // there is no player->stop()...
        } else {
            CHECK_EQ(decoder->start(), (status_t)OK);
+29 −34
Original line number Diff line number Diff line
@@ -18,16 +18,18 @@

#include <binder/ProcessState.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/CameraSource.h>
#include <media/stagefright/FileSource.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaCodecSource.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/SimpleDecodingSource.h>
#include <media/MediaPlayerInterface.h>

using namespace android;
@@ -182,9 +184,6 @@ int main(int argc, char **argv) {
        fprintf(stderr, "input color format must be 0 (YUV420SP) or 1 (YUV420P)\n");
        return 1;
    }
    OMXClient client;
    CHECK_EQ(client.connect(), (status_t)OK);

    status_t err = OK;

#if 0
@@ -197,8 +196,7 @@ int main(int argc, char **argv) {

    sp<MetaData> meta = source->getFormat();

    sp<MediaSource> decoder = OMXCodec::Create(
            client.interface(), meta, false /* createEncoder */, source);
    sp<MediaSource> decoder = SimpleDecodingSource::Create(source);

    int width, height;
    bool success = meta->findInt32(kKeyWidth, &width);
@@ -210,22 +208,21 @@ int main(int argc, char **argv) {
    sp<MediaSource> decoder = new DummySource(width, height, colorFormat);
#endif

    sp<MetaData> enc_meta = new MetaData;
    // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
    // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
    enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
    enc_meta->setInt32(kKeyWidth, width);
    enc_meta->setInt32(kKeyHeight, height);
    enc_meta->setInt32(kKeySampleRate, kFramerate);
    enc_meta->setInt32(kKeyBitRate, kVideoBitRate);
    enc_meta->setInt32(kKeyStride, width);
    enc_meta->setInt32(kKeySliceHeight, height);
    enc_meta->setInt32(kKeyIFramesInterval, kIFramesIntervalSec);
    enc_meta->setInt32(kKeyColorFormat, colorFormat);
    sp<AMessage> enc_meta = new AMessage;
    // enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
    // enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
    enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
    enc_meta->setInt32("width", width);
    enc_meta->setInt32("height", height);
    enc_meta->setInt32("sample-rate", kFramerate);
    enc_meta->setInt32("bit-rate", kVideoBitRate);
    // enc_meta->setInt32("stride", width);
    // enc_meta->setInt32("slice-height", height);
    enc_meta->setInt32("i-frame-interval", kIFramesIntervalSec);
    enc_meta->setInt32("color-format", colorFormat);

    sp<MediaSource> encoder =
        OMXCodec::Create(
                client.interface(), enc_meta, true /* createEncoder */, decoder);
        MediaCodecSource::Create(looper, format, decoder);

#if 1
    sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
@@ -260,7 +257,6 @@ int main(int argc, char **argv) {
#endif

    printf("$\n");
    client.disconnect();
#endif

#if 0
@@ -299,9 +295,6 @@ int main(int argc, char **argv) {
int main(int /* argc */, char ** /* argv */) {
    android::ProcessState::self()->startThreadPool();

    OMXClient client;
    CHECK_EQ(client.connect(), (status_t)OK);

    const int32_t kSampleRate = 22050;
    const int32_t kNumChannels = 2;
    sp<MediaSource> audioSource = new SineSource(kSampleRate, kNumChannels);
@@ -317,16 +310,20 @@ int main(int /* argc */, char ** /* argv */) {
    player->stop();
#endif

    sp<MetaData> encMeta = new MetaData;
    encMeta->setCString(kKeyMIMEType,
    sp<AMessage> encMeta = new AMessage;
    encMeta->setString("mime",
            0 ? MEDIA_MIMETYPE_AUDIO_AMR_WB : MEDIA_MIMETYPE_AUDIO_AAC);
    encMeta->setInt32(kKeySampleRate, kSampleRate);
    encMeta->setInt32(kKeyChannelCount, kNumChannels);
    encMeta->setInt32(kKeyMaxInputSize, 8192);
    encMeta->setInt32(kKeyBitRate, kAudioBitRate);
    encMeta->setInt32("sample-rate", kSampleRate);
    encMeta->setInt32("channel-count", kNumChannels);
    encMeta->setInt32("max-input-size", 8192);
    encMeta->setInt32("bitrate", kAudioBitRate);

    sp<ALooper> looper = new ALooper;
    looper->setName("record");
    looper->start();

    sp<IMediaSource> encoder =
        OMXCodec::Create(client.interface(), encMeta, true, audioSource);
        MediaCodecSource::Create(looper, encMeta, audioSource);

    encoder->start();

@@ -348,8 +345,6 @@ int main(int /* argc */, char ** /* argv */) {

    encoder->stop();

    client.disconnect();

    return 0;
}
#endif
+26 −23
Original line number Diff line number Diff line
@@ -23,15 +23,18 @@

#include <binder/ProcessState.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaCodecSource.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
#include <media/MediaPlayerInterface.h>

#include <OMX_Video.h>

using namespace android;

// Print usage showing how to use this utility to record videos
@@ -265,44 +268,45 @@ int main(int argc, char **argv) {
        }
    }

    OMXClient client;
    CHECK_EQ(client.connect(), (status_t)OK);

    status_t err = OK;
    sp<MediaSource> source =
        new DummySource(width, height, nFrames, frameRateFps, colorFormat);

    sp<MetaData> enc_meta = new MetaData;
    sp<AMessage> enc_meta = new AMessage;
    switch (codec) {
        case 1:
            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
            enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
            break;
        case 2:
            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
            enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
            break;
        default:
            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
            enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
            break;
    }
    enc_meta->setInt32(kKeyWidth, width);
    enc_meta->setInt32(kKeyHeight, height);
    enc_meta->setInt32(kKeyFrameRate, frameRateFps);
    enc_meta->setInt32(kKeyBitRate, bitRateBps);
    enc_meta->setInt32(kKeyStride, width);
    enc_meta->setInt32(kKeySliceHeight, height);
    enc_meta->setInt32(kKeyIFramesInterval, iFramesIntervalSeconds);
    enc_meta->setInt32(kKeyColorFormat, colorFormat);
    enc_meta->setInt32("width", width);
    enc_meta->setInt32("height", height);
    enc_meta->setInt32("frame-rate", frameRateFps);
    enc_meta->setInt32("bitrate", bitRateBps);
    enc_meta->setInt32("stride", width);
    enc_meta->setInt32("slice-height", height);
    enc_meta->setInt32("i-frame-interval", iFramesIntervalSeconds);
    enc_meta->setInt32("color-format", colorFormat);
    if (level != -1) {
        enc_meta->setInt32(kKeyVideoLevel, level);
        enc_meta->setInt32("level", level);
    }
    if (profile != -1) {
        enc_meta->setInt32(kKeyVideoProfile, profile);
        enc_meta->setInt32("profile", profile);
    }

    sp<ALooper> looper = new ALooper;
    looper->setName("recordvideo");
    looper->start();

    sp<IMediaSource> encoder =
        OMXCodec::Create(
                client.interface(), enc_meta, true /* createEncoder */, source,
                0, preferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0);
        MediaCodecSource::Create(
                looper, enc_meta, source, NULL /* consumer */,
                preferSoftwareCodec ? MediaCodecSource::FLAG_PREFER_SOFTWARE_CODEC : 0);

    int fd = open(fileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
    if (fd < 0) {
@@ -321,7 +325,6 @@ int main(int argc, char **argv) {
    int64_t end = systemTime();

    fprintf(stderr, "$\n");
    client.disconnect();

    if (err != OK && err != ERROR_END_OF_STREAM) {
        fprintf(stderr, "record failed: %d\n", err);
+40 −71
Original line number Diff line number Diff line
@@ -31,20 +31,26 @@

#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <media/ICrypto.h>
#include <media/IMediaHTTPService.h>
#include <media/IMediaPlayerService.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
#include "include/NuCachedSource2.h"
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/JPEGSource.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaCodecList.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/SimpleDecodingSource.h>
#include <media/stagefright/Utils.h>
#include <media/mediametadataretriever.h>

#include <media/stagefright/foundation/hexdump.h>
@@ -164,7 +170,7 @@ static void dumpSource(const sp<IMediaSource> &source, const String8 &filename)
    out = NULL;
}

static void playSource(OMXClient *client, sp<IMediaSource> &source) {
static void playSource(sp<IMediaSource> &source) {
    sp<MetaData> meta = source->getFormat();

    const char *mime;
@@ -176,20 +182,14 @@ static void playSource(OMXClient *client, sp<IMediaSource> &source) {
    } else {
        int flags = 0;
        if (gPreferSoftwareCodec) {
            flags |= OMXCodec::kPreferSoftwareCodecs;
            flags |= MediaCodecList::kPreferSoftwareCodecs;
        }
        if (gForceToUseHardwareCodec) {
            CHECK(!gPreferSoftwareCodec);
            flags |= OMXCodec::kHardwareCodecsOnly;
            flags |= MediaCodecList::kHardwareCodecsOnly;
        }
        rawSource = OMXCodec::Create(
            client->interface(), meta, false /* createEncoder */, source,
            NULL /* matchComponentName */,
            flags,
            gSurface);

        rawSource = SimpleDecodingSource::Create(source, flags, gSurface);
        if (rawSource == NULL) {
            fprintf(stderr, "Failed to instantiate decoder for '%s'.\n", mime);
            return;
        }
        displayAVCProfileLevelIfPossible(meta);
@@ -343,12 +343,6 @@ static void playSource(OMXClient *client, sp<IMediaSource> &source) {
                    printf(".");
                    fflush(stdout);
                }

                // render buffers from OMXCodec
                if (buffer->graphicBuffer() != NULL && gSurface != NULL) {
                    gSurface->queueBuffer(gSurface.get(), buffer->graphicBuffer()->getNativeBuffer(), -1);
                    buffer->meta_data()->setInt32(kKeyRendered, 1);
                }
            }

            sumDecodeUs += delayDecodeUs;
@@ -628,7 +622,7 @@ static void usage(const char *me) {
    fprintf(stderr, "       -D(ump) output_filename (decoded PCM data to a file)\n");
}

static void dumpCodecProfiles(const sp<IOMX>& omx, bool queryDecoders) {
static void dumpCodecProfiles(bool queryDecoders) {
    const char *kMimeTypes[] = {
        MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
        MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_AUDIO_AAC,
@@ -642,29 +636,35 @@ static void dumpCodecProfiles(const sp<IOMX>& omx, bool queryDecoders) {
    const char *codecType = queryDecoders? "decoder" : "encoder";
    printf("%s profiles:\n", codecType);

    sp<IMediaCodecList> list = MediaCodecList::getInstance();
    size_t numCodecs = list->countCodecs();

    for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]); ++k) {
        printf("type '%s':\n", kMimeTypes[k]);

        Vector<CodecCapabilities> results;
        // will retrieve hardware and software codecs
        CHECK_EQ(QueryCodecs(omx, kMimeTypes[k],
                             queryDecoders,
                             &results), (status_t)OK);

        for (size_t i = 0; i < results.size(); ++i) {
        for (size_t index = 0; index < numCodecs; ++index) {
            sp<MediaCodecInfo> info = list->getCodecInfo(index);
            if (info == NULL || info->isEncoder() != !queryDecoders) {
                continue;
            }
            sp<MediaCodecInfo::Capabilities> caps = info->getCapabilitiesFor(kMimeTypes[k]);
            if (caps == NULL) {
                continue;
            }
            printf("  %s '%s' supports ",
                       codecType, results[i].mComponentName.string());
                       codecType, info->getCodecName());

            if (results[i].mProfileLevels.size() == 0) {
            Vector<MediaCodecInfo::ProfileLevel> profileLevels;
            caps->getSupportedProfileLevels(&profileLevels);
            if (profileLevels.size() == 0) {
                printf("NOTHING.\n");
                continue;
            }

            for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) {
                const CodecProfileLevel &profileLevel =
                     results[i].mProfileLevels[j];
            for (size_t j = 0; j < profileLevels.size(); ++j) {
                const MediaCodecInfo::ProfileLevel &profileLevel = profileLevels[j];

                printf("%s%" PRIu32 "/%" PRIu32, j > 0 ? ", " : "",
                printf("%s%u/%u", j > 0 ? ", " : "",
                        profileLevel.mProfile, profileLevel.mLevel);
            }

@@ -898,17 +898,8 @@ int main(int argc, char **argv) {
    }

    if (dumpProfiles) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder = sm->getService(String16("media.player"));
        sp<IMediaPlayerService> service =
            interface_cast<IMediaPlayerService>(binder);

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

        sp<IOMX> omx = service->getOMX();
        CHECK(omx.get() != NULL);
        dumpCodecProfiles(omx, true /* queryDecoders */);
        dumpCodecProfiles(omx, false /* queryDecoders */);
        dumpCodecProfiles(true /* queryDecoders */);
        dumpCodecProfiles(false /* queryDecoders */);
    }

    if (listComponents) {
@@ -971,16 +962,11 @@ int main(int argc, char **argv) {
                    false /* isControlledByApp */);
            gSurface = new Surface(producer);
        }

        CHECK_EQ((status_t)OK,
                 native_window_api_connect(
                     gSurface.get(), NATIVE_WINDOW_API_MEDIA));
    }

    DataSource::RegisterDefaultSniffers();

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

    for (int k = 0; k < argc && err == OK; ++k) {
        bool syncInfoPresent = true;
@@ -1120,31 +1106,16 @@ int main(int argc, char **argv) {
        } else if (dumpStream) {
            dumpSource(mediaSource, dumpStreamFilename);
        } else if (dumpPCMStream) {
            OMXClient client;
            CHECK_EQ(client.connect(), (status_t)OK);

            sp<IMediaSource> decSource =
                OMXCodec::Create(
                        client.interface(),
                        mediaSource->getFormat(),
                        false,
                        mediaSource,
                        0,
                        0);

            sp<IMediaSource> decSource = SimpleDecodingSource::Create(mediaSource);
            dumpSource(decSource, dumpStreamFilename);
        } else if (seekTest) {
            performSeekTest(mediaSource);
        } else {
            playSource(&client, mediaSource);
            playSource(mediaSource);
        }
    }

    if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
        CHECK_EQ((status_t)OK,
                 native_window_api_disconnect(
                     gSurface.get(), NATIVE_WINDOW_API_MEDIA));

        gSurface.clear();

        if (useSurfaceAlloc) {
@@ -1152,7 +1123,5 @@ int main(int argc, char **argv) {
        }
    }

    client.disconnect();

    return 0;
}