0

我已将 Android 中的默认媒体框架从 Stagefright 更改为 Gstreamer。这样做是为了使其对我们的项目具有灵活性。

但是当我运行一些 apk 时,应用程序的所有声音都在应用程序启动时播放,并且在显示来自 Soundpool 的错误“sample # not READY”之后它不会播放。例如,在 App Baby 钢琴中,当我启动应用程序时,会播放钢琴音节的声音,而当我在进入播放模式后实际点击钢琴时,它不会被播放。

我认为的问题是,当声音被加载到 Soundpool 中时,会创建 Gstreamer Mediaplayer 对象并播放它,并且它是在应用程序启动时完成的。

在它显示的日志中,Sample Channel Count(0) 超出范围。它发生在下面部分的 SoundPoool.cpp 文件中。

status_t Sample::doLoad() {
    uint32_t sampleRate;
    int numChannels;
    int format;
    sp<IMemory> p;
    LOGW("Start decode");
    if (mUrl) {
        p = MediaPlayer::decode(mUrl, &sampleRate, &numChannels, &format);
    } else {
        p = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format);
        LOGW("close(%d)", mFd);
        ::close(mFd);
        mFd = -1;
    }
    if (p == 0) {
        LOGE("Unable to load sample: %s", mUrl);
        return -1;
    }
    LOGW("pointer = %p, size = %u, sampleRate = %u, numChannels = %d",
            p->pointer(), p->size(), sampleRate, numChannels);

    if (sampleRate > kMaxSampleRate) {
       LOGE("Sample rate (%u) out of range", sampleRate);
       return - 1;
    }

    if ((numChannels < 1) || (numChannels > 2)) {
        LOGE("Sample channel count (%d) out of range", numChannels);
        return - 1;
    }

    //_dumpBuffer(p->pointer(), p->size());
    uint8_t* q = static_cast<uint8_t*>(p->pointer()) + p->size() - 10;
    //_dumpBuffer(q, 10, 10, false);

    mData = p;
    mSize = p->size();
    mSampleRate = sampleRate;
    mNumChannels = numChannels;
    mFormat = format;
    mState = READY;
    return 0; }

并且 MediaPlayerService 解码函数从下面的代码部分将所有值返回为 null

sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
{
    LOGD("decode(%d, %lld, %lld)", fd, offset, length);
    sp<MemoryBase> mem;
    sp<MediaPlayerBase> player;

    player_type playerType = getPlayerType(fd, offset, length);
    LOGD("player type = %d", playerType);

    // create the right type of player
    sp<AudioCache> cache = new AudioCache("decode_fd");
    player = android::createPlayer(playerType, cache.get(), cache->notify);
    if (player == NULL) goto Exit;
    if (player->hardwareOutput()) goto Exit;

    static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);

    // set data source
    if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit;

    LOGD("prepare");
    player->prepareAsync();

    LOGD("wait for prepare");
    if (cache->wait() != NO_ERROR) goto Exit;

    LOGD("start");
    player->start();

    LOGD("wait for playback complete");
    if (cache->wait() != NO_ERROR) goto Exit;

    mem = new MemoryBase(cache->getHeap(), 0, cache->size());
    *pSampleRate = cache->sampleRate();//Nes
    *pNumChannels = cache->channelCount();
    *pFormat = cache->format();

    LOGD("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);

Exit:
    if (player != 0) player->reset();
    ::close(fd);
    return mem;
}

该函数返回的采样率、通道等的值为 0。

在此之后,当播放样本时,它显示错误““样本#未就绪”

int SoundPool::play(int sampleID, float leftVolume, float rightVolume,
        int priority, int loop, float rate)
{
    LOGW("sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
            sampleID, leftVolume, rightVolume, priority, loop, rate);
    sp<Sample> sample;
    SoundChannel* channel;
    int channelID;

    // scope for lock
    {
        Mutex::Autolock lock(&mLock);

        // is sample ready?
        sample = findSample(sampleID);
        if ((sample == 0) || (sample->state() != Sample::READY)) {
            LOGW("  sample %d not READY", sampleID);
            return 0;
        }

        dump();

        // allocate a channel
        channel = allocateChannel(priority);

        // no channel allocated - return 0
        if (!channel) {
            LOGW("No channel allocated");
            return 0;
        }

        channelID = ++mNextChannelID;
    }

    LOGW("channel state = %d", channel->state());
    channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate);
    return channelID;
}

有没有解决这个问题的方法..请帮助..

4

3 回答 3

1

您也可以使用此方法

public void loadSound (String strSound, int stream) {
     boolean loaded = false;
     mSoundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
            @Override
            public void onLoadComplete(SoundPool soundPool, int sampleId,
                    int status) {
                mSoundPool.play(stream, streamVolume, streamVolume, 1, LOOP_1_TIME, 1f);
            }
        });
    try {
          stream= mSoundPool.load(aMan.openFd(strSound), 1);
        } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
于 2013-02-08T05:57:56.703 回答
0

我在 android 2.0 上遇到了同样的问题,并通过使用 .ogg 格式而不是 .mp3 格式来解决我使用的声音,正如这里提到的那样。我希望这能解决你的问题。

于 2013-07-22T21:03:34.890 回答
0

Sample not ready 通常表示它还没有被加载,即它还在加载中。(也许您切换到的框架可能会加载更长的时间。)

你应该订阅它onLoadCompleteListener,当你收到回调时,声音就可以播放了。在此之前,它将无法播放。

于 2012-12-28T15:54:42.700 回答