d72031cee3
Upintegrate the android at home TX and RX players developed in the ICS_AAH branch. Change-Id: I8247d3702e30d8b0e215b31a92675d8ab28dccbb Signed-off-by: John Grossman <johngro@google.com>
289 lines
6.8 KiB
C++
289 lines
6.8 KiB
C++
/*
|
|
* Copyright (C) 2011 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "LibAAH_RTP"
|
|
//#define LOG_NDEBUG 0
|
|
|
|
#include <binder/IServiceManager.h>
|
|
#include <media/MediaPlayerInterface.h>
|
|
#include <utils/Log.h>
|
|
|
|
#include "aah_rx_player.h"
|
|
|
|
namespace android {
|
|
|
|
const uint32_t AAH_RXPlayer::kRTPRingBufferSize = 1 << 10;
|
|
|
|
sp<MediaPlayerBase> createAAH_RXPlayer() {
|
|
sp<MediaPlayerBase> ret = new AAH_RXPlayer();
|
|
return ret;
|
|
}
|
|
|
|
AAH_RXPlayer::AAH_RXPlayer()
|
|
: ring_buffer_(kRTPRingBufferSize)
|
|
, substreams_(NULL) {
|
|
thread_wrapper_ = new ThreadWrapper(*this);
|
|
|
|
is_playing_ = false;
|
|
multicast_joined_ = false;
|
|
transmitter_known_ = false;
|
|
current_epoch_known_ = false;
|
|
data_source_set_ = false;
|
|
sock_fd_ = -1;
|
|
|
|
substreams_.setCapacity(4);
|
|
|
|
memset(&listen_addr_, 0, sizeof(listen_addr_));
|
|
memset(&transmitter_addr_, 0, sizeof(transmitter_addr_));
|
|
|
|
fetchAudioFlinger();
|
|
}
|
|
|
|
AAH_RXPlayer::~AAH_RXPlayer() {
|
|
reset_l();
|
|
CHECK(substreams_.size() == 0);
|
|
omx_.disconnect();
|
|
}
|
|
|
|
status_t AAH_RXPlayer::initCheck() {
|
|
if (thread_wrapper_ == NULL) {
|
|
ALOGE("Failed to allocate thread wrapper!");
|
|
return NO_MEMORY;
|
|
}
|
|
|
|
if (!ring_buffer_.initCheck()) {
|
|
ALOGE("Failed to allocate reassembly ring buffer!");
|
|
return NO_MEMORY;
|
|
}
|
|
|
|
// Check for the presense of the common time service by attempting to query
|
|
// for CommonTime's frequency. If we get an error back, we cannot talk to
|
|
// the service at all and should abort now.
|
|
status_t res;
|
|
uint64_t freq;
|
|
res = cc_helper_.getCommonFreq(&freq);
|
|
if (OK != res) {
|
|
ALOGE("Failed to connect to common time service!");
|
|
return res;
|
|
}
|
|
|
|
return omx_.connect();
|
|
}
|
|
|
|
status_t AAH_RXPlayer::setDataSource(
|
|
const char *url,
|
|
const KeyedVector<String8, String8> *headers) {
|
|
AutoMutex api_lock(&api_lock_);
|
|
uint32_t a, b, c, d;
|
|
uint16_t port;
|
|
|
|
if (data_source_set_) {
|
|
return INVALID_OPERATION;
|
|
}
|
|
|
|
if (NULL == url) {
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
if (5 != sscanf(url, "%*[^:/]://%u.%u.%u.%u:%hu", &a, &b, &c, &d, &port)) {
|
|
ALOGE("Failed to parse URL \"%s\"", url);
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
if ((a > 255) || (b > 255) || (c > 255) || (d > 255) || (port == 0)) {
|
|
ALOGE("Bad multicast address \"%s\"", url);
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
ALOGI("setDataSource :: %u.%u.%u.%u:%hu", a, b, c, d, port);
|
|
|
|
a = (a << 24) | (b << 16) | (c << 8) | d;
|
|
|
|
memset(&listen_addr_, 0, sizeof(listen_addr_));
|
|
listen_addr_.sin_family = AF_INET;
|
|
listen_addr_.sin_port = htons(port);
|
|
listen_addr_.sin_addr.s_addr = htonl(a);
|
|
data_source_set_ = true;
|
|
|
|
return OK;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
|
|
return INVALID_OPERATION;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::setVideoSurface(const sp<Surface>& surface) {
|
|
return OK;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::setVideoSurfaceTexture(
|
|
const sp<ISurfaceTexture>& surfaceTexture) {
|
|
return OK;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::prepare() {
|
|
return OK;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::prepareAsync() {
|
|
sendEvent(MEDIA_PREPARED);
|
|
return OK;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::start() {
|
|
AutoMutex api_lock(&api_lock_);
|
|
|
|
if (is_playing_) {
|
|
return OK;
|
|
}
|
|
|
|
status_t res = startWorkThread();
|
|
is_playing_ = (res == OK);
|
|
return res;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::stop() {
|
|
return pause();
|
|
}
|
|
|
|
status_t AAH_RXPlayer::pause() {
|
|
AutoMutex api_lock(&api_lock_);
|
|
stopWorkThread();
|
|
CHECK(sock_fd_ < 0);
|
|
is_playing_ = false;
|
|
return OK;
|
|
}
|
|
|
|
bool AAH_RXPlayer::isPlaying() {
|
|
AutoMutex api_lock(&api_lock_);
|
|
return is_playing_;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::seekTo(int msec) {
|
|
sendEvent(MEDIA_SEEK_COMPLETE);
|
|
return OK;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::getCurrentPosition(int *msec) {
|
|
if (NULL != msec) {
|
|
*msec = 0;
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::getDuration(int *msec) {
|
|
if (NULL != msec) {
|
|
*msec = 1;
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::reset() {
|
|
AutoMutex api_lock(&api_lock_);
|
|
reset_l();
|
|
return OK;
|
|
}
|
|
|
|
void AAH_RXPlayer::reset_l() {
|
|
stopWorkThread();
|
|
CHECK(sock_fd_ < 0);
|
|
CHECK(!multicast_joined_);
|
|
is_playing_ = false;
|
|
data_source_set_ = false;
|
|
transmitter_known_ = false;
|
|
memset(&listen_addr_, 0, sizeof(listen_addr_));
|
|
}
|
|
|
|
status_t AAH_RXPlayer::setLooping(int loop) {
|
|
return OK;
|
|
}
|
|
|
|
player_type AAH_RXPlayer::playerType() {
|
|
return AAH_RX_PLAYER;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::setParameter(int key, const Parcel &request) {
|
|
return ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::getParameter(int key, Parcel *reply) {
|
|
return ERROR_UNSUPPORTED;
|
|
}
|
|
|
|
status_t AAH_RXPlayer::invoke(const Parcel& request, Parcel *reply) {
|
|
if (!reply) {
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
int32_t magic;
|
|
status_t err = request.readInt32(&magic);
|
|
if (err != OK) {
|
|
reply->writeInt32(err);
|
|
return OK;
|
|
}
|
|
|
|
if (magic != 0x12345) {
|
|
reply->writeInt32(BAD_VALUE);
|
|
return OK;
|
|
}
|
|
|
|
int32_t methodID;
|
|
err = request.readInt32(&methodID);
|
|
if (err != OK) {
|
|
reply->writeInt32(err);
|
|
return OK;
|
|
}
|
|
|
|
switch (methodID) {
|
|
// Get Volume
|
|
case INVOKE_GET_MASTER_VOLUME: {
|
|
if (audio_flinger_ != NULL) {
|
|
reply->writeInt32(OK);
|
|
reply->writeFloat(audio_flinger_->masterVolume());
|
|
} else {
|
|
reply->writeInt32(UNKNOWN_ERROR);
|
|
}
|
|
} break;
|
|
|
|
// Set Volume
|
|
case INVOKE_SET_MASTER_VOLUME: {
|
|
float targetVol = request.readFloat();
|
|
reply->writeInt32(audio_flinger_->setMasterVolume(targetVol));
|
|
} break;
|
|
|
|
default: return BAD_VALUE;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
void AAH_RXPlayer::fetchAudioFlinger() {
|
|
if (audio_flinger_ == NULL) {
|
|
sp<IServiceManager> sm = defaultServiceManager();
|
|
sp<IBinder> binder;
|
|
binder = sm->getService(String16("media.audio_flinger"));
|
|
|
|
if (binder == NULL) {
|
|
ALOGW("AAH_RXPlayer failed to fetch handle to audio flinger."
|
|
" Master volume control will not be possible.");
|
|
}
|
|
|
|
audio_flinger_ = interface_cast<IAudioFlinger>(binder);
|
|
}
|
|
}
|
|
|
|
} // namespace android
|