Esempio n. 1
0
static Int32 InitResourcesSDKInt()
{
    AutoPtr<ArrayOf<String> > array = InitACTIVE_CODENAMES();
    return GetInt32Property(String("ro.build.version.sdk"))
        +  array != NULL ? array->GetLength() : 0;
}
status_t Converter::doMoreWork() {
    status_t err;

    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
        for (;;) {
            size_t bufferIndex;
            err = mEncoder->dequeueInputBuffer(&bufferIndex);

            if (err != OK) {
                break;
            }

            mAvailEncoderInputIndices.push_back(bufferIndex);
        }

        feedEncoderInputBuffers();
    }

    for (;;) {
        size_t bufferIndex;
        size_t offset;
        size_t size;
        int64_t timeUs;
        uint32_t flags;
        native_handle_t* handle = NULL;
        err = mEncoder->dequeueOutputBuffer(
                &bufferIndex, &offset, &size, &timeUs, &flags);

        if (err != OK) {
            if (err == INFO_FORMAT_CHANGED) {
                continue;
            } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
                mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
                continue;
            }

            if (err == -EAGAIN) {
                err = OK;
            }
            break;
        }

        if (flags & MediaCodec::BUFFER_FLAG_EOS) {
            sp<AMessage> notify = mNotify->dup();
            notify->setInt32("what", kWhatEOS);
            notify->post();
        } else {
#if 0
            if (mIsVideo) {
                int32_t videoBitrate = GetInt32Property(
                        "media.wfd.video-bitrate", 5000000);

                setVideoBitrate(videoBitrate);
            }
#endif

            sp<ABuffer> buffer;
            sp<ABuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex);

            if (outbuf->meta()->findPointer("handle", (void**)&handle) &&
                    handle != NULL) {
                int32_t rangeLength, rangeOffset;
                CHECK(outbuf->meta()->findInt32("rangeOffset", &rangeOffset));
                CHECK(outbuf->meta()->findInt32("rangeLength", &rangeLength));
                outbuf->meta()->setPointer("handle", NULL);

                // MediaSender will post the following message when HDCP
                // is done, to release the output buffer back to encoder.
                sp<AMessage> notify(new AMessage(kWhatReleaseOutputBuffer, this));
                notify->setInt32("bufferIndex", bufferIndex);

                buffer = new ABuffer(
                        rangeLength > (int32_t)size ? rangeLength : size);
                buffer->meta()->setPointer("handle", handle);
                buffer->meta()->setInt32("rangeOffset", rangeOffset);
                buffer->meta()->setInt32("rangeLength", rangeLength);
                buffer->meta()->setMessage("notify", notify);
            } else {
                buffer = new ABuffer(size);
            }

            buffer->meta()->setInt64("timeUs", timeUs);

            ALOGV("[%s] time %lld us (%.2f secs)",
                    mIsVideo ? "video" : "audio", (long long)timeUs, timeUs / 1E6);

            memcpy(buffer->data(), outbuf->base() + offset, size);

            if (flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) {
                if (!handle) {
                    if (mIsH264) {
                        mCSD0 = buffer;
                    }
                    mOutputFormat->setBuffer("csd-0", buffer);
                }
            } else {
                if (mNeedToManuallyPrependSPSPPS
                        && mIsH264
                        && (mFlags & FLAG_PREPEND_CSD_IF_NECESSARY)
                        && IsIDR(buffer)) {
                    buffer = prependCSD(buffer);
                }

                sp<AMessage> notify = mNotify->dup();
                notify->setInt32("what", kWhatAccessUnit);
                notify->setBuffer("accessUnit", buffer);
                notify->post();
            }
        }

        if (!handle) {
            mEncoder->releaseOutputBuffer(bufferIndex);
        }

        if (flags & MediaCodec::BUFFER_FLAG_EOS) {
            break;
        }
    }

    return err;
}
Esempio n. 3
0
namespace Os {

static String GetStringProperty(
    /* [in] */ const String& property,
    /* [in] */ const String& defaultValue)
{
    AutoPtr<ISystemProperties> sysProp;
    CSystemProperties::AcquireSingleton((ISystemProperties**)&sysProp);
    String value;
    sysProp->Get(property, defaultValue, &value);
    return value;
}

static String GetStringProperty(
    /* [in] */ const String& property)
{
    return GetStringProperty(property, String("unknown")/*UNKNOWN*/);
}

static AutoPtr<ArrayOf<String> > GetStringPropertyList(
    /* [in] */ const String& property,
    /* [in] */ const String& separator)
{
    AutoPtr<ISystemProperties> sysProp;
    CSystemProperties::AcquireSingleton((ISystemProperties**)&sysProp);
    String value;
    sysProp->Get(property, &value);

    AutoPtr<ArrayOf<String> > array;
    if (value.IsNullOrEmpty()) {
        array = ArrayOf<String>::Alloc(0);
    }
    else {
        StringUtils::Split(value, separator, (ArrayOf<String>**)&array);
    }
    return array;
}

static Int32 GetInt32Property(
    /* [in] */ const String& property)
{
    AutoPtr<ISystemProperties> sysProp;
    CSystemProperties::AcquireSingleton((ISystemProperties**)&sysProp);
    Int32 value;
    sysProp->GetInt32(property, 0, &value);
    return value;
}

static Int64 GetInt64Property(
    /* [in] */ const String& property)
{
    AutoPtr<ISystemProperties> sysProp;
    CSystemProperties::AcquireSingleton((ISystemProperties**)&sysProp);
    String retStr = GetStringProperty(property);
    sysProp->Get(property, String("unknown")/*UNKNOWN*/, &retStr);
    if (retStr.Equals("unknown"))
        return -1;

    return StringUtils::ParseInt64(retStr);
}

static AutoPtr<ArrayOf<String> > InitACTIVE_CODENAMES()
{
    AutoPtr<ArrayOf<String> > all = GetStringPropertyList(String("ro.build.version.all_codenames"), String(","));
    if (all != NULL && all->GetLength() > 0) {
        if ((*all)[0].Equals("REL")) {
            all = ArrayOf<String>::Alloc(0);
        }
    }

    return all;
}

static Int32 InitResourcesSDKInt()
{
    AutoPtr<ArrayOf<String> > array = InitACTIVE_CODENAMES();
    return GetInt32Property(String("ro.build.version.sdk"))
        +  array != NULL ? array->GetLength() : 0;
}

/**
 * Some devices split the fingerprint components between multiple
 * partitions, so we might derive the fingerprint at runtime.
 */
static String DeriveFingerprint() {
    String finger = GetStringProperty(String("ro.build.fingerprint"));
    if (finger.IsNullOrEmpty()) {
        StringBuilder sb;
        sb += GetStringProperty(String("ro.product.brand"));
        sb.AppendChar('/');
        sb += GetStringProperty(String("ro.product.name"));
        sb.AppendChar('/');
        sb += GetStringProperty(String("ro.product.device"));
        sb.AppendChar(':');
        sb += GetStringProperty(String("ro.build.version.release"));
        sb.AppendChar('/');
        sb += GetStringProperty(String("ro.build.id"));
        sb.AppendChar('/');
        sb += GetStringProperty(String("ro.build.version.incremental"));
        sb.AppendChar(':');
        sb += GetStringProperty(String("ro.build.type"));
        sb.AppendChar('/');
        sb += GetStringProperty(String("ro.build.tags"));
        finger = sb.ToString();
    }
    return finger;
}

const String Build::VERSION::INCREMENTAL = GetStringProperty(String("ro.build.version.incremental"));
const String Build::VERSION::RELEASE = GetStringProperty(String("ro.build.version.release"));
const String Build::VERSION::SDK = GetStringProperty(String("ro.build.version.sdk"));
const Int32 Build::VERSION::SDK_INT = GetInt32Property(String("ro.build.version.sdk"));
const String Build::VERSION::CODENAME = GetStringProperty(String("ro.build.version.codename"));
const Int32 Build::VERSION::RESOURCES_SDK_INT = InitResourcesSDKInt();

AutoPtr<ArrayOf<String> > Build::VERSION::ALL_CODENAMES
    = GetStringPropertyList(String("ro.build.version.all_codenames"), String(","));

AutoPtr<ArrayOf<String> > Build::VERSION::ACTIVE_CODENAMES = InitACTIVE_CODENAMES();

const Int32 Build::VERSION_CODES::CUR_DEVELOPMENT;
const Int32 Build::VERSION_CODES::BASE;
const Int32 Build::VERSION_CODES::BASE_1_1;
const Int32 Build::VERSION_CODES::CUPCAKE;
const Int32 Build::VERSION_CODES::DONUT;
const Int32 Build::VERSION_CODES::ECLAIR;
const Int32 Build::VERSION_CODES::ECLAIR_0_1;
const Int32 Build::VERSION_CODES::ECLAIR_MR1;
const Int32 Build::VERSION_CODES::FROYO;
const Int32 Build::VERSION_CODES::GINGERBREAD;
const Int32 Build::VERSION_CODES::GINGERBREAD_MR1;
const Int32 Build::VERSION_CODES::HONEYCOMB;
const Int32 Build::VERSION_CODES::HONEYCOMB_MR1;
const Int32 Build::VERSION_CODES::HONEYCOMB_MR2;
const Int32 Build::VERSION_CODES::ICE_CREAM_SANDWICH;
const Int32 Build::VERSION_CODES::ICE_CREAM_SANDWICH_MR1;
const Int32 Build::VERSION_CODES::JELLY_BEAN;
const Int32 Build::VERSION_CODES::JELLY_BEAN_MR1;
const Int32 Build::VERSION_CODES::JELLY_BEAN_MR2;
const Int32 Build::VERSION_CODES::KITKAT;
const Int32 Build::VERSION_CODES::KITKAT_WATCH;
const Int32 Build::VERSION_CODES::L;
const Int32 Build::VERSION_CODES::LOLLIPOP;

const String Build::TAG("Build");
const String Build::UNKNOWN("unknown");
const String Build::ID = GetStringProperty(String("ro.build.id"));
const String Build::DISPLAY = GetStringProperty(String("ro.build.display.id"));
const String Build::PRODUCT = GetStringProperty(String("ro.product.name"));
const String Build::DEVICE = GetStringProperty(String("ro.product.device"));
const String Build::BOARD = GetStringProperty(String("ro.product.board"));
const String Build::CPU_ABI;
const String Build::CPU_ABI2;
const String Build::MANUFACTURER = GetStringProperty(String("ro.product.manufacturer"));
const String Build::BRAND = GetStringProperty(String("ro.product.brand"));
const String Build::MODEL = GetStringProperty(String("ro.product.model"));
const String Build::BOOTLOADER = GetStringProperty(String("ro.bootloader"));
const String Build::RADIO = GetStringProperty(String("gsm.version.baseband")); ///TelephonyProperties.PROPERTY_BASEBAND_VERSION
const String Build::HARDWARE = GetStringProperty(String("ro.hardware"));
const String Build::SERIAL = GetStringProperty(String("ro.serialno"));
const String Build::TYPE = GetStringProperty(String("user")); //GetStringProperty(String("ro.build.type");
const String Build::TAGS = GetStringProperty(String("ro.build.tags"));
const String Build::FINGERPRINT = DeriveFingerprint();

const Int64 Build::TIME = GetInt64Property(String("ro.build.date.utc")) * 1000;
const String Build::USER = GetStringProperty(String("ro.build.user"));
const String Build::HOST = GetStringProperty(String("ro.build.host"));

AutoPtr<ArrayOf<String> > Build::SUPPORTED_ABIS
    = GetStringPropertyList(String("ro.product.cpu.abilist"), String(","));

AutoPtr<ArrayOf<String> > Build::SUPPORTED_32_BIT_ABIS
    = GetStringPropertyList(String("ro.product.cpu.abilist32"), String(","));

AutoPtr<ArrayOf<String> > Build::SUPPORTED_64_BIT_ABIS
    = GetStringPropertyList(String("ro.product.cpu.abilist64"), String(","));

const Boolean Build::IS_DEBUGGABLE = GetInt32Property(String("ro.debuggable")) == 1;

ECode Build::EnsureFingerprintProperty()
{
    String value = GetStringProperty(String("ro.build.fingerprint"));
    if (value.IsNullOrEmpty()) {
        // try {
        AutoPtr<ISystemProperties> sysProp;
        CSystemProperties::AcquireSingleton((ISystemProperties**)&sysProp);
        sysProp->Set(String("ro.build.fingerprint"), FINGERPRINT);
        // } catch (IllegalArgumentException e) {
        //     Slog.e(TAG, "Failed to set fingerprint property", e);
        // }
    }
    return NOERROR;
}

String Build::GetRadioVersion()
{
    String value = GetStringProperty(
        String("gsm.version.baseband")/*TelephonyProperties.PROPERTY_BASEBAND_VERSION*/,
        String(NULL));
    return value;
}

String Build::GetString(
    /* [in] */ const char* property)
{
    String str(property);
    return GetStringProperty(str, UNKNOWN);
}

Int64 Build::GetInt64(
    /* [in] */ const char* property)
{
    String str(property);
    return GetInt64Property(str);
}

String Build::GetString(
    /* [in] */ const String& property)
{
    return GetStringProperty(property, UNKNOWN);
}

Int64 Build::GetInt64(
    /* [in] */ const String& property)
{
    AutoPtr<ISystemProperties> sysProp;
    CSystemProperties::AcquireSingleton((ISystemProperties**)&sysProp);
    String retStr = GetStringProperty(property);
    sysProp->Get(property, UNKNOWN, &retStr);
    if (retStr.Equals(UNKNOWN))
        return -1;

    return StringUtils::ParseInt64(retStr);
}


} // namespace Os
status_t Converter::initEncoder() {
    AString outputMIME;
    CHECK(mOutputFormat->findString("mime", &outputMIME));

    bool isAudio = !strncasecmp(outputMIME.c_str(), "audio/", 6);

    if (!mIsPCMAudio) {
        mEncoder = MediaCodec::CreateByType(
                mCodecLooper, outputMIME.c_str(), true /* encoder */);

        if (mEncoder == NULL) {
            return ERROR_UNSUPPORTED;
        }
    }

    if (mIsPCMAudio) {
        return OK;
    }

    int32_t audioBitrate = GetInt32Property("media.wfd.audio-bitrate", 128000);
    int32_t videoBitrate = GetInt32Property("media.wfd.video-bitrate", 5000000);
    mPrevVideoBitrate = videoBitrate;

    ALOGI("using audio bitrate of %d bps, video bitrate of %d bps",
          audioBitrate, videoBitrate);

    if (isAudio) {
        mOutputFormat->setInt32("bitrate", audioBitrate);
    } else {
        mOutputFormat->setInt32("bitrate", videoBitrate);
        mOutputFormat->setInt32("bitrate-mode", OMX_Video_ControlRateConstant);
        mOutputFormat->setInt32("frame-rate", 30);
        mOutputFormat->setInt32("i-frame-interval", 15);  // Iframes every 15 secs

        // Configure encoder to use intra macroblock refresh mode
        mOutputFormat->setInt32("intra-refresh-mode", OMX_VIDEO_IntraRefreshCyclic);

        int width, height, mbs;
        if (!mOutputFormat->findInt32("width", &width)
                || !mOutputFormat->findInt32("height", &height)) {
            return ERROR_UNSUPPORTED;
        }

        // Update macroblocks in a cyclic fashion with 10% of all MBs within
        // frame gets updated at one time. It takes about 10 frames to
        // completely update a whole video frame. If the frame rate is 30,
        // it takes about 333 ms in the best case (if next frame is not an IDR)
        // to recover from a lost/corrupted packet.
        mbs = (((width + 15) / 16) * ((height + 15) / 16) * 10) / 100;
        mOutputFormat->setInt32("intra-refresh-CIR-mbs", mbs);
    }

    ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());

    mNeedToManuallyPrependSPSPPS = false;

    status_t err = NO_INIT;

    if (!isAudio) {
        sp<AMessage> tmp = mOutputFormat->dup();
        tmp->setInt32("prepend-sps-pps-to-idr-frames", 1);

        err = mEncoder->configure(
                tmp,
                NULL /* nativeWindow */,
                NULL /* crypto */,
                MediaCodec::CONFIGURE_FLAG_ENCODE);

        if (err == OK) {
            // Encoder supported prepending SPS/PPS, we don't need to emulate
            // it.
            mOutputFormat = tmp;
        } else {
            mNeedToManuallyPrependSPSPPS = true;

            ALOGI("We going to manually prepend SPS and PPS to IDR frames.");
        }
    }

    if (err != OK) {
        // We'll get here for audio or if we failed to configure the encoder
        // to automatically prepend SPS/PPS in the case of video.

        err = mEncoder->configure(
                    mOutputFormat,
                    NULL /* nativeWindow */,
                    NULL /* crypto */,
                    MediaCodec::CONFIGURE_FLAG_ENCODE);
    }

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

    if (mFlags & FLAG_USE_SURFACE_INPUT) {
        CHECK(mIsVideo);

        err = mEncoder->createInputSurface(&mGraphicBufferProducer);

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

    err = mEncoder->start();

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

    err = mEncoder->getInputBuffers(&mEncoderInputBuffers);

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

    err = mEncoder->getOutputBuffers(&mEncoderOutputBuffers);

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

    if (mFlags & FLAG_USE_SURFACE_INPUT) {
        scheduleDoMoreWork();
    }

    return OK;
}