Esempio n. 1
0
status_t SimplePlayer::onOutputFormatChanged(
        size_t trackIndex, CodecState *state) {
    sp<AMessage> format;
    status_t err = state->mCodec->getOutputFormat(&format);

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

    AString mime;
    CHECK(format->findString("mime", &mime));

    if (!strncasecmp(mime.c_str(), "audio/", 6)) {
        int32_t channelCount;
        int32_t sampleRate;
        CHECK(format->findInt32("channel-count", &channelCount));
        CHECK(format->findInt32("sample-rate", &sampleRate));

        state->mAudioTrack = new AudioTrack(
                AUDIO_STREAM_MUSIC,
                sampleRate,
                AUDIO_FORMAT_PCM_16_BIT,
                audio_channel_out_mask_from_count(channelCount),
                0);

        state->mNumFramesWritten = 0;
    }

    return OK;
}
status_t LibmediaPlayback::Play(int duration_secs) {
  audio_channel_mask_t audio_mask =
      audio_channel_out_mask_from_count(num_channels_);
  const audio_stream_type_t kStreamType = AUDIO_STREAM_MUSIC;
  size_t frame_count = 0;  // Use default value for frame count.
  audio_output_flags_t audio_output_flags = AUDIO_OUTPUT_FLAG_NONE;

  AudioTrack* track = new AudioTrack(
      kStreamType, sample_rate_, audio_format_, audio_mask, frame_count,
      audio_output_flags, LibmediaPlayback::AudioCallback,
      reinterpret_cast<void*>(this));
  status_t status = track->initCheck();
  if (status != OK) {
    LOG(ERROR) << "Audio track initialization failed.";
    return status;
  }

  float volume = 0.9;
  track->setVolume(volume);
  status = track->start();
  if (status != OK) {
    LOG(ERROR) << "Audio track failed to start.";
    return status;
  }

  sleep(duration_secs);
  track->stop();

  if (in_file_)
    sf_close(in_file_);
  else
    sine_data_buffer_->release();

  return status;
}
Esempio n. 3
0
//-------------------------------------------------------------------------------------------------
int JetPlayer::init()
{
    //Mutex::Autolock lock(&mMutex);

    EAS_RESULT result;

    // retrieve the EAS library settings
    if (pLibConfig == NULL)
        pLibConfig = EAS_Config();
    if (pLibConfig == NULL) {
        ALOGE("JetPlayer::init(): EAS library configuration could not be retrieved, aborting.");
        return EAS_FAILURE;
    }

    // init the EAS library
    result = EAS_Init(&mEasData);
    if (result != EAS_SUCCESS) {
        ALOGE("JetPlayer::init(): Error initializing Sonivox EAS library, aborting.");
        mState = EAS_STATE_ERROR;
        return result;
    }
    // init the JET library with the default app event controller range
    result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG));
    if (result != EAS_SUCCESS) {
        ALOGE("JetPlayer::init(): Error initializing JET library, aborting.");
        mState = EAS_STATE_ERROR;
        return result;
    }

    // create the output AudioTrack
    mAudioTrack = new AudioTrack();
    mAudioTrack->set(AUDIO_STREAM_MUSIC,  //TODO parameterize this
            pLibConfig->sampleRate,
            AUDIO_FORMAT_PCM_16_BIT,
            audio_channel_out_mask_from_count(pLibConfig->numChannels),
            mTrackBufferSize,
            AUDIO_OUTPUT_FLAG_NONE);

    // create render and playback thread
    {
        Mutex::Autolock l(mMutex);
        ALOGV("JetPlayer::init(): trying to start render thread");
        mThread = new JetPlayerThread(this);
        mThread->run("jetRenderThread", ANDROID_PRIORITY_AUDIO);
        mCondition.wait(mMutex);
    }
    if (mTid > 0) {
        // render thread started, we're ready
        ALOGV("JetPlayer::init(): render thread(%d) successfully started.", mTid);
        mState = EAS_STATE_READY;
    } else {
        ALOGE("JetPlayer::init(): failed to start render thread.");
        mState = EAS_STATE_ERROR;
        return EAS_FAILURE;
    }

    return EAS_SUCCESS;
}
Esempio n. 4
0
bool android_sys_render::init_audio(void* ctx, int channels, int bits_per_sample, int sample_rate, int format)
{
	if(!m_support)return false;
	int play_buf_size;
	status_t s;
	m_writedata->nchannels = channels;
	m_writedata->rate = sample_rate;
	m_sleep_in = 1000000.0/(2*channels*sample_rate);
	__android_log_print(ANDROID_LOG_INFO,"android_sys_render","%d  %d",channels,sample_rate);
	int notify_frames=(int)(audio_buf_ms*(float)m_writedata->rate);
	
	m_writedata->mCard->enableVoipMode();
	m_writedata->nFramesRequested=0;
	
	if (AudioTrack::getMinFrameCount(&play_buf_size,m_writedata->stype,m_writedata->rate)==0)
	{
#ifdef WTITE_LOG
		__android_log_print(ANDROID_LOG_INFO,"android_sys_render","AudioTrack: min frame count is %i",play_buf_size);
#endif
	}
	else
	{
#ifdef WTITE_LOG
		__android_log_print(ANDROID_LOG_INFO,"android_sys_render","AudioTrack::getMinFrameCount() error");
#endif
		return false;
	}
	
	m_writedata->tr=new AudioTrack(m_writedata->stype,
                     	m_writedata->rate,
                     	AUDIO_FORMAT_PCM_16_BIT,
                     	audio_channel_out_mask_from_count(m_writedata->nchannels),
                     	play_buf_size,
                     	AUDIO_OUTPUT_FLAG_NONE, // AUDIO_OUTPUT_FLAG_NONE,
                     	android_snd_write_cb, m_writedata,notify_frames,0);
	s=m_writedata->tr->initCheck();
	if (s!=0) 
	{
#ifdef WTITE_LOG
		__android_log_print(ANDROID_LOG_INFO,"android_sys_render","Problem setting up AudioTrack: %s",strerror(-s));
#endif
		delete m_writedata->tr;
		m_writedata->tr=NULL;
		return false;
	}
	m_writedata->nbufs=0;
#ifdef WTITE_LOG
	__android_log_print(ANDROID_LOG_INFO,"android_sys_render","AudioTrack latency estimated to %i ms",m_writedata->tr->latency());
#endif
	m_writedata->mStarted=false;
	m_writedata->flowControlStart = av_gettime();
	m_writedata->minBufferFilling = -1;
	return true;
}
void AudioMixerController::initTrack(Track* track, std::vector<Track*>& tracksToRemove)
{
    uint32_t channelMask = audio_channel_out_mask_from_count(2);
    int32_t name = _mixer->getTrackName(channelMask, AUDIO_FORMAT_PCM_16_BIT,
                                        AUDIO_SESSION_OUTPUT_MIX);
    if (name < 0)
    {
        // If we could not get the track name, it means that there're MAX_NUM_TRACKS tracks
        // So ignore the new track.
        tracksToRemove.push_back(track);
    }
    else
    {
        _mixer->setBufferProvider(name, track);
        _mixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER,
                             _mixingBuffer.buf);
        _mixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::MIXER_FORMAT,
                (void *) (uintptr_t) AUDIO_FORMAT_PCM_16_BIT);
        _mixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::FORMAT,
                (void *) (uintptr_t) AUDIO_FORMAT_PCM_16_BIT);
        _mixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::MIXER_CHANNEL_MASK,
                (void *) (uintptr_t) channelMask);
        _mixer->setParameter(
                name,
                AudioMixer::TRACK,
                AudioMixer::CHANNEL_MASK,
                (void *) (uintptr_t) channelMask);

        track->setState(Track::State::PLAYING);
        track->setName(name);
        _mixer->enable(name);

        std::lock_guard<std::mutex> lk(track->_volumeDirtyMutex);
        gain_minifloat_packed_t volume = track->getVolumeLR();
        float lVolume = float_from_gain(gain_minifloat_unpack_left(volume));
        float rVolume = float_from_gain(gain_minifloat_unpack_right(volume));

        _mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME0, &lVolume);
        _mixer->setParameter(name, AudioMixer::VOLUME, AudioMixer::VOLUME1, &rVolume);

        track->setVolumeDirty(false);
        track->setInitialized(true);
    }
}
int main(int argc, char* argv[]) {
  if (argc < 3) {
    Usage();
    return -1;
  }
  // Process command line arguments.
  const int kAudioDeviceBase = 16;
  uint32_t desired_output_device = strtol(
      argv[1], nullptr /* look at full string*/, kAudioDeviceBase);
  const int kSampleRateBase = 10;
  uint32_t desired_sample_rate = strtol(
      argv[2], nullptr /* look at full string*/, kSampleRateBase);
  char* filename = nullptr;
  if (desired_sample_rate == 0) {
    filename = argv[2];
  }

  LOG(INFO) << "Starting audio hal tests.";
  int rc = 0;
  const hw_module_t* module = nullptr;

  // Load audio HAL.
  rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, "primary", &module);
  if (rc) {
    LOG(WARNING) << "Could not get primary hw module, trying usb. (" << strerror(rc) << ")";
    rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, "usb", &module);
    if (rc) {
      LOG(ERROR) << "Could not get hw module. (" << strerror(rc) << ")";
      return -1;
    }
  }

  // Open audio device.
  CHECK(module != nullptr);
  audio_hw_device_t* audio_device = nullptr;
  rc = audio_hw_device_open(module, &audio_device);
  if (rc) {
    LOG(ERROR) << "Could not open hw device. (" << strerror(rc) << ")";
    return -1;
  }

  // Set to a high number so it doesn't interfere with existing stream handles
  // from AudioFlinger.
  audio_io_handle_t handle = 0x999;
  audio_devices_t output_device =
      static_cast<audio_devices_t>(desired_output_device);
  audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
  audio_config_t config;
  SF_INFO file_info;
  SNDFILE* in_file = nullptr;
  if (filename) {
    in_file = sf_open(filename, SFM_READ, &file_info);
    CHECK(in_file != nullptr);
    config.channel_mask = audio_channel_out_mask_from_count(file_info.channels);
    if (!(file_info.format & SF_FORMAT_PCM_16)) {
      LOG(ERROR) << "File must be of format 16-bit PCM.";
      return -1;
    }
    config.format = kAudioPlaybackFormat;
    config.sample_rate = file_info.samplerate;
  } else {
    config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
    config.format = kAudioPlaybackFormat;
    config.sample_rate = desired_sample_rate;
  }
  LOG(INFO) << "Now playing to " << output_device << " at sample rate "
            << config.sample_rate;
  const char* stream_name = "output_stream";

  // Open audio output stream.
  audio_stream_out_t* out_stream = nullptr;
  CHECK(audio_device != nullptr);
  rc = audio_device->open_output_stream(audio_device, handle, output_device,
                                        flags, &config, &out_stream,
                                        stream_name);
  if (rc) {
    LOG(ERROR) << "Could not open output stream. (" << strerror(rc) << ")";
    return -1;
  }

  // Set volume.
  const float kLeftVolume = 0.75;
  const float kRightVolume = 0.75;
  CHECK(out_stream != nullptr);
  rc = out_stream->set_volume(out_stream, kLeftVolume, kRightVolume);
  if (rc) {
    LOG(ERROR) << "Could not set volume correctly. (" << strerror(rc) << ")";
  }


  if (filename) {
    PlayFile(out_stream, in_file, &config);
  } else {
    PlaySineWave(out_stream, &config);
  }

  // Close output stream and device.
  audio_device->close_output_stream(audio_device, out_stream);
  audio_hw_device_close(audio_device);

  LOG(INFO) << "Done with hal tests";
  return 0;
}
status_t AudioPlayer::start(bool sourceAlreadyStarted) {
    CHECK(!mStarted);
    CHECK(mSource != NULL);

    status_t err;
    if (!sourceAlreadyStarted) {
        err = mSource->start();

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

    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
    // of playback, if there is one, getFormat below will retrieve the
    // updated format, if there isn't, we'll stash away the valid buffer
    // of data to be used on the first audio callback.

    CHECK(mFirstBuffer == NULL);

    MediaSource::ReadOptions options;
    if (mSeeking) {
        options.setSeekTo(mSeekTimeUs);
        mSeeking = false;
    }

    mFirstBufferResult = mSource->read(&mFirstBuffer, &options);
    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
        ALOGV("INFO_FORMAT_CHANGED!!!");

        CHECK(mFirstBuffer == NULL);
        mFirstBufferResult = OK;
        mIsFirstBuffer = false;
    } else {
        mIsFirstBuffer = true;
    }

    sp<MetaData> format = mSource->getFormat();
    const char *mime;
    bool success = format->findCString(kKeyMIMEType, &mime);
    CHECK(success);
    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));

    success = format->findInt32(kKeySampleRate, &mSampleRate);
    CHECK(success);

    int32_t numChannels, channelMask;
    success = format->findInt32(kKeyChannelCount, &numChannels);
    CHECK(success);

    if(!format->findInt32(kKeyChannelMask, &channelMask)) {
        // log only when there's a risk of ambiguity of channel mask selection
        ALOGI_IF(numChannels > 2,
                "source format didn't specify channel mask, using (%d) channel order", numChannels);
        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
    }

    if (mAudioSink.get() != NULL) {

        status_t err = mAudioSink->open(
                mSampleRate, numChannels, channelMask, AUDIO_FORMAT_PCM_16_BIT,
                DEFAULT_AUDIOSINK_BUFFERCOUNT,
                &AudioPlayer::AudioSinkCallback,
                this,
                (mAllowDeepBuffering ?
                            AUDIO_OUTPUT_FLAG_DEEP_BUFFER :
                            AUDIO_OUTPUT_FLAG_NONE));
        if (err != OK) {
            if (mFirstBuffer != NULL) {
                mFirstBuffer->release();
                mFirstBuffer = NULL;
            }

            if (!sourceAlreadyStarted) {
                mSource->stop();
            }

            return err;
        }

        mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
        mFrameSize = mAudioSink->frameSize();

        mAudioSink->start();
    } else {
        // playing to an AudioTrack, set up mask if necessary
        audio_channel_mask_t audioMask = channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ?
                audio_channel_out_mask_from_count(numChannels) : channelMask;
        if (0 == audioMask) {
            return BAD_VALUE;
        }

        mAudioTrack = new AudioTrack(
                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,
                0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);

        if ((err = mAudioTrack->initCheck()) != OK) {
            delete mAudioTrack;
            mAudioTrack = NULL;

            if (mFirstBuffer != NULL) {
                mFirstBuffer->release();
                mFirstBuffer = NULL;
            }

            if (!sourceAlreadyStarted) {
                mSource->stop();
            }

            return err;
        }

        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
        mFrameSize = mAudioTrack->frameSize();

        mAudioTrack->start();
    }

    mStarted = true;
    mPinnedTimeUs = -1ll;

    return OK;
}
Esempio n. 8
0
static int adev_open_output_stream(struct audio_hw_device *dev,
                                   audio_io_handle_t handle,
                                   audio_devices_t devices,
                                   audio_output_flags_t flags,
                                   struct audio_config *config,
                                   struct audio_stream_out **stream_out,
                                   const char *address /*__unused*/)
{
    ALOGV("adev_open_output_stream() handle:0x%X, device:0x%X, flags:0x%X, addr:%s",
          handle, devices, flags, address);

    struct audio_device *adev = (struct audio_device *)dev;

    struct stream_out *out;
    out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
    if (!out)
        return -ENOMEM;

    /* setup function pointers */
    out->stream.common.get_sample_rate = out_get_sample_rate;
    out->stream.common.set_sample_rate = out_set_sample_rate;
    out->stream.common.get_buffer_size = out_get_buffer_size;
    out->stream.common.get_channels = out_get_channels;
    out->stream.common.get_format = out_get_format;
    out->stream.common.set_format = out_set_format;
    out->stream.common.standby = out_standby;
    out->stream.common.dump = out_dump;
    out->stream.common.set_parameters = out_set_parameters;
    out->stream.common.get_parameters = out_get_parameters;
    out->stream.common.add_audio_effect = out_add_audio_effect;
    out->stream.common.remove_audio_effect = out_remove_audio_effect;
    out->stream.get_latency = out_get_latency;
    out->stream.set_volume = out_set_volume;
    out->stream.write = out_write;
    out->stream.get_render_position = out_get_render_position;
    out->stream.get_presentation_position = out_get_presentation_position;
    out->stream.get_next_write_timestamp = out_get_next_write_timestamp;

    pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
    pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);

    out->dev = adev;
    pthread_mutex_lock(&adev->lock);
    out->profile = &adev->out_profile;

    // build this to hand to the alsa_device_proxy
    struct pcm_config proxy_config;
    memset(&proxy_config, 0, sizeof(proxy_config));

    /* Pull out the card/device pair */
    parse_card_device_params(true, &(out->profile->card), &(out->profile->device));

    profile_read_device_info(out->profile);

    pthread_mutex_unlock(&adev->lock);

    int ret = 0;

    /* Rate */
    if (config->sample_rate == 0) {
        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile);
    } else if (profile_is_sample_rate_valid(out->profile, config->sample_rate)) {
        proxy_config.rate = config->sample_rate;
    } else {
        ALOGE("%s: The requested sample rate (%d) is not valid", __func__, config->sample_rate);
        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile);
        ret = -EINVAL;
    }

    /* Format */
    if (config->format == AUDIO_FORMAT_DEFAULT) {
        proxy_config.format = profile_get_default_format(out->profile);
        config->format = audio_format_from_pcm_format(proxy_config.format);
    } else {
        enum pcm_format fmt = pcm_format_from_audio_format(config->format);
        if (profile_is_format_valid(out->profile, fmt)) {
            proxy_config.format = fmt;
        } else {
            ALOGE("%s: The requested format (0x%x) is not valid", __func__, config->format);
            proxy_config.format = profile_get_default_format(out->profile);
            config->format = audio_format_from_pcm_format(proxy_config.format);
            ret = -EINVAL;
        }
    }

    /* Channels */
    unsigned proposed_channel_count = 0;
    if (k_force_channels) {
        proposed_channel_count = k_force_channels;
    } else if (config->channel_mask == AUDIO_CHANNEL_NONE) {
        proposed_channel_count =  profile_get_default_channel_count(out->profile);
    }
    if (proposed_channel_count != 0) {
        if (proposed_channel_count <= FCC_2) {
            // use channel position mask for mono and stereo
            config->channel_mask = audio_channel_out_mask_from_count(proposed_channel_count);
        } else {
            // use channel index mask for multichannel
            config->channel_mask =
                    audio_channel_mask_for_index_assignment_from_count(proposed_channel_count);
        }
        out->hal_channel_count = proposed_channel_count;
    } else {
        out->hal_channel_count = audio_channel_count_from_out_mask(config->channel_mask);
    }
    /* we can expose any channel mask, and emulate internally based on channel count. */
    out->hal_channel_mask = config->channel_mask;

    /* no validity checks are needed as proxy_prepare() forces channel_count to be valid.
     * and we emulate any channel count discrepancies in out_write(). */
    proxy_config.channels = proposed_channel_count;

#if TARGET_AUDIO_PRIMARY
	out->profile->default_config.period_count = 4;
#endif
    proxy_prepare(&out->proxy, out->profile, &proxy_config);

    /* TODO The retry mechanism isn't implemented in AudioPolicyManager/AudioFlinger. */
    ret = 0;

    out->conversion_buffer = NULL;
    out->conversion_buffer_size = 0;

    out->standby = true;

    *stream_out = &out->stream;

    return ret;

err_open:
    free(out);
    *stream_out = NULL;
    return -ENOSYS;
}
status_t AudioPlayer::start(bool sourceAlreadyStarted) {
    CHECK(!mStarted);
    CHECK(mSource != NULL);

    status_t err;
    if (!sourceAlreadyStarted) {
        mSourcePaused = false;
        err = mSource->start();

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

    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
    // of playback, if there is one, getFormat below will retrieve the
    // updated format, if there isn't, we'll stash away the valid buffer
    // of data to be used on the first audio callback.

    CHECK(mFirstBuffer == NULL);

    MediaSource::ReadOptions options;
    if (mSeeking) {
        options.setSeekTo(mSeekTimeUs);
        mSeeking = false;
    }

    mFirstBufferResult = mSource->read(&mFirstBuffer, &options);
    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
        ALOGV("INFO_FORMAT_CHANGED!!!");

        CHECK(mFirstBuffer == NULL);
        mFirstBufferResult = OK;
        mIsFirstBuffer = false;
    } else {
        mIsFirstBuffer = true;
    }

    sp<MetaData> format = mSource->getFormat();
    const char *mime;
    bool success = format->findCString(kKeyMIMEType, &mime);
    CHECK(success);
    CHECK(useOffload() || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));

    success = format->findInt32(kKeySampleRate, &mSampleRate);
    CHECK(success);

    int32_t numChannels, channelMask;
    success = format->findInt32(kKeyChannelCount, &numChannels);
    CHECK(success);

    if(!format->findInt32(kKeyChannelMask, &channelMask)) {
        // log only when there's a risk of ambiguity of channel mask selection
        ALOGI_IF(numChannels > 2,
                "source format didn't specify channel mask, using (%d) channel order", numChannels);
        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
    }

    audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;

    if (useOffload()) {
        if (mapMimeToAudioFormat(audioFormat, mime) != OK) {
            ALOGE("Couldn't map mime type \"%s\" to a valid AudioSystem::audio_format", mime);
            audioFormat = AUDIO_FORMAT_INVALID;
        } else {
#ifdef QCOM_HARDWARE
            // Override audio format for PCM offload
            if (audioFormat == AUDIO_FORMAT_PCM_16_BIT) {
                audioFormat = AUDIO_FORMAT_PCM_16_BIT_OFFLOAD;
            }
#endif
            ALOGV("Mime type \"%s\" mapped to audio_format 0x%x", mime, audioFormat);
        }
    }

    int avgBitRate = -1;
    format->findInt32(kKeyBitRate, &avgBitRate);

    if (mAudioSink.get() != NULL) {

        uint32_t flags = AUDIO_OUTPUT_FLAG_NONE;
        audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;

        if (allowDeepBuffering()) {
            flags |= AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
        }
        if (useOffload()) {
            flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;

            int64_t durationUs;
            if (format->findInt64(kKeyDuration, &durationUs)) {
                offloadInfo.duration_us = durationUs;
            } else {
                offloadInfo.duration_us = -1;
            }

            offloadInfo.sample_rate = mSampleRate;
            offloadInfo.channel_mask = channelMask;
            offloadInfo.format = audioFormat;
            offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
            offloadInfo.bit_rate = avgBitRate;
            offloadInfo.has_video = ((mCreateFlags & HAS_VIDEO) != 0);
            offloadInfo.is_streaming = ((mCreateFlags & IS_STREAMING) != 0);
        }

        status_t err = mAudioSink->open(
                mSampleRate, numChannels, channelMask, audioFormat,
                DEFAULT_AUDIOSINK_BUFFERCOUNT,
                &AudioPlayer::AudioSinkCallback,
                this,
                (audio_output_flags_t)flags,
                useOffload() ? &offloadInfo : NULL);

        if (err == OK) {
            mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
            mFrameSize = mAudioSink->frameSize();

            if (useOffload()) {
                // If the playback is offloaded to h/w we pass the
                // HAL some metadata information
                // We don't want to do this for PCM because it will be going
                // through the AudioFlinger mixer before reaching the hardware
                sendMetaDataToHal(mAudioSink, format);
            }

            err = mAudioSink->start();
            // do not alter behavior for non offloaded tracks: ignore start status.
            if (!useOffload()) {
                err = OK;
            }
        }

        if (err != OK) {
            if (mFirstBuffer != NULL) {
                mFirstBuffer->release();
                mFirstBuffer = NULL;
            }

            if (!sourceAlreadyStarted) {
                mSource->stop();
            }

            return err;
        }

    } else {
        // playing to an AudioTrack, set up mask if necessary
        audio_channel_mask_t audioMask = channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ?
                audio_channel_out_mask_from_count(numChannels) : channelMask;
        if (0 == audioMask) {
            return BAD_VALUE;
        }

        mAudioTrack = new AudioTrack(
                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,
                0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);

        if ((err = mAudioTrack->initCheck()) != OK) {
            mAudioTrack.clear();

            if (mFirstBuffer != NULL) {
                mFirstBuffer->release();
                mFirstBuffer = NULL;
            }

            if (!sourceAlreadyStarted) {
                mSource->stop();
            }

            return err;
        }

        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
        mFrameSize = mAudioTrack->frameSize();

        mAudioTrack->start();
    }

    mStarted = true;
    mPlaying = true;
    mPinnedTimeUs = -1ll;
    const char *componentName;
    if (!(format->findCString(kKeyDecoderComponent, &componentName))) {
          componentName = "none";
    }
    if (!strncmp(componentName, "OMX.qcom.", 9)) {
        mPauseRequired = true;
    } else {
        mPauseRequired = false;
    }

    return OK;
}
status_t VideoEditorAudioPlayer::start(bool sourceAlreadyStarted) {
    Mutex::Autolock autoLock(mLock);
    CHECK(!mStarted);
    CHECK(mSource != NULL);
    ALOGV("Start");
    status_t err;
    M4OSA_ERR result = M4NO_ERROR;
    M4OSA_UInt32 startTime = 0;
    M4OSA_UInt32 seekTimeStamp = 0;
    M4OSA_Bool bStoryBoardTSBeyondBTEndCutTime = M4OSA_FALSE;

    if (!sourceAlreadyStarted) {
        err = mSource->start();
        if (err != OK) {
            return err;
        }
    }

    // Create the BG Audio handler
    mAudioProcess = new VideoEditorBGAudioProcessing();
    AudioMixSettings audioMixSettings;

    // Pass on the audio ducking parameters
    audioMixSettings.lvInDucking_threshold =
        mAudioMixSettings->uiInDucking_threshold;
    audioMixSettings.lvInDucking_lowVolume =
        ((M4OSA_Float)mAudioMixSettings->uiInDucking_lowVolume) / 100.0;
    audioMixSettings.lvInDucking_enable =
        mAudioMixSettings->bInDucking_enable;
    audioMixSettings.lvPTVolLevel =
        ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal) / 100.0;
    audioMixSettings.lvBTVolLevel =
        ((M4OSA_Float)mAudioMixSettings->uiAddVolume) / 100.0;
    audioMixSettings.lvBTChannelCount = mAudioMixSettings->uiBTChannelCount;
    audioMixSettings.lvPTChannelCount = mAudioMixSettings->uiNbChannels;

    // Call to Audio mix param setting
    mAudioProcess->setMixParams(audioMixSettings);

    // Get the BG Audio PCM file details
    if ( mBGAudioPCMFileHandle ) {

        // TODO : 32bits required for OSAL, to be updated once OSAL is updated
        M4OSA_UInt32 tmp32 = 0;
        result = M4OSA_fileReadGetOption(mBGAudioPCMFileHandle,
                                        M4OSA_kFileReadGetFileSize,
                                        (M4OSA_Void**)&tmp32);
        mBGAudioPCMFileLength = tmp32;
        mBGAudioPCMFileTrimmedLength = mBGAudioPCMFileLength;


        ALOGV("VideoEditorAudioPlayer::start M4OSA_kFileReadGetFileSize = %lld",
                            mBGAudioPCMFileLength);

        // Get the duration in time of the audio BT
        if ( result == M4NO_ERROR ) {
         ALOGV("VEAP: channels = %d freq = %d",
         mAudioMixSettings->uiNbChannels,  mAudioMixSettings->uiSamplingFrequency);

            // No trim
            mBGAudioPCMFileDuration = ((
                    (int64_t)(mBGAudioPCMFileLength/sizeof(M4OSA_UInt16)/
                    mAudioMixSettings->uiNbChannels))*1000 ) /
                    mAudioMixSettings->uiSamplingFrequency;

            ALOGV("VideoEditorAudioPlayer:: beginCutMs %d , endCutMs %d",
                    (unsigned int) mAudioMixSettings->beginCutMs,
                    (unsigned int) mAudioMixSettings->endCutMs);

            // Remove the trim part
            if ((mAudioMixSettings->beginCutMs == 0) &&
                (mAudioMixSettings->endCutMs != 0)) {
                // End time itself the file duration
                mBGAudioPCMFileDuration = mAudioMixSettings->endCutMs;
                // Limit the file length also
                mBGAudioPCMFileTrimmedLength = ((
                     (int64_t)(mBGAudioPCMFileDuration *
                     mAudioMixSettings->uiSamplingFrequency) *
                     mAudioMixSettings->uiNbChannels) *
                     sizeof(M4OSA_UInt16)) / 1000;
            }
            else if ((mAudioMixSettings->beginCutMs != 0) &&
                     (mAudioMixSettings->endCutMs == mBGAudioPCMFileDuration)) {
                // End time itself the file duration
                mBGAudioPCMFileDuration = mBGAudioPCMFileDuration -
                      mAudioMixSettings->beginCutMs;
                // Limit the file length also
                mBGAudioPCMFileTrimmedLength = ((
                     (int64_t)(mBGAudioPCMFileDuration *
                     mAudioMixSettings->uiSamplingFrequency) *
                     mAudioMixSettings->uiNbChannels) *
                     sizeof(M4OSA_UInt16)) / 1000;
            }
            else if ((mAudioMixSettings->beginCutMs != 0) &&
                    (mAudioMixSettings->endCutMs != 0)) {
                // End time itself the file duration
                mBGAudioPCMFileDuration = mAudioMixSettings->endCutMs -
                    mAudioMixSettings->beginCutMs;
                // Limit the file length also
                mBGAudioPCMFileTrimmedLength = ((
                    (int64_t)(mBGAudioPCMFileDuration *
                    mAudioMixSettings->uiSamplingFrequency) *
                    mAudioMixSettings->uiNbChannels) *
                    sizeof(M4OSA_UInt16)) / 1000; /*make to sec from ms*/
            }

            ALOGV("VideoEditorAudioPlayer: file duration recorded : %lld",
                    mBGAudioPCMFileDuration);
        }

        // Last played location to be seeked at for next media item
        if ( result == M4NO_ERROR ) {
            ALOGV("VideoEditorAudioPlayer::mBGAudioStoryBoardSkimTimeStamp %lld",
                    mBGAudioStoryBoardSkimTimeStamp);
            ALOGV("VideoEditorAudioPlayer::uiAddCts %d",
                    mAudioMixSettings->uiAddCts);
            if (mBGAudioStoryBoardSkimTimeStamp >= mAudioMixSettings->uiAddCts) {
                startTime = (mBGAudioStoryBoardSkimTimeStamp -
                 mAudioMixSettings->uiAddCts);
            }
            else {
                // do nothing
            }

            ALOGV("VideoEditorAudioPlayer::startTime %d", startTime);
            seekTimeStamp = 0;
            if (startTime) {
                if (startTime >= mBGAudioPCMFileDuration) {
                    // The BG track should be looped and started again
                    if (mAudioMixSettings->bLoop) {
                        // Add begin cut time to the mod value
                        seekTimeStamp = ((startTime%mBGAudioPCMFileDuration) +
                        mAudioMixSettings->beginCutMs);
                    }else {
                        // Looping disabled, donot do BT Mix , set to file end
                        seekTimeStamp = (mBGAudioPCMFileDuration +
                        mAudioMixSettings->beginCutMs);
                    }
                }else {
                    // BT still present , just seek to story board time
                    seekTimeStamp = startTime + mAudioMixSettings->beginCutMs;
                }
            }
            else {
                seekTimeStamp = mAudioMixSettings->beginCutMs;
            }

            // Convert the seekTimeStamp to file location
            mBGAudioPCMFileOriginalSeekPoint = (
                                        (int64_t)(mAudioMixSettings->beginCutMs)
                                        * mAudioMixSettings->uiSamplingFrequency
                                        * mAudioMixSettings->uiNbChannels
                                        * sizeof(M4OSA_UInt16))/ 1000 ; /*make to sec from ms*/

            mBGAudioPCMFileSeekPoint = ((int64_t)(seekTimeStamp)
                                        * mAudioMixSettings->uiSamplingFrequency
                                        * mAudioMixSettings->uiNbChannels
                                        * sizeof(M4OSA_UInt16))/ 1000 ;
        }
    }

    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
    // of playback, if there is one, getFormat below will retrieve the
    // updated format, if there isn't, we'll stash away the valid buffer
    // of data to be used on the first audio callback.

    CHECK(mFirstBuffer == NULL);

    mFirstBufferResult = mSource->read(&mFirstBuffer);
    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
        ALOGV("INFO_FORMAT_CHANGED!!!");

        CHECK(mFirstBuffer == NULL);
        mFirstBufferResult = OK;
        mIsFirstBuffer = false;
    } else {
        mIsFirstBuffer = true;
    }

    sp<MetaData> format = mSource->getFormat();
    const char *mime;
    bool success = format->findCString(kKeyMIMEType, &mime);
    CHECK(success);
    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));

    success = format->findInt32(kKeySampleRate, &mSampleRate);
    CHECK(success);

    int32_t numChannels;
    success = format->findInt32(kKeyChannelCount, &numChannels);
    CHECK(success);

    if (mAudioSink.get() != NULL) {
        status_t err = mAudioSink->open(
                mSampleRate, numChannels, CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT,
                DEFAULT_AUDIOSINK_BUFFERCOUNT,
                &VideoEditorAudioPlayer::AudioSinkCallback, this);
        if (err != OK) {
            if (mFirstBuffer != NULL) {
                mFirstBuffer->release();
                mFirstBuffer = NULL;
            }

            if (!sourceAlreadyStarted) {
                mSource->stop();
            }

            return err;
        }

        mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
        mFrameSize = mAudioSink->frameSize();

        mAudioSink->start();
    } else {
        mAudioTrack = new AudioTrack(
                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
                audio_channel_out_mask_from_count(numChannels),
                0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);

        if ((err = mAudioTrack->initCheck()) != OK) {
            mAudioTrack.clear();

            if (mFirstBuffer != NULL) {
                mFirstBuffer->release();
                mFirstBuffer = NULL;
            }

            if (!sourceAlreadyStarted) {
                mSource->stop();
            }

            return err;
        }

        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
        mFrameSize = mAudioTrack->frameSize();

        mAudioTrack->start();
    }

    mStarted = true;

    return OK;
}
Esempio n. 11
0
static uint32_t out_get_channels(const struct audio_stream *stream)
{
    const struct stream_out *out = (const struct stream_out*)stream;
    return audio_channel_out_mask_from_count(out->hal_channel_count);
}