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