diff options
Diffstat (limited to 'media')
48 files changed, 850 insertions, 143 deletions
diff --git a/media/libeffects/downmix/Android.mk b/media/libeffects/downmix/Android.mk index 5d0a87c..2bb6dbe 100644 --- a/media/libeffects/downmix/Android.mk +++ b/media/libeffects/downmix/Android.mk @@ -13,7 +13,7 @@ LOCAL_MODULE:= libdownmix  LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx  ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)  LOCAL_LDLIBS += -ldl diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c index d571f17..d84bca6 100644 --- a/media/libeffects/downmix/EffectDownmix.c +++ b/media/libeffects/downmix/EffectDownmix.c @@ -61,13 +61,13 @@ const struct effect_interface_s gDownmixInterface = {  // This is the only symbol that needs to be exported  __attribute__ ((visibility ("default")))  audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { -    tag : AUDIO_EFFECT_LIBRARY_TAG, -    version : EFFECT_LIBRARY_API_VERSION, -    name : "Downmix Library", -    implementor : "The Android Open Source Project", -    create_effect : DownmixLib_Create, -    release_effect : DownmixLib_Release, -    get_descriptor : DownmixLib_GetDescriptor, +    .tag = AUDIO_EFFECT_LIBRARY_TAG, +    .version = EFFECT_LIBRARY_API_VERSION, +    .name = "Downmix Library", +    .implementor = "The Android Open Source Project", +    .create_effect = DownmixLib_Create, +    .release_effect = DownmixLib_Release, +    .get_descriptor = DownmixLib_GetDescriptor,  }; diff --git a/media/libeffects/loudness/Android.mk b/media/libeffects/loudness/Android.mk index dcb7b27..edf964e 100644 --- a/media/libeffects/loudness/Android.mk +++ b/media/libeffects/loudness/Android.mk @@ -14,7 +14,7 @@ LOCAL_SHARED_LIBRARIES := \  	liblog \  	libstlport -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx  LOCAL_MODULE:= libldnhncr  LOCAL_C_INCLUDES := \ diff --git a/media/libeffects/loudness/EffectLoudnessEnhancer.cpp b/media/libeffects/loudness/EffectLoudnessEnhancer.cpp index 5510caf..a5a1a3f 100644 --- a/media/libeffects/loudness/EffectLoudnessEnhancer.cpp +++ b/media/libeffects/loudness/EffectLoudnessEnhancer.cpp @@ -453,13 +453,13 @@ const struct effect_interface_s gLEInterface = {  // This is the only symbol that needs to be exported  __attribute__ ((visibility ("default")))  audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { -    tag : AUDIO_EFFECT_LIBRARY_TAG, -    version : EFFECT_LIBRARY_API_VERSION, -    name : "Loudness Enhancer Library", -    implementor : "The Android Open Source Project", -    create_effect : LELib_Create, -    release_effect : LELib_Release, -    get_descriptor : LELib_GetDescriptor, +    .tag = AUDIO_EFFECT_LIBRARY_TAG, +    .version = EFFECT_LIBRARY_API_VERSION, +    .name = "Loudness Enhancer Library", +    .implementor = "The Android Open Source Project", +    .create_effect = LELib_Create, +    .release_effect = LELib_Release, +    .get_descriptor = LELib_GetDescriptor,  };  }; // extern "C" diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk index f1af389..68ba34c 100644 --- a/media/libeffects/lvm/wrapper/Android.mk +++ b/media/libeffects/lvm/wrapper/Android.mk @@ -13,7 +13,7 @@ LOCAL_CFLAGS += -fvisibility=hidden  LOCAL_MODULE:= libbundlewrapper -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx  LOCAL_STATIC_LIBRARIES += libmusicbundle @@ -42,7 +42,7 @@ LOCAL_CFLAGS += -fvisibility=hidden  LOCAL_MODULE:= libreverbwrapper -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx  LOCAL_STATIC_LIBRARIES += libreverb diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp index 9fcfba3..b6aea6c 100644 --- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp +++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp @@ -3214,13 +3214,13 @@ const struct effect_interface_s gLvmEffectInterface = {  // This is the only symbol that needs to be exported  __attribute__ ((visibility ("default")))  audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { -    tag : AUDIO_EFFECT_LIBRARY_TAG, -    version : EFFECT_LIBRARY_API_VERSION, -    name : "Effect Bundle Library", -    implementor : "NXP Software Ltd.", -    create_effect : android::EffectCreate, -    release_effect : android::EffectRelease, -    get_descriptor : android::EffectGetDescriptor, +    .tag = AUDIO_EFFECT_LIBRARY_TAG, +    .version = EFFECT_LIBRARY_API_VERSION, +    .name = "Effect Bundle Library", +    .implementor = "NXP Software Ltd.", +    .create_effect = android::EffectCreate, +    .release_effect = android::EffectRelease, +    .get_descriptor = android::EffectGetDescriptor,  };  } diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp index 2e22532..c98d62b 100644 --- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp +++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp @@ -2147,13 +2147,13 @@ const struct effect_interface_s gReverbInterface = {  // This is the only symbol that needs to be exported  __attribute__ ((visibility ("default")))  audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { -    tag : AUDIO_EFFECT_LIBRARY_TAG, -    version : EFFECT_LIBRARY_API_VERSION, -    name : "Reverb Library", -    implementor : "NXP Software Ltd.", -    create_effect : android::EffectCreate, -    release_effect : android::EffectRelease, -    get_descriptor : android::EffectGetDescriptor, +    .tag = AUDIO_EFFECT_LIBRARY_TAG, +    .version = EFFECT_LIBRARY_API_VERSION, +    .name = "Reverb Library", +    .implementor = "NXP Software Ltd.", +    .create_effect = android::EffectCreate, +    .release_effect = android::EffectRelease, +    .get_descriptor = android::EffectGetDescriptor,  };  } diff --git a/media/libeffects/preprocessing/Android.mk b/media/libeffects/preprocessing/Android.mk index c344352..9e8cb83 100644 --- a/media/libeffects/preprocessing/Android.mk +++ b/media/libeffects/preprocessing/Android.mk @@ -5,7 +5,7 @@ include $(CLEAR_VARS)  LOCAL_MODULE:= libaudiopreprocessing  LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx  LOCAL_SRC_FILES:= \      PreProcessing.cpp diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp index 1eb5d40..be4fa7e 100644 --- a/media/libeffects/preprocessing/PreProcessing.cpp +++ b/media/libeffects/preprocessing/PreProcessing.cpp @@ -1895,13 +1895,13 @@ int PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid,  // This is the only symbol that needs to be exported  __attribute__ ((visibility ("default")))  audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { -    tag : AUDIO_EFFECT_LIBRARY_TAG, -    version : EFFECT_LIBRARY_API_VERSION, -    name : "Audio Preprocessing Library", -    implementor : "The Android Open Source Project", -    create_effect : PreProcessingLib_Create, -    release_effect : PreProcessingLib_Release, -    get_descriptor : PreProcessingLib_GetDescriptor +    .tag = AUDIO_EFFECT_LIBRARY_TAG, +    .version = EFFECT_LIBRARY_API_VERSION, +    .name = "Audio Preprocessing Library", +    .implementor = "The Android Open Source Project", +    .create_effect = PreProcessingLib_Create, +    .release_effect = PreProcessingLib_Release, +    .get_descriptor = PreProcessingLib_GetDescriptor  };  }; // extern "C" diff --git a/media/libeffects/proxy/Android.mk b/media/libeffects/proxy/Android.mk index a1894b7..b438796 100644 --- a/media/libeffects/proxy/Android.mk +++ b/media/libeffects/proxy/Android.mk @@ -15,7 +15,7 @@  LOCAL_PATH:= $(call my-dir)  include $(CLEAR_VARS)  LOCAL_MODULE:= libeffectproxy -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx  LOCAL_MODULE_TAGS := optional diff --git a/media/libeffects/proxy/EffectProxy.cpp b/media/libeffects/proxy/EffectProxy.cpp index f93a143..62d3fd3 100644 --- a/media/libeffects/proxy/EffectProxy.cpp +++ b/media/libeffects/proxy/EffectProxy.cpp @@ -363,11 +363,11 @@ int Effect_getDescriptor(effect_handle_t   self,  __attribute__ ((visibility ("default")))  audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { -    tag : AUDIO_EFFECT_LIBRARY_TAG, -    version : EFFECT_LIBRARY_API_VERSION, -    name : "Effect Proxy", -    implementor : "AOSP", -    create_effect : android::EffectProxyCreate, -    release_effect : android::EffectProxyRelease, -    get_descriptor : android::EffectProxyGetDescriptor, +    .tag = AUDIO_EFFECT_LIBRARY_TAG, +    .version = EFFECT_LIBRARY_API_VERSION, +    .name = "Effect Proxy", +    .implementor = "AOSP", +    .create_effect = android::EffectProxyCreate, +    .release_effect = android::EffectProxyRelease, +    .get_descriptor = android::EffectProxyGetDescriptor,  }; diff --git a/media/libeffects/testlibs/Android.mk_ b/media/libeffects/testlibs/Android.mk_ index 2954908..672ebba 100644 --- a/media/libeffects/testlibs/Android.mk_ +++ b/media/libeffects/testlibs/Android.mk_ @@ -11,7 +11,7 @@ LOCAL_CFLAGS+= -O2  LOCAL_SHARED_LIBRARIES := \  	libcutils -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx  LOCAL_MODULE:= libreverbtest  ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) @@ -47,7 +47,7 @@ LOCAL_CFLAGS+= -O2  LOCAL_SHARED_LIBRARIES := \  	libcutils -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx  LOCAL_MODULE:= libequalizertest  ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk index e196eb2..dd2d306 100644 --- a/media/libeffects/visualizer/Android.mk +++ b/media/libeffects/visualizer/Android.mk @@ -13,7 +13,7 @@ LOCAL_SHARED_LIBRARIES := \  	liblog \  	libdl -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx +LOCAL_MODULE_RELATIVE_PATH := soundfx  LOCAL_MODULE:= libvisualizer  LOCAL_C_INCLUDES := \ diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp index 18bdb78..4b318c0 100644 --- a/media/libeffects/visualizer/EffectVisualizer.cpp +++ b/media/libeffects/visualizer/EffectVisualizer.cpp @@ -679,13 +679,13 @@ const struct effect_interface_s gVisualizerInterface = {  // This is the only symbol that needs to be exported  __attribute__ ((visibility ("default")))  audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { -    tag : AUDIO_EFFECT_LIBRARY_TAG, -    version : EFFECT_LIBRARY_API_VERSION, -    name : "Visualizer Library", -    implementor : "The Android Open Source Project", -    create_effect : VisualizerLib_Create, -    release_effect : VisualizerLib_Release, -    get_descriptor : VisualizerLib_GetDescriptor, +    .tag = AUDIO_EFFECT_LIBRARY_TAG, +    .version = EFFECT_LIBRARY_API_VERSION, +    .name = "Visualizer Library", +    .implementor = "The Android Open Source Project", +    .create_effect = VisualizerLib_Create, +    .release_effect = VisualizerLib_Release, +    .get_descriptor = VisualizerLib_GetDescriptor,  };  }; // extern "C" diff --git a/media/libmedia/AudioParameter.cpp b/media/libmedia/AudioParameter.cpp index e3fea77..33dbf0b 100644 --- a/media/libmedia/AudioParameter.cpp +++ b/media/libmedia/AudioParameter.cpp @@ -37,9 +37,10 @@ AudioParameter::AudioParameter(const String8& keyValuePairs)  {      char *str = new char[keyValuePairs.length()+1];      mKeyValuePairs = keyValuePairs; +    char *last;      strcpy(str, keyValuePairs.string()); -    char *pair = strtok(str, ";"); +    char *pair = strtok_r(str, ";", &last);      while (pair != NULL) {          if (strlen(pair) != 0) {              size_t eqIdx = strcspn(pair, "="); @@ -58,7 +59,7 @@ AudioParameter::AudioParameter(const String8& keyValuePairs)          } else {              ALOGV("AudioParameter() cstor empty key value pair");          } -        pair = strtok(NULL, ";"); +        pair = strtok_r(NULL, ";", &last);      }      delete[] str; diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp index f7a9a75..f1a6a9f 100644 --- a/media/libmedia/IDrm.cpp +++ b/media/libmedia/IDrm.cpp @@ -51,6 +51,7 @@ enum {      ENCRYPT,      DECRYPT,      SIGN, +    SIGN_RSA,      VERIFY,      SET_LISTENER  }; @@ -196,11 +197,15 @@ struct BpDrm : public BpInterface<IDrm> {          return reply.readInt32();      } -    virtual status_t getProvisionRequest(Vector<uint8_t> &request, +    virtual status_t getProvisionRequest(String8 const &certType, +                                         String8 const &certAuthority, +                                         Vector<uint8_t> &request,                                           String8 &defaultUrl) {          Parcel data, reply;          data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); +        data.writeString8(certType); +        data.writeString8(certAuthority);          remote()->transact(GET_PROVISION_REQUEST, data, &reply);          readVector(reply, request); @@ -209,13 +214,18 @@ struct BpDrm : public BpInterface<IDrm> {          return reply.readInt32();      } -    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response) { +    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response, +                                              Vector<uint8_t> &certificate, +                                              Vector<uint8_t> &wrappedKey) {          Parcel data, reply;          data.writeInterfaceToken(IDrm::getInterfaceDescriptor());          writeVector(data, response);          remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply); +        readVector(reply, certificate); +        readVector(reply, wrappedKey); +          return reply.readInt32();      } @@ -386,6 +396,25 @@ struct BpDrm : public BpInterface<IDrm> {          return reply.readInt32();      } +    virtual status_t signRSA(Vector<uint8_t> const &sessionId, +                             String8 const &algorithm, +                             Vector<uint8_t> const &message, +                             Vector<uint8_t> const &wrappedKey, +                             Vector<uint8_t> &signature) { +        Parcel data, reply; +        data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + +        writeVector(data, sessionId); +        data.writeString8(algorithm); +        writeVector(data, message); +        writeVector(data, wrappedKey); + +        remote()->transact(SIGN_RSA, data, &reply); +        readVector(reply, signature); + +        return reply.readInt32(); +    } +      virtual status_t setListener(const sp<IDrmClient>& listener) {          Parcel data, reply;          data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); @@ -563,9 +592,13 @@ status_t BnDrm::onTransact(          case GET_PROVISION_REQUEST:          {              CHECK_INTERFACE(IDrm, data, reply); +            String8 certType = data.readString8(); +            String8 certAuthority = data.readString8(); +              Vector<uint8_t> request;              String8 defaultUrl; -            status_t result = getProvisionRequest(request, defaultUrl); +            status_t result = getProvisionRequest(certType, certAuthority, +                                                  request, defaultUrl);              writeVector(reply, request);              reply->writeString8(defaultUrl);              reply->writeInt32(result); @@ -576,8 +609,13 @@ status_t BnDrm::onTransact(          {              CHECK_INTERFACE(IDrm, data, reply);              Vector<uint8_t> response; +            Vector<uint8_t> certificate; +            Vector<uint8_t> wrappedKey;              readVector(data, response); -            reply->writeInt32(provideProvisionResponse(response)); +            status_t result = provideProvisionResponse(response, certificate, wrappedKey); +            writeVector(reply, certificate); +            writeVector(reply, wrappedKey); +            reply->writeInt32(result);              return OK;          } @@ -725,6 +763,20 @@ status_t BnDrm::onTransact(              return OK;          } +        case SIGN_RSA: +        { +            CHECK_INTERFACE(IDrm, data, reply); +            Vector<uint8_t> sessionId, message, wrappedKey, signature; +            readVector(data, sessionId); +            String8 algorithm = data.readString8(); +            readVector(data, message); +            readVector(data, wrappedKey); +            uint32_t result = signRSA(sessionId, algorithm, message, wrappedKey, signature); +            writeVector(reply, signature); +            reply->writeInt32(result); +            return OK; +        } +      case SET_LISTENER: {          CHECK_INTERFACE(IDrm, data, reply);          sp<IDrmClient> listener = diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp index 6a108ae..f004ca4 100644 --- a/media/libmedia/MemoryLeakTrackUtil.cpp +++ b/media/libmedia/MemoryLeakTrackUtil.cpp @@ -49,7 +49,7 @@ struct MyString8 {      }      void append(const char *s) { -        strcat(mPtr, s); +        strncat(mPtr, s, MAX_SIZE - size() - 1);      }      const char *string() const { @@ -60,6 +60,10 @@ struct MyString8 {          return strlen(mPtr);      } +    void clear() { +        *mPtr = '\0'; +    } +  private:      char *mPtr; @@ -139,6 +143,9 @@ void dumpMemoryAddresses(int fd)              }          } while (moved); +        write(fd, result.string(), result.size()); +        result.clear(); +          for (size_t i = 0; i < count; i++) {              AllocEntry *e = &entries[i]; @@ -152,13 +159,14 @@ void dumpMemoryAddresses(int fd)                  result.append(buffer);              }              result.append("\n"); + +            write(fd, result.string(), result.size()); +            result.clear();          }          delete[] entries;          free_malloc_leak_info(info);      } - -    write(fd, result.string(), result.size());  }  #else diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp index eebcb79..d50037f 100644 --- a/media/libmediaplayerservice/Drm.cpp +++ b/media/libmediaplayerservice/Drm.cpp @@ -28,9 +28,21 @@  #include <media/stagefright/foundation/AString.h>  #include <media/stagefright/foundation/hexdump.h>  #include <media/stagefright/MediaErrors.h> +#include <binder/IServiceManager.h> +#include <binder/IPCThreadState.h>  namespace android { +static bool checkPermission(const char* permissionString) { +#ifndef HAVE_ANDROID_OS +    return true; +#endif +    if (getpid() == IPCThreadState::self()->getCallingPid()) return true; +    bool ok = checkCallingPermission(String16(permissionString)); +    if (!ok) ALOGE("Request requires %s", permissionString); +    return ok; +} +  KeyedVector<Vector<uint8_t>, String8> Drm::mUUIDToLibraryPathMap;  KeyedVector<String8, wp<SharedLibrary> > Drm::mLibraryPathToOpenLibraryMap;  Mutex Drm::mMapLock; @@ -373,7 +385,8 @@ status_t Drm::queryKeyStatus(Vector<uint8_t> const &sessionId,      return mPlugin->queryKeyStatus(sessionId, infoMap);  } -status_t Drm::getProvisionRequest(Vector<uint8_t> &request, String8 &defaultUrl) { +status_t Drm::getProvisionRequest(String8 const &certType, String8 const &certAuthority, +                                  Vector<uint8_t> &request, String8 &defaultUrl) {      Mutex::Autolock autoLock(mLock);      if (mInitCheck != OK) { @@ -384,10 +397,13 @@ status_t Drm::getProvisionRequest(Vector<uint8_t> &request, String8 &defaultUrl)          return -EINVAL;      } -    return mPlugin->getProvisionRequest(request, defaultUrl); +    return mPlugin->getProvisionRequest(certType, certAuthority, +                                        request, defaultUrl);  } -status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response) { +status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response, +                                       Vector<uint8_t> &certificate, +                                       Vector<uint8_t> &wrappedKey) {      Mutex::Autolock autoLock(mLock);      if (mInitCheck != OK) { @@ -398,7 +414,7 @@ status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response) {          return -EINVAL;      } -    return mPlugin->provideProvisionResponse(response); +    return mPlugin->provideProvisionResponse(response, certificate, wrappedKey);  } @@ -589,6 +605,28 @@ status_t Drm::verify(Vector<uint8_t> const &sessionId,      return mPlugin->verify(sessionId, keyId, message, signature, match);  } +status_t Drm::signRSA(Vector<uint8_t> const &sessionId, +                      String8 const &algorithm, +                      Vector<uint8_t> const &message, +                      Vector<uint8_t> const &wrappedKey, +                      Vector<uint8_t> &signature) { +    Mutex::Autolock autoLock(mLock); + +    if (mInitCheck != OK) { +        return mInitCheck; +    } + +    if (mPlugin == NULL) { +        return -EINVAL; +    } + +    if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) { +        return -EPERM; +    } + +    return mPlugin->signRSA(sessionId, algorithm, message, wrappedKey, signature); +} +  void Drm::binderDied(const wp<IBinder> &the_late_who)  {      delete mPlugin; diff --git a/media/libmediaplayerservice/Drm.h b/media/libmediaplayerservice/Drm.h index 119fd50..3d4b0fc 100644 --- a/media/libmediaplayerservice/Drm.h +++ b/media/libmediaplayerservice/Drm.h @@ -66,10 +66,14 @@ struct Drm : public BnDrm,      virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,                                      KeyedVector<String8, String8> &infoMap) const; -    virtual status_t getProvisionRequest(Vector<uint8_t> &request, +    virtual status_t getProvisionRequest(String8 const &certType, +                                         String8 const &certAuthority, +                                         Vector<uint8_t> &request,                                           String8 &defaulUrl); -    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response); +    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response, +                                              Vector<uint8_t> &certificate, +                                              Vector<uint8_t> &wrappedKey);      virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops); @@ -111,6 +115,12 @@ struct Drm : public BnDrm,                              Vector<uint8_t> const &signature,                              bool &match); +    virtual status_t signRSA(Vector<uint8_t> const &sessionId, +                             String8 const &algorithm, +                             Vector<uint8_t> const &message, +                             Vector<uint8_t> const &wrappedKey, +                             Vector<uint8_t> &signature); +      virtual status_t setListener(const sp<IDrmClient>& listener);      virtual void sendEvent(DrmPlugin::EventType eventType, int extra, diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index f710b55..25d55a3 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -32,6 +32,8 @@  #include "ATSParser.h" +#include "SoftwareRenderer.h" +  #include <cutils/properties.h> // for property_get  #include <media/stagefright/foundation/hexdump.h>  #include <media/stagefright/foundation/ABuffer.h> @@ -146,6 +148,7 @@ NuPlayer::NuPlayer()      : mUIDValid(false),        mSourceFlags(0),        mVideoIsAVC(false), +      mNeedsSwRenderer(false),        mAudioEOS(false),        mVideoEOS(false),        mScanSourcesPending(false), @@ -444,6 +447,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {              ALOGV("kWhatStart");              mVideoIsAVC = false; +            mNeedsSwRenderer = false;              mAudioEOS = false;              mVideoEOS = false;              mSkipRenderingAudioUntilMediaTimeUs = -1; @@ -680,6 +684,20 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {                      notifyListener(                              MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight); + +                    if (mNeedsSwRenderer && mNativeWindow != NULL) { +                        int32_t colorFormat; +                        CHECK(codecRequest->findInt32("color-format", &colorFormat)); + +                        sp<MetaData> meta = new MetaData; +                        meta->setInt32(kKeyWidth, width); +                        meta->setInt32(kKeyHeight, height); +                        meta->setRect(kKeyCropRect, cropLeft, cropTop, cropRight, cropBottom); +                        meta->setInt32(kKeyColorFormat, colorFormat); + +                        mRenderer->setSoftRenderer( +                                new SoftwareRenderer(mNativeWindow->getNativeWindow(), meta)); +                    }                  }              } else if (what == ACodec::kWhatShutdownCompleted) {                  ALOGV("%s shutdown completed", audio ? "audio" : "video"); @@ -703,8 +721,13 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {                  mRenderer->queueEOS(audio, UNKNOWN_ERROR);              } else if (what == ACodec::kWhatDrainThisBuffer) {                  renderBuffer(audio, codecRequest); -            } else if (what != ACodec::kWhatComponentAllocated -                    && what != ACodec::kWhatComponentConfigured +            } else if (what == ACodec::kWhatComponentAllocated) { +                if (!audio) { +                    AString name; +                    CHECK(codecRequest->findString("componentName", &name)); +                    mNeedsSwRenderer = name.startsWith("OMX.google."); +                } +            } else if (what != ACodec::kWhatComponentConfigured                      && what != ACodec::kWhatBuffersAllocated) {                  ALOGV("Unhandled codec notification %d '%c%c%c%c'.",                        what, diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index 13350f3..590e1f2 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -116,6 +116,7 @@ private:      sp<MediaPlayerBase::AudioSink> mAudioSink;      sp<Decoder> mVideoDecoder;      bool mVideoIsAVC; +    bool mNeedsSwRenderer;      sp<Decoder> mAudioDecoder;      sp<Renderer> mRenderer; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 3b2784b..bf5271e 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -20,6 +20,8 @@  #include "NuPlayerRenderer.h" +#include "SoftwareRenderer.h" +  #include <media/stagefright/foundation/ABuffer.h>  #include <media/stagefright/foundation/ADebug.h>  #include <media/stagefright/foundation/AMessage.h> @@ -34,6 +36,7 @@ NuPlayer::Renderer::Renderer(          const sp<AMessage> ¬ify,          uint32_t flags)      : mAudioSink(sink), +      mSoftRenderer(NULL),        mNotify(notify),        mFlags(flags),        mNumFramesWritten(0), @@ -57,6 +60,12 @@ NuPlayer::Renderer::Renderer(  }  NuPlayer::Renderer::~Renderer() { +    delete mSoftRenderer; +} + +void NuPlayer::Renderer::setSoftRenderer(SoftwareRenderer *softRenderer) { +    delete mSoftRenderer; +    mSoftRenderer = softRenderer;  }  void NuPlayer::Renderer::queueBuffer( @@ -413,7 +422,12 @@ void NuPlayer::Renderer::onDrainVideoQueue() {          ALOGV("video late by %lld us (%.2f secs)",               mVideoLateByUs, mVideoLateByUs / 1E6);      } else { -        ALOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6); +        ALOGV("rendering video at media time %.2f secs", +                (mFlags & FLAG_REAL_TIME ? realTimeUs : +                (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6); +        if (mSoftRenderer != NULL) { +            mSoftRenderer->render(entry->mBuffer->data(), entry->mBuffer->size(), NULL); +        }      }      entry->mNotifyConsumed->setInt32("render", !tooLate); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h index 94a05ea..9124e03 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h @@ -23,6 +23,7 @@  namespace android {  struct ABuffer; +class SoftwareRenderer;  struct NuPlayer::Renderer : public AHandler {      enum Flags { @@ -56,6 +57,8 @@ struct NuPlayer::Renderer : public AHandler {          kWhatMediaRenderingStart = 'mdrd',      }; +    void setSoftRenderer(SoftwareRenderer *softRenderer); +  protected:      virtual ~Renderer(); @@ -83,6 +86,7 @@ private:      static const int64_t kMinPositionUpdateDelayUs;      sp<MediaPlayerBase::AudioSink> mAudioSink; +    SoftwareRenderer *mSoftRenderer;      sp<AMessage> mNotify;      uint32_t mFlags;      List<QueueEntry> mAudioQueue; diff --git a/media/libnbaio/MonoPipe.cpp b/media/libnbaio/MonoPipe.cpp index de0ad28..3c61b60 100644 --- a/media/libnbaio/MonoPipe.cpp +++ b/media/libnbaio/MonoPipe.cpp @@ -183,7 +183,7 @@ ssize_t MonoPipe::write(const void *buffer, size_t count)              }          }          if (ns > 0) { -            const struct timespec req = {0, ns}; +            const struct timespec req = {0, static_cast<long>(ns)};              nanosleep(&req, NULL);          }          // record the time that this write() completed diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 718e6c7..67a19cd 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -35,7 +35,9 @@  #include <media/hardware/HardwareAPI.h> +#include <OMX_AudioExt.h>  #include <OMX_Component.h> +#include <OMX_IndexExt.h>  #include "include/avc_utils.h" @@ -990,6 +992,10 @@ status_t ACodec::setComponentRole(              "audio_decoder.flac", "audio_encoder.flac" },          { MEDIA_MIMETYPE_AUDIO_MSGSM,              "audio_decoder.gsm", "audio_encoder.gsm" }, +        { MEDIA_MIMETYPE_VIDEO_MPEG2, +            "video_decoder.mpeg2", "video_encoder.mpeg2" }, +        { MEDIA_MIMETYPE_AUDIO_AC3, +            "audio_decoder.ac3", "audio_encoder.ac3" },      };      static const size_t kNumMimeToRole = @@ -1288,6 +1294,15 @@ status_t ACodec::configureCodec(          } else {              err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);          } +    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) { +        int32_t numChannels; +        int32_t sampleRate; +        if (!msg->findInt32("channel-count", &numChannels) +                || !msg->findInt32("sample-rate", &sampleRate)) { +            err = INVALID_OPERATION; +        } else { +            err = setupAC3Codec(encoder, numChannels, sampleRate); +        }      }      if (err != OK) { @@ -1484,6 +1499,44 @@ status_t ACodec::setupAACCodec(              mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));  } +status_t ACodec::setupAC3Codec( +        bool encoder, int32_t numChannels, int32_t sampleRate) { +    status_t err = setupRawAudioFormat( +            encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels); + +    if (err != OK) { +        return err; +    } + +    if (encoder) { +        ALOGW("AC3 encoding is not supported."); +        return INVALID_OPERATION; +    } + +    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def; +    InitOMXParams(&def); +    def.nPortIndex = kPortIndexInput; + +    err = mOMX->getParameter( +            mNode, +            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, +            &def, +            sizeof(def)); + +    if (err != OK) { +        return err; +    } + +    def.nChannels = numChannels; +    def.nSampleRate = sampleRate; + +    return mOMX->setParameter( +            mNode, +            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, +            &def, +            sizeof(def)); +} +  static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(          bool isAMRWB, int32_t bps) {      if (isAMRWB) { @@ -2578,7 +2631,7 @@ void ACodec::sendFormatChange(const sp<AMessage> &reply) {          {              OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio; -            switch (audioDef->eEncoding) { +            switch ((int)audioDef->eEncoding) {                  case OMX_AUDIO_CodingPCM:                  {                      OMX_AUDIO_PARAM_PCMMODETYPE params; @@ -2684,6 +2737,24 @@ void ACodec::sendFormatChange(const sp<AMessage> &reply) {                      break;                  } +                case OMX_AUDIO_CodingAndroidAC3: +                { +                    OMX_AUDIO_PARAM_ANDROID_AC3TYPE params; +                    InitOMXParams(¶ms); +                    params.nPortIndex = kPortIndexOutput; + +                    CHECK_EQ((status_t)OK, mOMX->getParameter( +                            mNode, +                            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, +                            ¶ms, +                            sizeof(params))); + +                    notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3); +                    notify->setInt32("channel-count", params.nChannels); +                    notify->setInt32("sample-rate", params.nSampleRate); +                    break; +                } +                  default:                      TRESPASS();              } diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 130207d..aae6800 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -2096,7 +2096,10 @@ void AwesomePlayer::onCheckAudioStatus() {              mSeekNotificationSent = true;          } -        mSeeking = NO_SEEK; +        if (mVideoSource == NULL) { +            // For video the mSeeking flag is always reset in finishSeekIfNecessary +            mSeeking = NO_SEEK; +        }          notifyIfMediaStarted_l();      } diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 8ca45ad..9366a51 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -39,6 +39,9 @@  #include <media/stagefright/MetaData.h>  #include <utils/String8.h> +#include <byteswap.h> +#include "include/ID3.h" +  #ifndef UINT32_MAX  #define UINT32_MAX       (4294967295U)  #endif @@ -689,7 +692,7 @@ status_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) {              }              data_offset += 2; -            if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) { +            if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) {                  return ERROR_IO;              }              data_offset += sinf->len; @@ -1658,7 +1661,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {          case FOURCC('d', 'a', 't', 'a'):          {              if (mPath.size() == 6 && underMetaDataPath(mPath)) { -                status_t err = parseMetaData(data_offset, chunk_data_size); +                status_t err = parseITunesMetaData(data_offset, chunk_data_size);                  if (err != OK) {                      return err; @@ -1804,6 +1807,35 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {              break;          } +        case FOURCC('t', 'i', 't', 'l'): +        case FOURCC('p', 'e', 'r', 'f'): +        case FOURCC('a', 'u', 't', 'h'): +        case FOURCC('g', 'n', 'r', 'e'): +        case FOURCC('a', 'l', 'b', 'm'): +        case FOURCC('y', 'r', 'r', 'c'): +        { +            status_t err = parse3GPPMetaData(data_offset, chunk_data_size, depth); + +            if (err != OK) { +                return err; +            } + +            *offset += chunk_size; +            break; +        } + +        case FOURCC('I', 'D', '3', '2'): +        { +            if (chunk_data_size < 6) { +                return ERROR_MALFORMED; +            } + +            parseID3v2MetaData(data_offset + 6); + +            *offset += chunk_size; +            break; +        } +          case FOURCC('-', '-', '-', '-'):          {              mLastCommentMean.clear(); @@ -2038,7 +2070,7 @@ status_t MPEG4Extractor::parseTrackHeader(      return OK;  } -status_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) { +status_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {      if (size < 4 || size == SIZE_MAX) {          return ERROR_MALFORMED;      } @@ -2187,7 +2219,7 @@ status_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {              break;      } -    if (size >= 8 && metadataKey) { +    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {          if (metadataKey == kKeyAlbumArt) {              mFileMetaData->setData(                      kKeyAlbumArt, MetaData::TYPE_NONE, @@ -2228,6 +2260,170 @@ status_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {      return OK;  } +status_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) { +    if (size < 4) { +        return ERROR_MALFORMED; +    } + +    uint8_t *buffer = new uint8_t[size]; +    if (mDataSource->readAt( +                offset, buffer, size) != (ssize_t)size) { +        delete[] buffer; +        buffer = NULL; + +        return ERROR_IO; +    } + +    uint32_t metadataKey = 0; +    switch (mPath[depth]) { +        case FOURCC('t', 'i', 't', 'l'): +        { +            metadataKey = kKeyTitle; +            break; +        } +        case FOURCC('p', 'e', 'r', 'f'): +        { +            metadataKey = kKeyArtist; +            break; +        } +        case FOURCC('a', 'u', 't', 'h'): +        { +            metadataKey = kKeyWriter; +            break; +        } +        case FOURCC('g', 'n', 'r', 'e'): +        { +            metadataKey = kKeyGenre; +            break; +        } +        case FOURCC('a', 'l', 'b', 'm'): +        { +            if (buffer[size - 1] != '\0') { +              char tmp[4]; +              sprintf(tmp, "%u", buffer[size - 1]); + +              mFileMetaData->setCString(kKeyCDTrackNumber, tmp); +            } + +            metadataKey = kKeyAlbum; +            break; +        } +        case FOURCC('y', 'r', 'r', 'c'): +        { +            char tmp[5]; +            uint16_t year = U16_AT(&buffer[4]); + +            if (year < 10000) { +                sprintf(tmp, "%u", year); + +                mFileMetaData->setCString(kKeyYear, tmp); +            } +            break; +        } + +        default: +            break; +    } + +    if (metadataKey > 0) { +        bool isUTF8 = true; // Common case +        char16_t *framedata = NULL; +        int len16 = 0; // Number of UTF-16 characters + +        // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00 +        if (size - 6 >= 4) { +            len16 = ((size - 6) / 2) - 1; // don't include 0x0000 terminator +            framedata = (char16_t *)(buffer + 6); +            if (0xfffe == *framedata) { +                // endianness marker (BOM) doesn't match host endianness +                for (int i = 0; i < len16; i++) { +                    framedata[i] = bswap_16(framedata[i]); +                } +                // BOM is now swapped to 0xfeff, we will execute next block too +            } + +            if (0xfeff == *framedata) { +                // Remove the BOM +                framedata++; +                len16--; +                isUTF8 = false; +            } +            // else normal non-zero-length UTF-8 string +            // we can't handle UTF-16 without BOM as there is no other +            // indication of encoding. +        } + +        if (isUTF8) { +            mFileMetaData->setCString(metadataKey, (const char *)buffer + 6); +        } else { +            // Convert from UTF-16 string to UTF-8 string. +            String8 tmpUTF8str(framedata, len16); +            mFileMetaData->setCString(metadataKey, tmpUTF8str.string()); +        } +    } + +    delete[] buffer; +    buffer = NULL; + +    return OK; +} + +void MPEG4Extractor::parseID3v2MetaData(off64_t offset) { +    ID3 id3(mDataSource, true /* ignorev1 */, offset); + +    if (id3.isValid()) { +        struct Map { +            int key; +            const char *tag1; +            const char *tag2; +        }; +        static const Map kMap[] = { +            { kKeyAlbum, "TALB", "TAL" }, +            { kKeyArtist, "TPE1", "TP1" }, +            { kKeyAlbumArtist, "TPE2", "TP2" }, +            { kKeyComposer, "TCOM", "TCM" }, +            { kKeyGenre, "TCON", "TCO" }, +            { kKeyTitle, "TIT2", "TT2" }, +            { kKeyYear, "TYE", "TYER" }, +            { kKeyAuthor, "TXT", "TEXT" }, +            { kKeyCDTrackNumber, "TRK", "TRCK" }, +            { kKeyDiscNumber, "TPA", "TPOS" }, +            { kKeyCompilation, "TCP", "TCMP" }, +        }; +        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); + +        for (size_t i = 0; i < kNumMapEntries; ++i) { +            if (!mFileMetaData->hasData(kMap[i].key)) { +                ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1); +                if (it->done()) { +                    delete it; +                    it = new ID3::Iterator(id3, kMap[i].tag2); +                } + +                if (it->done()) { +                    delete it; +                    continue; +                } + +                String8 s; +                it->getString(&s); +                delete it; + +                mFileMetaData->setCString(kMap[i].key, s); +            } +        } + +        size_t dataSize; +        String8 mime; +        const void *data = id3.getAlbumArt(&dataSize, &mime); + +        if (data) { +            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize); +            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string()); +        } +    } +} +  sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {      status_t err;      if ((err = readMetaData()) != OK) { diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index c36dd7c..8af1aaf 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -746,6 +746,10 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {                              CHECK(msg->findInt32("width", &width));                              CHECK(msg->findInt32("height", &height)); +                            int32_t cropLeft, cropTop, cropRight, cropBottom; +                            CHECK(msg->findRect("crop", +                                &cropLeft, &cropTop, &cropRight, &cropBottom)); +                              int32_t colorFormat;                              CHECK(msg->findInt32(                                          "color-format", &colorFormat)); @@ -753,6 +757,8 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {                              sp<MetaData> meta = new MetaData;                              meta->setInt32(kKeyWidth, width);                              meta->setInt32(kKeyHeight, height); +                            meta->setRect(kKeyCropRect, +                                cropLeft, cropTop, cropRight, cropBottom);                              meta->setInt32(kKeyColorFormat, colorFormat);                              mSoftRenderer = diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp index 6248e90..b74b2e2 100644 --- a/media/libstagefright/MediaCodecList.cpp +++ b/media/libstagefright/MediaCodecList.cpp @@ -57,15 +57,6 @@ MediaCodecList::MediaCodecList()      parseXMLFile(file); -    if (mInitCheck == OK) { -        // These are currently still used by the video editing suite. - -        addMediaCodec(true /* encoder */, "AACEncoder", "audio/mp4a-latm"); - -        addMediaCodec( -                false /* encoder */, "OMX.google.raw.decoder", "audio/raw"); -    } -  #if 0      for (size_t i = 0; i < mCodecInfos.size(); ++i) {          const CodecInfo &info = mCodecInfos.itemAt(i); diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp index b5d4e44..340cba7 100644 --- a/media/libstagefright/MediaDefs.cpp +++ b/media/libstagefright/MediaDefs.cpp @@ -42,6 +42,7 @@ const char *MEDIA_MIMETYPE_AUDIO_RAW = "audio/raw";  const char *MEDIA_MIMETYPE_AUDIO_FLAC = "audio/flac";  const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS = "audio/aac-adts";  const char *MEDIA_MIMETYPE_AUDIO_MSGSM = "audio/gsm"; +const char *MEDIA_MIMETYPE_AUDIO_AC3 = "audio/ac3";  const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4";  const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav"; diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp index 2264a23..725f97e 100644 --- a/media/libstagefright/MetaData.cpp +++ b/media/libstagefright/MetaData.cpp @@ -221,6 +221,16 @@ bool MetaData::findData(uint32_t key, uint32_t *type,      return true;  } +bool MetaData::hasData(uint32_t key) const { +    ssize_t i = mItems.indexOfKey(key); + +    if (i < 0) { +        return false; +    } + +    return true; +} +  MetaData::typed_data::typed_data()      : mType(0),        mSize(0) { diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 43736ad..625922f 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -40,7 +40,9 @@  #include <utils/Vector.h>  #include <OMX_Audio.h> +#include <OMX_AudioExt.h>  #include <OMX_Component.h> +#include <OMX_IndexExt.h>  #include "include/avc_utils.h" @@ -528,6 +530,17 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {                      sampleRate,                      numChannels);          } +    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AC3, mMIME)) { +        int32_t numChannels; +        int32_t sampleRate; +        CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); +        CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); + +        status_t err = setAC3Format(numChannels, sampleRate); +        if (err != OK) { +            CODEC_LOGE("setAC3Format() failed (err = %d)", err); +            return err; +        }      } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_ALAW, mMIME)              || !strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_MLAW, mMIME)) {          // These are PCM-like formats with a fixed sample rate but @@ -1394,6 +1407,10 @@ void OMXCodec::setComponentRole(              "audio_decoder.flac", "audio_encoder.flac" },          { MEDIA_MIMETYPE_AUDIO_MSGSM,              "audio_decoder.gsm", "audio_encoder.gsm" }, +        { MEDIA_MIMETYPE_VIDEO_MPEG2, +            "video_decoder.mpeg2", "video_encoder.mpeg2" }, +        { MEDIA_MIMETYPE_AUDIO_AC3, +            "audio_decoder.ac3", "audio_encoder.ac3" },      };      static const size_t kNumMimeToRole = @@ -3489,6 +3506,31 @@ status_t OMXCodec::setAACFormat(      return OK;  } +status_t OMXCodec::setAC3Format(int32_t numChannels, int32_t sampleRate) { +    OMX_AUDIO_PARAM_ANDROID_AC3TYPE def; +    InitOMXParams(&def); +    def.nPortIndex = kPortIndexInput; + +    status_t err = mOMX->getParameter( +            mNode, +            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, +            &def, +            sizeof(def)); + +    if (err != OK) { +        return err; +    } + +    def.nChannels = numChannels; +    def.nSampleRate = sampleRate; + +    return mOMX->setParameter( +            mNode, +            (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3, +            &def, +            sizeof(def)); +} +  void OMXCodec::setG711Format(int32_t numChannels) {      CHECK(!mIsEncoder);      setRawAudioFormat(kPortIndexInput, 8000, numChannels); @@ -4422,6 +4464,17 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {                  mOutputFormat->setInt32(kKeyChannelCount, numChannels);                  mOutputFormat->setInt32(kKeySampleRate, sampleRate);                  mOutputFormat->setInt32(kKeyBitRate, bitRate); +            } else if (audio_def->eEncoding == +                    (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidAC3) { +                mOutputFormat->setCString( +                        kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3); +                int32_t numChannels, sampleRate, bitRate; +                inputFormat->findInt32(kKeyChannelCount, &numChannels); +                inputFormat->findInt32(kKeySampleRate, &sampleRate); +                inputFormat->findInt32(kKeyBitRate, &bitRate); +                mOutputFormat->setInt32(kKeyChannelCount, numChannels); +                mOutputFormat->setInt32(kKeySampleRate, sampleRate); +                mOutputFormat->setInt32(kKeyBitRate, bitRate);              } else {                  CHECK(!"Should not be here. Unknown audio encoding.");              } diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp index dedd186..0afac69 100644 --- a/media/libstagefright/TimedEventQueue.cpp +++ b/media/libstagefright/TimedEventQueue.cpp @@ -318,7 +318,7 @@ sp<TimedEventQueue::Event> TimedEventQueue::removeEventFromQueue_l(  void TimedEventQueue::acquireWakeLock_l()  { -    if (mWakeLockCount++ == 0) { +    if (mWakeLockCount == 0) {          CHECK(mWakeLockToken == 0);          if (mPowerManager == 0) {              // use checkService() to avoid blocking if power service is not up yet @@ -341,21 +341,23 @@ void TimedEventQueue::acquireWakeLock_l()              IPCThreadState::self()->restoreCallingIdentity(token);              if (status == NO_ERROR) {                  mWakeLockToken = binder; +                mWakeLockCount++;              }          } +    } else { +        mWakeLockCount++;      }  }  void TimedEventQueue::releaseWakeLock_l(bool force)  { +    if (mWakeLockCount == 0) { +        return; +    }      if (force) { -        if (mWakeLockCount == 0) { -            return; -        }          // Force wakelock release below by setting reference count to 1.          mWakeLockCount = 1;      } -    CHECK(mWakeLockCount != 0);      if (--mWakeLockCount == 0) {          CHECK(mWakeLockToken != 0);          if (mPowerManager != 0) { diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp index 5ae80cc..bc48272 100644 --- a/media/libstagefright/WVMExtractor.cpp +++ b/media/libstagefright/WVMExtractor.cpp @@ -76,7 +76,7 @@ static void init_routine()  {      gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);      if (gVendorLibHandle == NULL) { -        ALOGE("Failed to open libwvm.so"); +        ALOGE("Failed to open libwvm.so: %s", dlerror());      }  } diff --git a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp index 4e11628..e2b9e4f 100644 --- a/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp +++ b/media/libstagefright/codecs/avc/enc/SoftAVCEncoder.cpp @@ -887,7 +887,13 @@ void SoftAVCEncoder::onQueueFilled(OMX_U32 portIndex) {          CHECK(encoderStatus == AVCENC_SUCCESS || encoderStatus == AVCENC_NEW_IDR);          dataLength = outHeader->nAllocLen;  // Reset the output buffer length          if (inHeader->nFilledLen > 0) { +            if (outHeader->nAllocLen >= 4) { +                memcpy(outPtr, "\x00\x00\x00\x01", 4); +                outPtr += 4; +                dataLength -= 4; +            }              encoderStatus = PVAVCEncodeNAL(mHandle, outPtr, &dataLength, &type); +            dataLength = outPtr + dataLength - outHeader->pBuffer;              if (encoderStatus == AVCENC_SUCCESS) {                  CHECK(NULL == PVAVCEncGetOverrunBuffer(mHandle));              } else if (encoderStatus == AVCENC_PICTURE_READY) { diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp index f211bc8..e31ad40 100644 --- a/media/libstagefright/httplive/M3UParser.cpp +++ b/media/libstagefright/httplive/M3UParser.cpp @@ -626,7 +626,7 @@ status_t M3UParser::parseMetaDataDuration(      if (meta->get() == NULL) {          *meta = new AMessage;      } -    (*meta)->setInt64(key, (int64_t)x * 1E6); +    (*meta)->setInt64(key, (int64_t)(x * 1E6));      return OK;  } diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp index 751b810..8dcecbb 100644 --- a/media/libstagefright/id3/ID3.cpp +++ b/media/libstagefright/id3/ID3.cpp @@ -56,14 +56,14 @@ private:      DISALLOW_EVIL_CONSTRUCTORS(MemorySource);  }; -ID3::ID3(const sp<DataSource> &source, bool ignoreV1) +ID3::ID3(const sp<DataSource> &source, bool ignoreV1, off64_t offset)      : mIsValid(false),        mData(NULL),        mSize(0),        mFirstFrameOffset(0),        mVersion(ID3_UNKNOWN),        mRawSize(0) { -    mIsValid = parseV2(source); +    mIsValid = parseV2(source, offset);      if (!mIsValid && !ignoreV1) {          mIsValid = parseV1(source); @@ -79,7 +79,7 @@ ID3::ID3(const uint8_t *data, size_t size, bool ignoreV1)        mRawSize(0) {      sp<MemorySource> source = new MemorySource(data, size); -    mIsValid = parseV2(source); +    mIsValid = parseV2(source, 0);      if (!mIsValid && !ignoreV1) {          mIsValid = parseV1(source); @@ -115,7 +115,7 @@ bool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) {      return true;  } -bool ID3::parseV2(const sp<DataSource> &source) { +bool ID3::parseV2(const sp<DataSource> &source, off64_t offset) {  struct id3_header {      char id[3];      uint8_t version_major; @@ -126,7 +126,7 @@ struct id3_header {      id3_header header;      if (source->readAt( -                0, &header, sizeof(header)) != (ssize_t)sizeof(header)) { +                offset, &header, sizeof(header)) != (ssize_t)sizeof(header)) {          return false;      } @@ -185,7 +185,7 @@ struct id3_header {      mSize = size;      mRawSize = mSize + sizeof(header); -    if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) { +    if (source->readAt(offset + sizeof(header), mData, mSize) != (ssize_t)mSize) {          free(mData);          mData = NULL; diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h index cca83ab..e83f3ef 100644 --- a/media/libstagefright/include/ID3.h +++ b/media/libstagefright/include/ID3.h @@ -35,7 +35,7 @@ struct ID3 {          ID3_V2_4,      }; -    ID3(const sp<DataSource> &source, bool ignoreV1 = false); +    ID3(const sp<DataSource> &source, bool ignoreV1 = false, off64_t offset = 0);      ID3(const uint8_t *data, size_t size, bool ignoreV1 = false);      ~ID3(); @@ -86,7 +86,7 @@ private:      size_t mRawSize;      bool parseV1(const sp<DataSource> &source); -    bool parseV2(const sp<DataSource> &source); +    bool parseV2(const sp<DataSource> &source, off64_t offset);      void removeUnsynchronization();      bool removeUnsynchronizationV2_4(bool iTunesHack); diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h index bbec1c4..7b4bc6d 100644 --- a/media/libstagefright/include/MPEG4Extractor.h +++ b/media/libstagefright/include/MPEG4Extractor.h @@ -95,7 +95,9 @@ private:      status_t readMetaData();      status_t parseChunk(off64_t *offset, int depth); -    status_t parseMetaData(off64_t offset, size_t size); +    status_t parseITunesMetaData(off64_t offset, size_t size); +    status_t parse3GPPMetaData(off64_t offset, size_t size, int depth); +    void parseID3v2MetaData(off64_t offset);      status_t updateAudioTrackInfoFromESDS_MPEG4Audio(              const void *esds_data, size_t esds_size); diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp index 175a263..cb57a2f 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.cpp +++ b/media/libstagefright/mpeg2ts/ATSParser.cpp @@ -506,6 +506,11 @@ ATSParser::Stream::Stream(                      ElementaryStreamQueue::PCM_AUDIO);              break; +        case STREAMTYPE_AC3: +            mQueue = new ElementaryStreamQueue( +                    ElementaryStreamQueue::AC3); +            break; +          default:              break;      } @@ -614,6 +619,7 @@ bool ATSParser::Stream::isAudio() const {          case STREAMTYPE_MPEG2_AUDIO:          case STREAMTYPE_MPEG2_AUDIO_ADTS:          case STREAMTYPE_PCM_AUDIO: +        case STREAMTYPE_AC3:              return true;          default: diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h index 8a80069..86b025f 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.h +++ b/media/libstagefright/mpeg2ts/ATSParser.h @@ -89,6 +89,10 @@ struct ATSParser : public RefBase {          STREAMTYPE_MPEG2_AUDIO_ADTS     = 0x0f,          STREAMTYPE_MPEG4_VIDEO          = 0x10,          STREAMTYPE_H264                 = 0x1b, + +        // From ATSC A/53 Part 3:2009, 6.7.1 +        STREAMTYPE_AC3                  = 0x81, +          STREAMTYPE_PCM_AUDIO            = 0x83,      }; diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp index 8f9c9c8..2b0711b 100644 --- a/media/libstagefright/mpeg2ts/ESQueue.cpp +++ b/media/libstagefright/mpeg2ts/ESQueue.cpp @@ -56,6 +56,122 @@ void ElementaryStreamQueue::clear(bool clearFormat) {      }  } +// Parse AC3 header assuming the current ptr is start position of syncframe, +// update metadata only applicable, and return the payload size +static unsigned parseAC3SyncFrame( +        const uint8_t *ptr, size_t size, sp<MetaData> *metaData) { +    static const unsigned channelCountTable[] = {2, 1, 2, 3, 3, 4, 4, 5}; +    static const unsigned samplingRateTable[] = {48000, 44100, 32000}; +    static const unsigned rates[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, +            320, 384, 448, 512, 576, 640}; + +    static const unsigned frameSizeTable[19][3] = { +        { 64, 69, 96 }, +        { 80, 87, 120 }, +        { 96, 104, 144 }, +        { 112, 121, 168 }, +        { 128, 139, 192 }, +        { 160, 174, 240 }, +        { 192, 208, 288 }, +        { 224, 243, 336 }, +        { 256, 278, 384 }, +        { 320, 348, 480 }, +        { 384, 417, 576 }, +        { 448, 487, 672 }, +        { 512, 557, 768 }, +        { 640, 696, 960 }, +        { 768, 835, 1152 }, +        { 896, 975, 1344 }, +        { 1024, 1114, 1536 }, +        { 1152, 1253, 1728 }, +        { 1280, 1393, 1920 }, +    }; + +    ABitReader bits(ptr, size); +    unsigned syncStartPos = 0;  // in bytes +    if (bits.numBitsLeft() < 16) { +        return 0; +    } +    if (bits.getBits(16) != 0x0B77) { +        return 0; +    } + +    if (bits.numBitsLeft() < 16 + 2 + 6 + 5 + 3 + 3) { +        ALOGV("Not enough bits left for further parsing"); +        return 0; +    } +    bits.skipBits(16);  // crc1 + +    unsigned fscod = bits.getBits(2); +    if (fscod == 3) { +        ALOGW("Incorrect fscod in AC3 header"); +        return 0; +    } + +    unsigned frmsizecod = bits.getBits(6); +    if (frmsizecod > 37) { +        ALOGW("Incorrect frmsizecod in AC3 header"); +        return 0; +    } + +    unsigned bsid = bits.getBits(5); +    if (bsid > 8) { +        ALOGW("Incorrect bsid in AC3 header. Possibly E-AC-3?"); +        return 0; +    } + +    unsigned bsmod = bits.getBits(3); +    unsigned acmod = bits.getBits(3); +    unsigned cmixlev = 0; +    unsigned surmixlev = 0; +    unsigned dsurmod = 0; + +    if ((acmod & 1) > 0 && acmod != 1) { +        if (bits.numBitsLeft() < 2) { +            return 0; +        } +        cmixlev = bits.getBits(2); +    } +    if ((acmod & 4) > 0) { +        if (bits.numBitsLeft() < 2) { +            return 0; +        } +        surmixlev = bits.getBits(2); +    } +    if (acmod == 2) { +        if (bits.numBitsLeft() < 2) { +            return 0; +        } +        dsurmod = bits.getBits(2); +    } + +    if (bits.numBitsLeft() < 1) { +        return 0; +    } +    unsigned lfeon = bits.getBits(1); + +    unsigned samplingRate = samplingRateTable[fscod]; +    unsigned payloadSize = frameSizeTable[frmsizecod >> 1][fscod]; +    if (fscod == 1) { +        payloadSize += frmsizecod & 1; +    } +    payloadSize <<= 1;  // convert from 16-bit words to bytes + +    unsigned channelCount = channelCountTable[acmod] + lfeon; + +    if (metaData != NULL) { +        (*metaData)->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AC3); +        (*metaData)->setInt32(kKeyChannelCount, channelCount); +        (*metaData)->setInt32(kKeySampleRate, samplingRate); +    } + +    return payloadSize; +} + +static bool IsSeeminglyValidAC3Header(const uint8_t *ptr, size_t size) { +    return parseAC3SyncFrame(ptr, size, NULL) > 0; +} +  static bool IsSeeminglyValidADTSHeader(const uint8_t *ptr, size_t size) {      if (size < 3) {          // Not enough data to verify header. @@ -224,6 +340,33 @@ status_t ElementaryStreamQueue::appendData(                  break;              } +            case AC3: +            { +                uint8_t *ptr = (uint8_t *)data; + +                ssize_t startOffset = -1; +                for (size_t i = 0; i < size; ++i) { +                    if (IsSeeminglyValidAC3Header(&ptr[i], size - i)) { +                        startOffset = i; +                        break; +                    } +                } + +                if (startOffset < 0) { +                    return ERROR_MALFORMED; +                } + +                if (startOffset > 0) { +                    ALOGI("found something resembling an AC3 syncword at " +                          "offset %d", +                          startOffset); +                } + +                data = &ptr[startOffset]; +                size -= startOffset; +                break; +            } +              case MPEG_AUDIO:              {                  uint8_t *ptr = (uint8_t *)data; @@ -328,6 +471,8 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnit() {              return dequeueAccessUnitH264();          case AAC:              return dequeueAccessUnitAAC(); +        case AC3: +            return dequeueAccessUnitAC3();          case MPEG_VIDEO:              return dequeueAccessUnitMPEGVideo();          case MPEG4_VIDEO: @@ -340,6 +485,51 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnit() {      }  } +sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitAC3() { +    unsigned syncStartPos = 0;  // in bytes +    unsigned payloadSize = 0; +    sp<MetaData> format = new MetaData; +    while (true) { +        if (syncStartPos + 2 >= mBuffer->size()) { +            return NULL; +        } + +        payloadSize = parseAC3SyncFrame( +                mBuffer->data() + syncStartPos, +                mBuffer->size() - syncStartPos, +                &format); +        if (payloadSize > 0) { +            break; +        } +        ++syncStartPos; +    } + +    if (mBuffer->size() < syncStartPos + payloadSize) { +        ALOGV("Not enough buffer size for AC3"); +        return NULL; +    } + +    if (mFormat == NULL) { +        mFormat = format; +    } + +    sp<ABuffer> accessUnit = new ABuffer(syncStartPos + payloadSize); +    memcpy(accessUnit->data(), mBuffer->data(), syncStartPos + payloadSize); + +    int64_t timeUs = fetchTimestamp(syncStartPos + payloadSize); +    CHECK_GE(timeUs, 0ll); +    accessUnit->meta()->setInt64("timeUs", timeUs); + +    memmove( +            mBuffer->data(), +            mBuffer->data() + syncStartPos + payloadSize, +            mBuffer->size() - syncStartPos - payloadSize); + +    mBuffer->setRange(0, mBuffer->size() - syncStartPos - payloadSize); + +    return accessUnit; +} +  sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitPCMAudio() {      if (mBuffer->size() < 4) {          return NULL; diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h index 66a8087..a2cca77 100644 --- a/media/libstagefright/mpeg2ts/ESQueue.h +++ b/media/libstagefright/mpeg2ts/ESQueue.h @@ -32,6 +32,7 @@ struct ElementaryStreamQueue {      enum Mode {          H264,          AAC, +        AC3,          MPEG_AUDIO,          MPEG_VIDEO,          MPEG4_VIDEO, @@ -67,6 +68,7 @@ private:      sp<ABuffer> dequeueAccessUnitH264();      sp<ABuffer> dequeueAccessUnitAAC(); +    sp<ABuffer> dequeueAccessUnitAC3();      sp<ABuffer> dequeueAccessUnitMPEGAudio();      sp<ABuffer> dequeueAccessUnitMPEGVideo();      sp<ABuffer> dequeueAccessUnitMPEG4Video(); diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp index 5116550..efde7a9 100644 --- a/media/libstagefright/rtsp/ARTSPConnection.cpp +++ b/media/libstagefright/rtsp/ARTSPConnection.cpp @@ -489,7 +489,6 @@ void ARTSPConnection::onReceiveResponse() {      FD_SET(mSocket, &rs);      int res = select(mSocket + 1, &rs, NULL, NULL, &tv); -    CHECK_GE(res, 0);      if (res == 1) {          MakeSocketBlocking(mSocket, true); diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h index f4b5846..cd77aa0 100644 --- a/media/libstagefright/rtsp/MyHandler.h +++ b/media/libstagefright/rtsp/MyHandler.h @@ -686,23 +686,27 @@ struct MyHandler : public AHandler {                          i = response->mHeaders.indexOfKey("transport");                          CHECK_GE(i, 0); -                        if (!track->mUsingInterleavedTCP) { -                            AString transport = response->mHeaders.valueAt(i); - -                            // We are going to continue even if we were -                            // unable to poke a hole into the firewall... -                            pokeAHole( -                                    track->mRTPSocket, -                                    track->mRTCPSocket, -                                    transport); -                        } +                        if (track->mRTPSocket != -1 && track->mRTCPSocket != -1) { +                            if (!track->mUsingInterleavedTCP) { +                                AString transport = response->mHeaders.valueAt(i); + +                                // We are going to continue even if we were +                                // unable to poke a hole into the firewall... +                                pokeAHole( +                                        track->mRTPSocket, +                                        track->mRTCPSocket, +                                        transport); +                            } -                        mRTPConn->addStream( -                                track->mRTPSocket, track->mRTCPSocket, -                                mSessionDesc, index, -                                notify, track->mUsingInterleavedTCP); +                            mRTPConn->addStream( +                                    track->mRTPSocket, track->mRTCPSocket, +                                    mSessionDesc, index, +                                    notify, track->mUsingInterleavedTCP); -                        mSetupTracksSuccessful = true; +                            mSetupTracksSuccessful = true; +                        } else { +                            result = BAD_VALUE; +                        }                      }                  } @@ -726,7 +730,7 @@ struct MyHandler : public AHandler {                  }                  ++index; -                if (index < mSessionDesc->countTracks()) { +                if (result == OK && index < mSessionDesc->countTracks()) {                      setupTrack(index);                  } else if (mSetupTracksSuccessful) {                      ++mKeepAliveGeneration; @@ -1559,6 +1563,8 @@ private:          info->mUsingInterleavedTCP = false;          info->mFirstSeqNumInSegment = 0;          info->mNewSegment = true; +        info->mRTPSocket = -1; +        info->mRTCPSocket = -1;          info->mRTPAnchor = 0;          info->mNTPAnchorUs = -1;          info->mNormalPlayTimeRTP = 0; diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp index 930f0b0..c4f87a0 100644 --- a/media/mtp/MtpDataPacket.cpp +++ b/media/mtp/MtpDataPacket.cpp @@ -331,7 +331,7 @@ void MtpDataPacket::putString(const char* s) {  void MtpDataPacket::putString(const uint16_t* string) {      int count = 0; -    for (int i = 0; i < 256; i++) { +    for (int i = 0; i <= MTP_STRING_MAX_CHARACTER_NUMBER; i++) {          if (string[i])              count++;          else diff --git a/media/mtp/MtpStringBuffer.cpp b/media/mtp/MtpStringBuffer.cpp index fe8cf04..f3420a4 100644 --- a/media/mtp/MtpStringBuffer.cpp +++ b/media/mtp/MtpStringBuffer.cpp @@ -56,42 +56,47 @@ MtpStringBuffer::~MtpStringBuffer() {  }  void MtpStringBuffer::set(const char* src) { -    int length = strlen(src); -    if (length >= sizeof(mBuffer)) -        length = sizeof(mBuffer) - 1; -    memcpy(mBuffer, src, length); -      // count the characters      int count = 0;      char ch; -    while ((ch = *src++) != 0) { +    char* dest = (char*)mBuffer; + +    while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) {          if ((ch & 0x80) == 0) {              // single byte character +            *dest++ = ch;          } else if ((ch & 0xE0) == 0xC0) {              // two byte character -            if (! *src++) { +            char ch1 = *src++; +            if (! ch1) {                  // last character was truncated, so ignore last byte -                length--;                  break;              } + +            *dest++ = ch; +            *dest++ = ch1;          } else if ((ch & 0xF0) == 0xE0) {              // 3 byte char -            if (! *src++) { +            char ch1 = *src++; +            if (! ch1) {                  // last character was truncated, so ignore last byte -                length--;                  break;              } -            if (! *src++) { -                // last character was truncated, so ignore last two bytes -                length -= 2; +            char ch2 = *src++; +            if (! ch2) { +                // last character was truncated, so ignore last byte                  break;              } + +            *dest++ = ch; +            *dest++ = ch1; +            *dest++ = ch2;          }          count++;      } -    mByteCount = length + 1; -    mBuffer[length] = 0; +    *dest++ = 0; +    mByteCount = dest - (char*)mBuffer;      mCharCount = count;  } @@ -100,7 +105,7 @@ void MtpStringBuffer::set(const uint16_t* src) {      uint16_t ch;      uint8_t* dest = mBuffer; -    while ((ch = *src++) != 0 && count < 255) { +    while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) {          if (ch >= 0x0800) {              *dest++ = (uint8_t)(0xE0 | (ch >> 12));              *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F)); diff --git a/media/mtp/MtpStringBuffer.h b/media/mtp/MtpStringBuffer.h index cbc8307..e5150df 100644 --- a/media/mtp/MtpStringBuffer.h +++ b/media/mtp/MtpStringBuffer.h @@ -19,6 +19,9 @@  #include <stdint.h> +// Max Character number of a MTP String +#define MTP_STRING_MAX_CHARACTER_NUMBER             255 +  namespace android {  class MtpDataPacket; @@ -29,7 +32,7 @@ class MtpStringBuffer {  private:      // mBuffer contains string in UTF8 format      // maximum 3 bytes/character, with 1 extra for zero termination -    uint8_t         mBuffer[255 * 3 + 1]; +    uint8_t         mBuffer[MTP_STRING_MAX_CHARACTER_NUMBER * 3 + 1];      int             mCharCount;      int             mByteCount;  | 
