Merge change 22986 into eclair
* changes: Squashed commit of the following:
This commit is contained in:
@@ -38,23 +38,3 @@ LOCAL_CFLAGS += -Wno-multichar
|
||||
LOCAL_MODULE:= record
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
################################################################################
|
||||
|
||||
# include $(CLEAR_VARS)
|
||||
#
|
||||
# LOCAL_SRC_FILES:= \
|
||||
# play.cpp
|
||||
#
|
||||
# LOCAL_SHARED_LIBRARIES := \
|
||||
# libstagefright
|
||||
#
|
||||
# LOCAL_C_INCLUDES:= \
|
||||
# frameworks/base/media/libstagefright \
|
||||
# $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
|
||||
#
|
||||
# LOCAL_CFLAGS += -Wno-multichar
|
||||
#
|
||||
# LOCAL_MODULE:= play
|
||||
#
|
||||
# include $(BUILD_EXECUTABLE)
|
||||
|
||||
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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.
|
||||
*/
|
||||
|
||||
#include <binder/ProcessState.h>
|
||||
#include <media/stagefright/OMXClient.h>
|
||||
#include <media/stagefright/TimedEventQueue.h>
|
||||
#include <media/stagefright/MPEG4Extractor.h>
|
||||
#include <media/stagefright/MediaSource.h>
|
||||
#include <media/stagefright/MetaData.h>
|
||||
#include <media/stagefright/MmapSource.h>
|
||||
#include <media/stagefright/OMXDecoder.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
struct NewPlayer {
|
||||
NewPlayer();
|
||||
~NewPlayer();
|
||||
|
||||
void setSource(const char *uri);
|
||||
void start();
|
||||
void pause();
|
||||
void stop();
|
||||
|
||||
private:
|
||||
struct PlayerEvent : public TimedEventQueue::Event {
|
||||
PlayerEvent(NewPlayer *player,
|
||||
void (NewPlayer::*method)(int64_t realtime_us))
|
||||
: mPlayer(player),
|
||||
mMethod(method) {
|
||||
}
|
||||
|
||||
virtual void fire(TimedEventQueue *queue, int64_t realtime_us) {
|
||||
(mPlayer->*mMethod)(realtime_us);
|
||||
}
|
||||
|
||||
private:
|
||||
NewPlayer *mPlayer;
|
||||
void (NewPlayer::*mMethod)(int64_t realtime_us);
|
||||
|
||||
PlayerEvent(const PlayerEvent &);
|
||||
PlayerEvent &operator=(const PlayerEvent &);
|
||||
};
|
||||
|
||||
struct PlayVideoFrameEvent : public TimedEventQueue::Event {
|
||||
PlayVideoFrameEvent(NewPlayer *player, MediaBuffer *buffer)
|
||||
: mPlayer(player),
|
||||
mBuffer(buffer) {
|
||||
}
|
||||
|
||||
virtual ~PlayVideoFrameEvent() {
|
||||
if (mBuffer != NULL) {
|
||||
mBuffer->release();
|
||||
mBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void fire(TimedEventQueue *queue, int64_t realtime_us) {
|
||||
mPlayer->onPlayVideoFrame(realtime_us, mBuffer);
|
||||
mBuffer = NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
NewPlayer *mPlayer;
|
||||
MediaBuffer *mBuffer;
|
||||
|
||||
PlayVideoFrameEvent(const PlayVideoFrameEvent &);
|
||||
PlayVideoFrameEvent &operator=(const PlayVideoFrameEvent &);
|
||||
};
|
||||
|
||||
OMXClient mClient;
|
||||
|
||||
MPEG4Extractor *mExtractor;
|
||||
MediaSource *mAudioSource;
|
||||
OMXDecoder *mAudioDecoder;
|
||||
MediaSource *mVideoSource;
|
||||
OMXDecoder *mVideoDecoder;
|
||||
|
||||
int32_t mVideoWidth, mVideoHeight;
|
||||
|
||||
TimedEventQueue mQueue;
|
||||
wp<TimedEventQueue::Event> mPlayVideoFrameEvent;
|
||||
|
||||
int64_t mMediaTimeUsStart;
|
||||
int64_t mRealTimeUsStart;
|
||||
|
||||
void setAudioSource(MediaSource *source);
|
||||
void setVideoSource(MediaSource *source);
|
||||
|
||||
int64_t approxRealTime(int64_t mediatime_us) const;
|
||||
|
||||
void onStart(int64_t realtime_us);
|
||||
void onPause(int64_t realtime_us);
|
||||
void onFetchVideoFrame(int64_t realtime_us);
|
||||
void onPlayVideoFrame(int64_t realtime_us, MediaBuffer *buffer);
|
||||
|
||||
static int64_t getMediaBufferTimeUs(MediaBuffer *buffer);
|
||||
|
||||
NewPlayer(const NewPlayer &);
|
||||
NewPlayer &operator=(const NewPlayer &);
|
||||
};
|
||||
|
||||
NewPlayer::NewPlayer()
|
||||
: mExtractor(NULL),
|
||||
mAudioSource(NULL),
|
||||
mAudioDecoder(NULL),
|
||||
mVideoSource(NULL),
|
||||
mVideoDecoder(NULL),
|
||||
mVideoWidth(0),
|
||||
mVideoHeight(0) {
|
||||
status_t err = mClient.connect();
|
||||
assert(err == OK);
|
||||
}
|
||||
|
||||
NewPlayer::~NewPlayer() {
|
||||
stop();
|
||||
|
||||
mClient.disconnect();
|
||||
}
|
||||
|
||||
void NewPlayer::setSource(const char *uri) {
|
||||
stop();
|
||||
|
||||
mExtractor = new MPEG4Extractor(new MmapSource(uri));
|
||||
|
||||
int num_tracks;
|
||||
status_t err = mExtractor->countTracks(&num_tracks);
|
||||
assert(err == OK);
|
||||
|
||||
for (int i = 0; i < num_tracks; ++i) {
|
||||
const sp<MetaData> meta = mExtractor->getTrackMetaData(i);
|
||||
assert(meta != NULL);
|
||||
|
||||
const char *mime;
|
||||
if (!meta->findCString(kKeyMIMEType, &mime)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_audio = false;
|
||||
bool is_acceptable = false;
|
||||
if (!strncasecmp(mime, "audio/", 6)) {
|
||||
is_audio = true;
|
||||
is_acceptable = (mAudioSource == NULL);
|
||||
} else if (!strncasecmp(mime, "video/", 6)) {
|
||||
is_acceptable = (mVideoSource == NULL);
|
||||
}
|
||||
|
||||
if (!is_acceptable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MediaSource *source;
|
||||
if (mExtractor->getTrack(i, &source) != OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_audio) {
|
||||
setAudioSource(source);
|
||||
} else {
|
||||
setVideoSource(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NewPlayer::setAudioSource(MediaSource *source) {
|
||||
mAudioSource = source;
|
||||
|
||||
sp<MetaData> meta = source->getFormat();
|
||||
|
||||
mAudioDecoder = OMXDecoder::Create(&mClient, meta);
|
||||
mAudioDecoder->setSource(source);
|
||||
}
|
||||
|
||||
void NewPlayer::setVideoSource(MediaSource *source) {
|
||||
mVideoSource = source;
|
||||
|
||||
sp<MetaData> meta = source->getFormat();
|
||||
|
||||
bool success = meta->findInt32(kKeyWidth, &mVideoWidth);
|
||||
assert(success);
|
||||
|
||||
success = meta->findInt32(kKeyHeight, &mVideoHeight);
|
||||
assert(success);
|
||||
|
||||
mVideoDecoder = OMXDecoder::Create(&mClient, meta);
|
||||
mVideoDecoder->setSource(source);
|
||||
}
|
||||
|
||||
void NewPlayer::start() {
|
||||
mQueue.start();
|
||||
mQueue.postEvent(new PlayerEvent(this, &NewPlayer::onStart));
|
||||
}
|
||||
|
||||
void NewPlayer::pause() {
|
||||
mQueue.postEvent(new PlayerEvent(this, &NewPlayer::onPause));
|
||||
}
|
||||
|
||||
void NewPlayer::stop() {
|
||||
mQueue.stop();
|
||||
|
||||
delete mVideoDecoder;
|
||||
mVideoDecoder = NULL;
|
||||
delete mVideoSource;
|
||||
mVideoSource = NULL;
|
||||
mVideoWidth = mVideoHeight = 0;
|
||||
|
||||
delete mAudioDecoder;
|
||||
mAudioDecoder = NULL;
|
||||
delete mAudioSource;
|
||||
mAudioSource = NULL;
|
||||
|
||||
delete mExtractor;
|
||||
mExtractor = NULL;
|
||||
}
|
||||
|
||||
int64_t NewPlayer::approxRealTime(int64_t mediatime_us) const {
|
||||
return mRealTimeUsStart + (mediatime_us - mMediaTimeUsStart);
|
||||
}
|
||||
|
||||
void NewPlayer::onStart(int64_t realtime_us) {
|
||||
mRealTimeUsStart = TimedEventQueue::getRealTimeUs();
|
||||
|
||||
if (mVideoDecoder != NULL) {
|
||||
mQueue.postEvent(new PlayerEvent(this, &NewPlayer::onFetchVideoFrame));
|
||||
}
|
||||
}
|
||||
|
||||
void NewPlayer::onFetchVideoFrame(int64_t realtime_us) {
|
||||
MediaBuffer *buffer;
|
||||
status_t err = mVideoDecoder->read(&buffer);
|
||||
assert(err == OK);
|
||||
|
||||
int64_t mediatime_us = getMediaBufferTimeUs(buffer);
|
||||
|
||||
sp<TimedEventQueue::Event> event = new PlayVideoFrameEvent(this, buffer);
|
||||
mPlayVideoFrameEvent = event;
|
||||
|
||||
mQueue.postTimedEvent(event, approxRealTime(mediatime_us));
|
||||
}
|
||||
|
||||
// static
|
||||
int64_t NewPlayer::getMediaBufferTimeUs(MediaBuffer *buffer) {
|
||||
int32_t units, scale;
|
||||
bool success =
|
||||
buffer->meta_data()->findInt32(kKeyTimeUnits, &units);
|
||||
assert(success);
|
||||
success =
|
||||
buffer->meta_data()->findInt32(kKeyTimeScale, &scale);
|
||||
assert(success);
|
||||
|
||||
return (int64_t)units * 1000000 / scale;
|
||||
}
|
||||
|
||||
void NewPlayer::onPlayVideoFrame(int64_t realtime_us, MediaBuffer *buffer) {
|
||||
LOGI("playing video frame (mediatime: %.2f sec)\n",
|
||||
getMediaBufferTimeUs(buffer) / 1E6);
|
||||
fflush(stdout);
|
||||
|
||||
buffer->release();
|
||||
buffer = NULL;
|
||||
|
||||
mQueue.postEvent(new PlayerEvent(this, &NewPlayer::onFetchVideoFrame));
|
||||
}
|
||||
|
||||
void NewPlayer::onPause(int64_t realtime_us) {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
android::ProcessState::self()->startThreadPool();
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "usage: %s filename\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
NewPlayer player;
|
||||
player.setSource(argv[1]);
|
||||
player.start();
|
||||
sleep(10);
|
||||
player.stop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <media/stagefright/MmapSource.h>
|
||||
#include <media/stagefright/OMXClient.h>
|
||||
#include <media/stagefright/OMXCodec.h>
|
||||
#include <media/stagefright/OMXDecoder.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
@@ -87,8 +86,6 @@ private:
|
||||
DummySource &operator=(const DummySource &);
|
||||
};
|
||||
|
||||
#define USE_OMX_CODEC 1
|
||||
|
||||
sp<MediaSource> createSource(const char *filename) {
|
||||
sp<MediaSource> source;
|
||||
|
||||
@@ -140,13 +137,8 @@ int main(int argc, char **argv) {
|
||||
|
||||
sp<MetaData> meta = source->getFormat();
|
||||
|
||||
#if USE_OMX_CODEC
|
||||
sp<OMXCodec> decoder = OMXCodec::Create(
|
||||
client.interface(), meta, false /* createEncoder */, source);
|
||||
#else
|
||||
sp<OMXDecoder> decoder = OMXDecoder::Create(
|
||||
&client, meta, false /* createEncoder */, source);
|
||||
#endif
|
||||
|
||||
int width, height;
|
||||
bool success = meta->findInt32(kKeyWidth, &width);
|
||||
@@ -164,14 +156,9 @@ int main(int argc, char **argv) {
|
||||
enc_meta->setInt32(kKeyWidth, width);
|
||||
enc_meta->setInt32(kKeyHeight, height);
|
||||
|
||||
#if USE_OMX_CODEC
|
||||
sp<OMXCodec> encoder =
|
||||
OMXCodec::Create(
|
||||
client.interface(), enc_meta, true /* createEncoder */, decoder);
|
||||
#else
|
||||
sp<OMXDecoder> encoder = OMXDecoder::Create(
|
||||
&client, enc_meta, true /* createEncoder */, decoder);
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <media/stagefright/MmapSource.h>
|
||||
#include <media/stagefright/OMXClient.h>
|
||||
#include <media/stagefright/OMXCodec.h>
|
||||
#include <media/stagefright/OMXDecoder.h>
|
||||
|
||||
#include "JPEGSource.h"
|
||||
|
||||
@@ -50,18 +49,11 @@ static int64_t getNowUs() {
|
||||
return (int64_t)tv.tv_usec + tv.tv_sec * 1000000;
|
||||
}
|
||||
|
||||
#define USE_OMX_CODEC 1
|
||||
|
||||
static void playSource(OMXClient *client, const sp<MediaSource> &source) {
|
||||
sp<MetaData> meta = source->getFormat();
|
||||
|
||||
#if !USE_OMX_CODEC
|
||||
sp<OMXDecoder> decoder = OMXDecoder::Create(
|
||||
client, meta, false /* createEncoder */, source);
|
||||
#else
|
||||
sp<OMXCodec> decoder = OMXCodec::Create(
|
||||
client->interface(), meta, false /* createEncoder */, source);
|
||||
#endif
|
||||
|
||||
if (decoder == NULL) {
|
||||
return;
|
||||
|
||||
@@ -119,12 +119,6 @@ struct omx_message {
|
||||
EMPTY_BUFFER_DONE,
|
||||
FILL_BUFFER_DONE,
|
||||
|
||||
// reserved for OMXDecoder use.
|
||||
START,
|
||||
INITIAL_FILL_BUFFER,
|
||||
|
||||
// reserved for OMXObserver use.
|
||||
QUIT_OBSERVER,
|
||||
} type;
|
||||
|
||||
IOMX::node_id node;
|
||||
@@ -137,28 +131,21 @@ struct omx_message {
|
||||
OMX_U32 data2;
|
||||
} event_data;
|
||||
|
||||
// if type == EMPTY_BUFFER_DONE || type == FILL_BUFFER
|
||||
// || type == INITIAL_FILL_BUFFER
|
||||
// if type == EMPTY_BUFFER_DONE
|
||||
struct {
|
||||
IOMX::buffer_id buffer;
|
||||
} buffer_data;
|
||||
|
||||
// if type == EMPTY_BUFFER || type == FILL_BUFFER_DONE
|
||||
// if type == FILL_BUFFER_DONE
|
||||
struct {
|
||||
IOMX::buffer_id buffer;
|
||||
OMX_U32 range_offset;
|
||||
OMX_U32 range_length;
|
||||
OMX_U32 flags;
|
||||
OMX_TICKS timestamp;
|
||||
OMX_PTR platform_private; // ignored if type == EMPTY_BUFFER
|
||||
OMX_PTR platform_private;
|
||||
} extended_buffer_data;
|
||||
|
||||
// if type == SEND_COMMAND
|
||||
struct {
|
||||
OMX_COMMANDTYPE cmd;
|
||||
OMX_S32 param;
|
||||
} send_command_data;
|
||||
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
@@ -20,62 +20,11 @@
|
||||
|
||||
#include <media/IOMX.h>
|
||||
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/List.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class OMXObserver {
|
||||
public:
|
||||
OMXObserver();
|
||||
virtual ~OMXObserver();
|
||||
|
||||
void postMessage(const omx_message &msg);
|
||||
|
||||
protected:
|
||||
virtual void onOMXMessage(const omx_message &msg) = 0;
|
||||
|
||||
private:
|
||||
friend class OMXClient;
|
||||
|
||||
pthread_t mThread;
|
||||
Mutex mLock;
|
||||
Condition mQueueNotEmpty;
|
||||
List<omx_message> mQueue;
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
static void *ThreadWrapper(void *me);
|
||||
void threadEntry();
|
||||
|
||||
OMXObserver(const OMXObserver &);
|
||||
OMXObserver &operator=(const OMXObserver &);
|
||||
};
|
||||
|
||||
class OMXClient;
|
||||
|
||||
class OMXClientReflector : public BnOMXObserver {
|
||||
public:
|
||||
OMXClientReflector(OMXClient *client);
|
||||
|
||||
virtual void on_message(const omx_message &msg);
|
||||
void reset();
|
||||
|
||||
private:
|
||||
OMXClient *mClient;
|
||||
|
||||
OMXClientReflector(const OMXClientReflector &);
|
||||
OMXClientReflector &operator=(const OMXClientReflector &);
|
||||
};
|
||||
|
||||
class OMXClient {
|
||||
public:
|
||||
friend class OMXClientReflector;
|
||||
|
||||
OMXClient();
|
||||
~OMXClient();
|
||||
|
||||
status_t connect();
|
||||
void disconnect();
|
||||
@@ -84,18 +33,8 @@ public:
|
||||
return mOMX;
|
||||
}
|
||||
|
||||
status_t registerObserver(IOMX::node_id node, OMXObserver *observer);
|
||||
void unregisterObserver(IOMX::node_id node);
|
||||
|
||||
private:
|
||||
sp<IOMX> mOMX;
|
||||
Mutex mLock;
|
||||
|
||||
KeyedVector<IOMX::node_id, OMXObserver *> mObservers;
|
||||
|
||||
sp<OMXClientReflector> mReflector;
|
||||
|
||||
bool onOMXMessage(const omx_message &msg);
|
||||
|
||||
OMXClient(const OMXClient &);
|
||||
OMXClient &operator=(const OMXClient &);
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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.
|
||||
*/
|
||||
|
||||
#ifndef OMX_DECODER_H_
|
||||
|
||||
#define OMX_DECODER_H_
|
||||
|
||||
#include <binder/MemoryDealer.h>
|
||||
#include <media/stagefright/MediaBuffer.h>
|
||||
#include <media/stagefright/MediaSource.h>
|
||||
#include <media/stagefright/OMXClient.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/List.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
#include <OMX_Video.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class OMXMediaBuffer;
|
||||
|
||||
class OMXDecoder : public MediaSource,
|
||||
public OMXObserver,
|
||||
public MediaBufferObserver {
|
||||
public:
|
||||
static sp<OMXDecoder> Create(
|
||||
OMXClient *client, const sp<MetaData> &data,
|
||||
bool createEncoder,
|
||||
const sp<MediaSource> &source);
|
||||
|
||||
virtual status_t start(MetaData *params = NULL);
|
||||
virtual status_t stop();
|
||||
|
||||
virtual sp<MetaData> getFormat();
|
||||
|
||||
virtual status_t read(
|
||||
MediaBuffer **buffer, const ReadOptions *options = NULL);
|
||||
|
||||
void addCodecSpecificData(const void *data, size_t size);
|
||||
|
||||
// from OMXObserver
|
||||
virtual void onOMXMessage(const omx_message &msg);
|
||||
|
||||
// from MediaBufferObserver
|
||||
virtual void signalBufferReturned(MediaBuffer *buffer);
|
||||
|
||||
protected:
|
||||
virtual ~OMXDecoder();
|
||||
|
||||
private:
|
||||
enum {
|
||||
kPortIndexInput = 0,
|
||||
kPortIndexOutput = 1
|
||||
};
|
||||
|
||||
enum PortStatus {
|
||||
kPortStatusActive = 0,
|
||||
kPortStatusDisabled = 1,
|
||||
kPortStatusShutdown = 2,
|
||||
kPortStatusFlushing = 3,
|
||||
kPortStatusFlushingToDisabled = 4,
|
||||
kPortStatusFlushingToShutdown = 5,
|
||||
};
|
||||
|
||||
enum Quirks {
|
||||
kWantsNALFragments = 1,
|
||||
kDoesntReturnBuffersOnDisable = 2,
|
||||
kDoesntFlushOnExecutingToIdle = 4,
|
||||
kDoesntProperlyFlushAllPortsAtOnce = 8,
|
||||
kRequiresAllocateBufferOnInputPorts = 16,
|
||||
kRequiresAllocateBufferOnOutputPorts = 32,
|
||||
kRequiresLoadedToIdleAfterAllocation = 64,
|
||||
kMeasuresTimeInMilliseconds = 128,
|
||||
};
|
||||
|
||||
OMXClient *mClient;
|
||||
sp<IOMX> mOMX;
|
||||
IOMX::node_id mNode;
|
||||
char *mComponentName;
|
||||
char *mMIME;
|
||||
bool mIsMP3;
|
||||
bool mIsAVC;
|
||||
bool mIsEncoder;
|
||||
uint32_t mQuirks;
|
||||
|
||||
sp<MediaSource> mSource;
|
||||
sp<MetaData> mOutputFormat;
|
||||
|
||||
Mutex mLock;
|
||||
Condition mOutputBufferAvailable;
|
||||
|
||||
List<MediaBuffer *> mOutputBuffers;
|
||||
|
||||
struct CodecSpecificData {
|
||||
void *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
List<CodecSpecificData> mCodecSpecificData;
|
||||
List<CodecSpecificData>::iterator mCodecSpecificDataIterator;
|
||||
|
||||
volatile OMX_STATETYPE mState;
|
||||
OMX_U32 mPortStatusMask;
|
||||
bool mShutdownInitiated;
|
||||
|
||||
typedef List<IOMX::buffer_id> BufferList;
|
||||
Vector<BufferList> mBuffers;
|
||||
|
||||
KeyedVector<IOMX::buffer_id, sp<IMemory> > mBufferMap;
|
||||
KeyedVector<IOMX::buffer_id, OMXMediaBuffer *> mMediaBufferMap;
|
||||
|
||||
sp<MemoryDealer> mDealer;
|
||||
|
||||
bool mSeeking;
|
||||
int64_t mSeekTimeUs;
|
||||
|
||||
bool mStarted;
|
||||
status_t mErrorCondition;
|
||||
bool mReachedEndOfInput;
|
||||
|
||||
OMXDecoder(OMXClient *client, IOMX::node_id node,
|
||||
const char *mime, const char *codec,
|
||||
bool is_encoder,
|
||||
uint32_t quirks,
|
||||
const sp<MediaSource> &source);
|
||||
|
||||
void setPortStatus(OMX_U32 port_index, PortStatus status);
|
||||
PortStatus getPortStatus(OMX_U32 port_index) const;
|
||||
|
||||
void allocateBuffers(OMX_U32 port_index);
|
||||
|
||||
void setAMRFormat();
|
||||
void setAACFormat();
|
||||
|
||||
status_t setVideoPortFormatType(
|
||||
OMX_U32 portIndex,
|
||||
OMX_VIDEO_CODINGTYPE compressionFormat,
|
||||
OMX_COLOR_FORMATTYPE colorFormat);
|
||||
|
||||
void setVideoOutputFormat(const char *mime, OMX_U32 width, OMX_U32 height);
|
||||
void setVideoInputFormat(const char *mime, OMX_U32 width, OMX_U32 height);
|
||||
void setup();
|
||||
void dumpPortDefinition(OMX_U32 port_index);
|
||||
|
||||
void onStart();
|
||||
void onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
|
||||
void onEventCmdComplete(OMX_COMMANDTYPE type, OMX_U32 data);
|
||||
void onEventPortSettingsChanged(OMX_U32 port_index);
|
||||
void onStateChanged(OMX_STATETYPE to);
|
||||
void onEmptyBufferDone(IOMX::buffer_id buffer);
|
||||
void onFillBufferDone(const omx_message &msg);
|
||||
|
||||
void onRealEmptyBufferDone(IOMX::buffer_id buffer);
|
||||
void onRealFillBufferDone(const omx_message &msg);
|
||||
|
||||
void initiateShutdown();
|
||||
|
||||
void freeInputBuffer(IOMX::buffer_id buffer);
|
||||
void freeOutputBuffer(IOMX::buffer_id buffer);
|
||||
void freePortBuffers(OMX_U32 port_index);
|
||||
|
||||
void postStart();
|
||||
void postEmptyBufferDone(IOMX::buffer_id buffer);
|
||||
void postInitialFillBuffer(IOMX::buffer_id buffer);
|
||||
|
||||
OMXDecoder(const OMXDecoder &);
|
||||
OMXDecoder &operator=(const OMXDecoder &);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // OMX_DECODER_H_
|
||||
@@ -26,7 +26,6 @@ LOCAL_SRC_FILES:= \
|
||||
AudioPlayer.cpp \
|
||||
ESDS.cpp \
|
||||
OMXClient.cpp \
|
||||
OMXDecoder.cpp \
|
||||
string.cpp
|
||||
|
||||
LOCAL_C_INCLUDES:= \
|
||||
|
||||
@@ -33,14 +33,11 @@
|
||||
#include <media/stagefright/MetaData.h>
|
||||
#include <media/stagefright/MmapSource.h>
|
||||
#include <media/stagefright/OMXCodec.h>
|
||||
#include <media/stagefright/OMXDecoder.h>
|
||||
#include <media/stagefright/ShoutcastSource.h>
|
||||
#include <media/stagefright/TimeSource.h>
|
||||
#include <ui/PixelFormat.h>
|
||||
#include <ui/Surface.h>
|
||||
|
||||
#define USE_OMX_CODEC 1
|
||||
|
||||
namespace android {
|
||||
|
||||
MediaPlayerImpl::MediaPlayerImpl(const char *uri)
|
||||
@@ -406,13 +403,8 @@ void MediaPlayerImpl::setAudioSource(const sp<MediaSource> &source) {
|
||||
|
||||
sp<MetaData> meta = source->getFormat();
|
||||
|
||||
#if !USE_OMX_CODEC
|
||||
mAudioDecoder = OMXDecoder::Create(
|
||||
&mClient, meta, false /* createEncoder */, source);
|
||||
#else
|
||||
mAudioDecoder = OMXCodec::Create(
|
||||
mClient.interface(), meta, false /* createEncoder */, source);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MediaPlayerImpl::setVideoSource(const sp<MediaSource> &source) {
|
||||
@@ -427,13 +419,8 @@ void MediaPlayerImpl::setVideoSource(const sp<MediaSource> &source) {
|
||||
success = meta->findInt32(kKeyHeight, &mVideoHeight);
|
||||
CHECK(success);
|
||||
|
||||
#if !USE_OMX_CODEC
|
||||
mVideoDecoder = OMXDecoder::Create(
|
||||
&mClient, meta, false /* createEncoder */, source);
|
||||
#else
|
||||
mVideoDecoder = OMXCodec::Create(
|
||||
mClient.interface(), meta, false /* createEncoder */, source);
|
||||
#endif
|
||||
|
||||
if (mISurface.get() != NULL || mSurface.get() != NULL) {
|
||||
depopulateISurface();
|
||||
|
||||
@@ -18,11 +18,8 @@
|
||||
#define LOG_TAG "OMXClient"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <media/IMediaPlayerService.h>
|
||||
#include <media/IOMX.h>
|
||||
#include <media/stagefright/MediaDebug.h>
|
||||
#include <media/stagefright/OMXClient.h>
|
||||
|
||||
@@ -31,13 +28,7 @@ namespace android {
|
||||
OMXClient::OMXClient() {
|
||||
}
|
||||
|
||||
OMXClient::~OMXClient() {
|
||||
disconnect();
|
||||
}
|
||||
|
||||
status_t OMXClient::connect() {
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
|
||||
sp<IServiceManager> sm = defaultServiceManager();
|
||||
sp<IBinder> binder = sm->getService(String16("media.player"));
|
||||
sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
|
||||
@@ -47,175 +38,10 @@ status_t OMXClient::connect() {
|
||||
mOMX = service->createOMX();
|
||||
CHECK(mOMX.get() != NULL);
|
||||
|
||||
mReflector = new OMXClientReflector(this);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void OMXClient::disconnect() {
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
|
||||
if (mReflector.get() != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(mObservers.isEmpty());
|
||||
|
||||
mReflector->reset();
|
||||
mReflector.clear();
|
||||
}
|
||||
|
||||
status_t OMXClient::registerObserver(
|
||||
IOMX::node_id node, OMXObserver *observer) {
|
||||
Mutex::Autolock autoLock(&mLock);
|
||||
|
||||
ssize_t index = mObservers.indexOfKey(node);
|
||||
if (index >= 0) {
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
mObservers.add(node, observer);
|
||||
observer->start();
|
||||
|
||||
mOMX->observe_node(node, mReflector);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void OMXClient::unregisterObserver(IOMX::node_id node) {
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
|
||||
ssize_t index = mObservers.indexOfKey(node);
|
||||
CHECK(index >= 0);
|
||||
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
OMXObserver *observer = mObservers.valueAt(index);
|
||||
observer->stop();
|
||||
mObservers.removeItemsAt(index);
|
||||
}
|
||||
|
||||
bool OMXClient::onOMXMessage(const omx_message &msg) {
|
||||
bool done = false;
|
||||
|
||||
switch (msg.type) {
|
||||
case omx_message::EVENT:
|
||||
{
|
||||
LOGV("OnEvent node:%p event:%d data1:%ld data2:%ld",
|
||||
msg.u.event_data.node,
|
||||
msg.u.event_data.event,
|
||||
msg.u.event_data.data1,
|
||||
msg.u.event_data.data2);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case omx_message::FILL_BUFFER_DONE:
|
||||
{
|
||||
LOGV("FillBufferDone %p", msg.u.extended_buffer_data.buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
case omx_message::EMPTY_BUFFER_DONE:
|
||||
{
|
||||
LOGV("EmptyBufferDone %p", msg.u.buffer_data.buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOGE("received unknown omx_message type %d", msg.type);
|
||||
break;
|
||||
}
|
||||
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
ssize_t index = mObservers.indexOfKey(msg.node);
|
||||
|
||||
if (index >= 0) {
|
||||
mObservers.editValueAt(index)->postMessage(msg);
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OMXObserver::OMXObserver() {
|
||||
}
|
||||
|
||||
OMXObserver::~OMXObserver() {
|
||||
}
|
||||
|
||||
void OMXObserver::start() {
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||
|
||||
int err = pthread_create(&mThread, &attr, ThreadWrapper, this);
|
||||
CHECK_EQ(err, 0);
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
|
||||
void OMXObserver::stop() {
|
||||
omx_message msg;
|
||||
msg.type = omx_message::QUIT_OBSERVER;
|
||||
postMessage(msg);
|
||||
|
||||
void *dummy;
|
||||
pthread_join(mThread, &dummy);
|
||||
}
|
||||
|
||||
void OMXObserver::postMessage(const omx_message &msg) {
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
mQueue.push_back(msg);
|
||||
mQueueNotEmpty.signal();
|
||||
}
|
||||
|
||||
// static
|
||||
void *OMXObserver::ThreadWrapper(void *me) {
|
||||
static_cast<OMXObserver *>(me)->threadEntry();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void OMXObserver::threadEntry() {
|
||||
for (;;) {
|
||||
omx_message msg;
|
||||
|
||||
{
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
while (mQueue.empty()) {
|
||||
mQueueNotEmpty.wait(mLock);
|
||||
}
|
||||
|
||||
msg = *mQueue.begin();
|
||||
mQueue.erase(mQueue.begin());
|
||||
}
|
||||
|
||||
if (msg.type == omx_message::QUIT_OBSERVER) {
|
||||
break;
|
||||
}
|
||||
|
||||
onOMXMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OMXClientReflector::OMXClientReflector(OMXClient *client)
|
||||
: mClient(client) {
|
||||
}
|
||||
|
||||
void OMXClientReflector::on_message(const omx_message &msg) {
|
||||
if (mClient != NULL) {
|
||||
mClient->onOMXMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void OMXClientReflector::reset() {
|
||||
mClient = NULL;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user