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

Commit 2e730571 authored by The Android Automerger's avatar The Android Automerger
Browse files

Merge branch 'gingerbread' into gingerbread-release

parents c12791a6 76e2c7be
Loading
Loading
Loading
Loading
+203 −41
Original line number Diff line number Diff line
@@ -14,6 +14,10 @@
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "stagefright"
#include <media/stagefright/foundation/ADebug.h>

#include <sys/time.h>

#include <stdlib.h>
@@ -27,10 +31,11 @@
#include <media/IMediaPlayerService.h>
#include <media/stagefright/foundation/ALooper.h>
#include "include/ARTSPController.h"
#include "include/LiveSource.h"
#include "include/NuCachedSource2.h"
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/JPEGSource.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaExtractor.h>
@@ -43,6 +48,8 @@
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MPEG4Writer.h>

#include <fcntl.h>

using namespace android;

static long gNumRepetitions;
@@ -120,7 +127,7 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) {

            bool shouldSeek = false;
            if (err == INFO_FORMAT_CHANGED) {
                CHECK_EQ(buffer, NULL);
                CHECK(buffer == NULL);

                printf("format changed.\n");
                continue;
@@ -206,7 +213,7 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) {
            options.clearSeekTo();

            if (err != OK) {
                CHECK_EQ(buffer, NULL);
                CHECK(buffer == NULL);

                if (err == INFO_FORMAT_CHANGED) {
                    printf("format changed.\n");
@@ -267,14 +274,115 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) {
    }
}

static void writeSourceToMP4(const sp<MediaSource> &source) {
////////////////////////////////////////////////////////////////////////////////

struct DetectSyncSource : public MediaSource {
    DetectSyncSource(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);

private:
    enum StreamType {
        AVC,
        MPEG4,
        H263,
        OTHER,
    };

    sp<MediaSource> mSource;
    StreamType mStreamType;

    DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource);
};

DetectSyncSource::DetectSyncSource(const sp<MediaSource> &source)
    : mSource(source),
      mStreamType(OTHER) {
    const char *mime;
    CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));

    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
        mStreamType = AVC;
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {
        mStreamType = MPEG4;
        CHECK(!"sync frame detection not implemented yet for MPEG4");
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
        mStreamType = H263;
        CHECK(!"sync frame detection not implemented yet for H.263");
    }
}

status_t DetectSyncSource::start(MetaData *params) {
    return mSource->start(params);
}

status_t DetectSyncSource::stop() {
    return mSource->stop();
}

sp<MetaData> DetectSyncSource::getFormat() {
    return mSource->getFormat();
}

static bool isIDRFrame(MediaBuffer *buffer) {
    const uint8_t *data =
        (const uint8_t *)buffer->data() + buffer->range_offset();
    size_t size = buffer->range_length();
    for (size_t i = 0; i + 3 < size; ++i) {
        if (!memcmp("\x00\x00\x01", &data[i], 3)) {
            uint8_t nalType = data[i + 3] & 0x1f;
            if (nalType == 5) {
                return true;
            }
        }
    }

    return false;
}

status_t DetectSyncSource::read(
        MediaBuffer **buffer, const ReadOptions *options) {
    status_t err = mSource->read(buffer, options);

    if (err != OK) {
        return err;
    }

    if (mStreamType == AVC && isIDRFrame(*buffer)) {
        (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
    } else {
        (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
    }

    return OK;
}

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

static void writeSourcesToMP4(
        Vector<sp<MediaSource> > &sources, bool syncInfoPresent) {
    sp<MPEG4Writer> writer =
        new MPEG4Writer(gWriteMP4Filename.string());

    CHECK_EQ(writer->addSource(source), OK);
    // at most one minute.
    writer->setMaxFileDuration(60000000ll);

    for (size_t i = 0; i < sources.size(); ++i) {
        sp<MediaSource> source = sources.editItemAt(i);

        CHECK_EQ(writer->addSource(
                    syncInfoPresent ? source : new DetectSyncSource(source)),
                (status_t)OK);
    }

    sp<MetaData> params = new MetaData;
    CHECK_EQ(writer->start(), OK);
    params->setInt32(kKeyNotRealTime, true);
    CHECK_EQ(writer->start(params.get()), (status_t)OK);

    while (!writer->reachedEOS()) {
        usleep(100000);
@@ -283,7 +391,7 @@ static void writeSourceToMP4(const sp<MediaSource> &source) {
}

static void performSeekTest(const sp<MediaSource> &source) {
    CHECK_EQ(OK, source->start());
    CHECK_EQ((status_t)OK, source->start());

    int64_t durationUs;
    CHECK(source->getFormat()->findInt64(kKeyDuration, &durationUs));
@@ -335,7 +443,7 @@ static void performSeekTest(const sp<MediaSource> &source) {
        }
    }

    CHECK_EQ(OK, source->stop());
    CHECK_EQ((status_t)OK, source->stop());
}

static void usage(const char *me) {
@@ -481,10 +589,10 @@ int main(int argc, char **argv) {
        for (int k = 0; k < argc; ++k) {
            const char *filename = argv[k];

            CHECK_EQ(retriever->setDataSource(filename), OK);
            CHECK_EQ(retriever->setDataSource(filename), (status_t)OK);
            CHECK_EQ(retriever->setMode(
                        METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL),
                     OK);
                     (status_t)OK);

            sp<IMemory> mem = retriever->captureFrame();

@@ -530,7 +638,7 @@ int main(int argc, char **argv) {
            Vector<CodecCapabilities> results;
            CHECK_EQ(QueryCodecs(omx, kMimeTypes[k],
                                 true, // queryDecoders
                                 &results), OK);
                                 &results), (status_t)OK);

            for (size_t i = 0; i < results.size(); ++i) {
                printf("  decoder '%s' supports ",
@@ -579,12 +687,16 @@ int main(int argc, char **argv) {
    status_t err = client.connect();

    for (int k = 0; k < argc; ++k) {
        bool syncInfoPresent = true;

        const char *filename = argv[k];

        sp<DataSource> dataSource = DataSource::CreateFromURI(filename);

        if ((strncasecmp(filename, "sine:", 5)
                && strncasecmp(filename, "rtsp://", 7)) && dataSource == NULL) {
        if (strncasecmp(filename, "sine:", 5)
                && strncasecmp(filename, "rtsp://", 7)
                && strncasecmp(filename, "httplive://", 11)
                && dataSource == NULL) {
            fprintf(stderr, "Unable to create data source.\n");
            return 1;
        }
@@ -596,10 +708,14 @@ int main(int argc, char **argv) {
            isJPEG = true;
        }

        Vector<sp<MediaSource> > mediaSources;
        sp<MediaSource> mediaSource;

        if (isJPEG) {
            mediaSource = new JPEGSource(dataSource);
            if (gWriteMP4) {
                mediaSources.push(mediaSource);
            }
        } else if (!strncasecmp("sine:", filename, 5)) {
            char *end;
            long sampleRate = strtol(filename + 5, &end, 10);
@@ -608,6 +724,9 @@ int main(int argc, char **argv) {
                sampleRate = 44100;
            }
            mediaSource = new SineSource(sampleRate, 1);
            if (gWriteMP4) {
                mediaSources.push(mediaSource);
            }
        } else {
            sp<MediaExtractor> extractor;

@@ -625,6 +744,20 @@ int main(int argc, char **argv) {
                }

                extractor = rtspController.get();

                syncInfoPresent = false;
            } else if (!strncasecmp("httplive://", filename, 11)) {
                String8 uri("http://");
                uri.append(filename + 11);

                dataSource = new LiveSource(uri.string());
                dataSource = new NuCachedSource2(dataSource);

                extractor =
                    MediaExtractor::Create(
                            dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);

                syncInfoPresent = false;
            } else {
                extractor = MediaExtractor::Create(dataSource);
                if (extractor == NULL) {
@@ -635,6 +768,34 @@ int main(int argc, char **argv) {

            size_t numTracks = extractor->countTracks();

            if (gWriteMP4) {
                bool haveAudio = false;
                bool haveVideo = false;
                for (size_t i = 0; i < numTracks; ++i) {
                    sp<MediaSource> source = extractor->getTrack(i);

                    const char *mime;
                    CHECK(source->getFormat()->findCString(
                                kKeyMIMEType, &mime));

                    bool useTrack = false;
                    if (!haveAudio && !strncasecmp("audio/", mime, 6)) {
                        haveAudio = true;
                        useTrack = true;
                    } else if (!haveVideo && !strncasecmp("video/", mime, 6)) {
                        haveVideo = true;
                        useTrack = true;
                    }

                    if (useTrack) {
                        mediaSources.push(source);

                        if (haveAudio && haveVideo) {
                            break;
                        }
                    }
                }
            } else {
                sp<MetaData> meta;
                size_t i;
                for (i = 0; i < numTracks; ++i) {
@@ -672,9 +833,10 @@ int main(int argc, char **argv) {

                mediaSource = extractor->getTrack(i);
            }
        }

        if (gWriteMP4) {
            writeSourceToMP4(mediaSource);
            writeSourcesToMP4(mediaSources, syncInfoPresent);
        } else if (seekTest) {
            performSeekTest(mediaSource);
        } else {
+9 −1
Original line number Diff line number Diff line
@@ -2111,7 +2111,15 @@ void MPEG4Writer::Track::writeTrackHeader(
                      mOwner->endBox();  // d263
                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
                      CHECK(mCodecSpecificData);
                      CHECK(mCodecSpecificDataSize > 0);
                      CHECK(mCodecSpecificDataSize >= 5);

                      // Patch avcc's lengthSize field to match the number
                      // of bytes we use to indicate the size of a nal unit.
                      uint8_t *ptr = (uint8_t *)mCodecSpecificData;
                      ptr[4] =
                          (ptr[4] & 0xfc)
                            | (mOwner->useNalLengthFour() ? 3 : 1);

                      mOwner->beginBox("avcC");
                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
                      mOwner->endBox();  // avcC
+13 −6
Original line number Diff line number Diff line
@@ -980,7 +980,10 @@ status_t OMXCodec::setupErrorCorrectionParameters() {
    status_t err = mOMX->getParameter(
            mNode, OMX_IndexParamVideoErrorCorrection,
            &errorCorrectionType, sizeof(errorCorrectionType));
    CHECK_EQ(err, OK);
    if (err != OK) {
        LOGW("Error correction param query is not supported");
        return OK;  // Optional feature. Ignore this failure
    }

    errorCorrectionType.bEnableHEC = OMX_FALSE;
    errorCorrectionType.bEnableResync = OMX_TRUE;
@@ -991,7 +994,11 @@ status_t OMXCodec::setupErrorCorrectionParameters() {
    err = mOMX->setParameter(
            mNode, OMX_IndexParamVideoErrorCorrection,
            &errorCorrectionType, sizeof(errorCorrectionType));
    CHECK_EQ(err, OK);
    if (err != OK) {
        LOGW("Error correction param configuration is not supported");
    }

    // Optional feature. Ignore the failure.
    return OK;
}

@@ -1089,8 +1096,8 @@ status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {

    // Check profile and level parameters
    CodecProfileLevel defaultProfileLevel, profileLevel;
    defaultProfileLevel.mProfile = OMX_VIDEO_H263ProfileBaseline;
    defaultProfileLevel.mLevel = OMX_VIDEO_H263Level45;
    defaultProfileLevel.mProfile = h263type.eProfile;
    defaultProfileLevel.mLevel = h263type.eLevel;
    err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
    if (err != OK) return err;
    h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profileLevel.mProfile);
@@ -1146,8 +1153,8 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {

    // Check profile and level parameters
    CodecProfileLevel defaultProfileLevel, profileLevel;
    defaultProfileLevel.mProfile = OMX_VIDEO_MPEG4ProfileSimple;
    defaultProfileLevel.mLevel = OMX_VIDEO_MPEG4Level2;
    defaultProfileLevel.mProfile = mpeg4type.eProfile;
    defaultProfileLevel.mLevel = mpeg4type.eLevel;
    err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
    if (err != OK) return err;
    mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile);
+49 −40
Original line number Diff line number Diff line
@@ -4653,9 +4653,6 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
        goto Exit;
    }

    {
        Mutex::Autolock _l(mLock);

    // check audio settings permission for global effects
    if (sessionId == AudioSystem::SESSION_OUTPUT_MIX && !settingsAllowed()) {
        lStatus = PERMISSION_DENIED;
@@ -4677,6 +4674,24 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
        goto Exit;
    }

    if (output == 0) {
        if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE) {
            // output must be specified by AudioPolicyManager when using session
            // AudioSystem::SESSION_OUTPUT_STAGE
            lStatus = BAD_VALUE;
            goto Exit;
        } else if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) {
            // if the output returned by getOutputForEffect() is removed before we lock the
            // mutex below, the call to checkPlaybackThread_l(output) below will detect it
            // and we will exit safely
            output = AudioSystem::getOutputForEffect(&desc);
        }
    }

    {
        Mutex::Autolock _l(mLock);


        if (!EffectIsNullUuid(&pDesc->uuid)) {
            // if uuid is specified, request effect descriptor
            lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
@@ -4744,17 +4759,9 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,

        // If output is not specified try to find a matching audio session ID in one of the
        // output threads.
        // TODO: allow attachment of effect to inputs
        // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
        // because of code checking output when entering the function.
        if (output == 0) {
            if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE) {
                // output must be specified by AudioPolicyManager when using session
                // AudioSystem::SESSION_OUTPUT_STAGE
                lStatus = BAD_VALUE;
                goto Exit;
            } else if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) {
                output = AudioSystem::getOutputForEffect(&desc);
                LOGV("createEffect() got output %d for effect %s", output, desc.name);
            } else {
             // look for the thread where the specified audio session is present
            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
                if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
@@ -4769,7 +4776,7 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
                output = mPlaybackThreads.keyAt(0);
            }
        }
        }
        LOGV("createEffect() got output %d for effect %s", output, desc.name);
        PlaybackThread *thread = checkPlaybackThread_l(output);
        if (thread == NULL) {
            LOGE("createEffect() unknown output thread");
@@ -4777,6 +4784,8 @@ sp<IEffect> AudioFlinger::createEffect(pid_t pid,
            goto Exit;
        }

        // TODO: allow attachment of effect to inputs

        wclient = mClients.valueFor(pid);

        if (wclient != NULL) {