当前位置: 首页 > news >正文

做报纸能经常更新网站网站和服务器是什么

做报纸能经常更新网站,网站和服务器是什么,佛山全网优化,运营一个网站要多少钱android 的多媒体系统 多媒体系统的结构和业务 多媒体系统的宏鸡观结构 应用层#xff0c;java框架层,c 语言层,硬件抽像层,其中输入输出由HAL层,处理环节由packetView的OpenCore实现, 多媒体业备有以下几种: musicPlayer(音频播放器) viderPlayer(视频播放器) Camera(照… android 的多媒体系统 多媒体系统的结构和业务 多媒体系统的宏鸡观结构 应用层java框架层,c 语言层,硬件抽像层,其中输入输出由HAL层,处理环节由packetView的OpenCore实现, 多媒体业备有以下几种: musicPlayer(音频播放器) viderPlayer(视频播放器) Camera(照相机) soundRecord(录音机) videoCamera (摄像机) Media metadata(媒体元信息) 核心是媒体的播放和录制分别由下层的OpenCore的PVPlayer和PVAuthor来实现 多媒体的java类: \frameworks\base\media\java\android\media Jni部分的代码路径 \frameworks\base\media\jni   最终编译生成libMedia_jni.so 多媒体的本地框架: \frameworks\base\include\media \frameworks\base\media\libmedia 最终被子编译成libmedia.so 多媒体的服务部分 库的代码路径\frameworks\base\media\libmediaplayerservice 最后编译生成:libmediaplayerservice.so 守护进程的代码路径:\frameworks\base\media\mediaserver 多媒体的实现部分 多媒体的各种业务 多媒体从实现角度看, 分为两部分 输入/输出环节  中间处理环节(文件格式的处理和编解码环节) 例如一个mp3的播放 Mp3格式文件的解析,mp3编码流的解码pcm输出的播放 媒体播放器涉及内容 本地媒体揪放器部分; PVPlayer(实现的核心部分)    音频视频的编解码  音频输出环节 视频输出环节  (surface或者是overlay) Android.media.mediaplayer Android.view.surface Andorid.widget.videoview 数据流在android 媒体播放器中的运行情况是 上层的java应用程序将媒体的URI设置到媒体播放器中. Java框架架-----JNI--------本地框架-------PVPlayer中, PVPlayer解析后将媒体分为音频流和视频流 经过编码器的处理和同步(AVSync)转换成原始数据(音频是PCM视频一般是YUV或者是RGB) 照相机的统结构 录音机的系统结构 本地媒体框架中的媒体记录器部分 PVPlayer 音频编码模块 音频输入环节 android.media.mediaRecorder soundRecorder 摄像机的系统结构 本地框加的媒体记录器部分 PVAuthor 音频/视频编码模块 音频输入环节 Camera的本地接口 视频输出环节 android.media.MediaRecorder Android.view.surface Andoird.widget.videoview Music包和camera包 多媒体系统的各个层次 libMedia的框架部分 媒体播放器 头文件的目录 \frameworks\base\include\media 主要的头文件有 Mediaplayer.h媒体播放器本地部分的上层接口  提供了对上层的调用,通过JNI将接口给java调用其实都是调用下层的mediaplayer 继承自Bnmediaplayerclient. 部分代码如下 class MediaPlayer : public BnMediaPlayerClient, public virtual IMediaDeathNotifier { public: MediaPlayer(); ~MediaPlayer(); void            died(); void            disconnect(); status_t        setDataSource( const char *url,//设置数据源url const KeyedVectorString8, String8 *headers); status_t        setDataSource(int fd, int64_t offset, int64_t length);//设置数据源文件 status_t        setVideoSurface(const spSurface surface);//设视频输出界面 status_t        setListener(const spMediaPlayerListener listener);//设置临听 status_t        prepare();//准备播放 status_t        prepareAsync();//异部准备播放 status_t        start();//开始 status_t        stop();//停止 status_t        pause();//暂停 bool            isPlaying();//是否正在播放 status_t        getVideoWidth(int *w);//获取视频播放的宽 status_t        getVideoHeight(int *h);//获取视频播放的高  status_t        seekTo(int msec);//跳转到指定位置 status_t        getCurrentPosition(int *msec);//取得当前的播放位置 status_t        getDuration(int *msec);//播放的持续时间(总时长) status_t        reset();//复位 status_t        setAudioStreamType(int type);//设置音频流的格式 status_t        setLooping(int loop);// 设置循环 bool            isLooping();//是否循环 status_t        setVolume(float leftVolume, float rightVolume);//设置音量 void            notify(int msg, int ext1, int ext2);//通知函数 static  spIMemory     decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); static  spIMemory     decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); status_t        invoke(const Parcel request, Parcel *reply); status_t        setMetadataFilter(const Parcel filter); status_t        getMetadata(bool update_only, bool apply_filter, Parcel *metadata); status_t        suspend(); status_t        resume(); status_t        setAudioSessionId(int sessionId); int             getAudioSessionId(); status_t        setAuxEffectSendLevel(float level); status_t        attachAuxEffect(int effectId); private: void            clear_l(); status_t        seekTo_l(int msec); status_t        prepareAsync_l(); status_t        getDuration_l(int *msec); status_t        setDataSource(const spIMediaPlayer player); spIMediaPlayer            mPlayer; thread_id_t                 mLockThreadId; Mutex                       mLock; Mutex                       mNotifyLock; Condition                   mSignal; spMediaPlayerListener     mListener; void*                       mCookie; media_player_states         mCurrentState; int                         mDuration; int                         mCurrentPosition; int                         mSeekPosition; bool                        mPrepareSync; status_t                    mPrepareStatus; int                         mStreamType; bool                        mLoop; float                       mLeftVolume; float                       mRightVolume; int                         mVideoWidth; int                         mVideoHeight; int                         mAudioSessionId; float                       mSendLevel; }; IMeciaplayer.h 媒体播和器服务部分的接口(和上层的mediaplay 中的接口方法类似) 被BnMedaplayer继承,提供Binder通信本地实现基础 部分代码如下 //继承mediaplayerBase,通过autoFlinger输出 class MediaPlayerInterface : public MediaPlayerBase{ public: virtual             ~MediaPlayerInterface() { } virtual bool        hardwareOutput() { return false; } virtual void        setAudioSink(const spAudioSink audioSink) { mAudioSink  audioSink; } protected: spAudioSink       mAudioSink;//音频轮输出设备的抽像接口 }; // Implement this class for media players that output directo to hardware //直接从硬功夫件进行音频输出 class MediaPlayerHWInterface : public MediaPlayerBase//继承mediaplayerBaser { public: virtual             ~MediaPlayerHWInterface() {} virtual bool        hardwareOutput() { return true; } virtual status_t    setVolume(float leftVolume, float rightVolume)  0; virtual status_t    setAudioStreamType(int streamType)  0; }; mediaplayerInterface.h PVPlayer.h是媒体播放器实现层的接口 (是opencore媒体播放器实现的头文件) 继承自MediaPlayerInterface 部分代码如下 class PVPlayer : public MediaPlayerInterface { public: PVPlayer(); virtual             ~PVPlayer(); virtual status_t    initCheck(); virtual status_t    setDataSource( const char *url, const KeyedVectorString8, String8 *headers); virtual status_t    setDataSource(int fd, int64_t offset, int64_t length); virtual status_t    setVideoSurface(const spISurface surface); virtual status_t    prepare(); virtual status_t    prepareAsync(); virtual status_t    start(); virtual status_t    stop(); virtual status_t    pause(); virtual bool        isPlaying(); virtual status_t    seekTo(int msec); virtual status_t    getCurrentPosition(int *msec); virtual status_t    getDuration(int *msec); virtual status_t    reset(); virtual status_t    setLooping(int loop); virtual player_type playerType() { return PV_PLAYER; } virtual status_t    invoke(const Parcel request, Parcel *reply); virtual status_t    getMetadata( const SortedVectormedia::Metadata::Type ids, Parcel *records); // make available to PlayerDriver void        sendEvent(int msg, int ext10, int ext20) { MediaPlayerBase::sendEvent(msg, ext1, ext2); } private: static void         do_nothing(status_t s, void *cookie, bool cancelled) { } static void         run_init(status_t s, void *cookie, bool cancelled); static void         run_set_video_surface(status_t s, void *cookie, bool cancelled); static void         run_set_audio_output(status_t s, void *cookie, bool cancelled); static void         run_prepare(status_t s, void *cookie, bool cancelled); static void         check_for_live_streaming(status_t s, void *cookie, bool cancelled); PlayerDriver*               mPlayerDriver; char *                      mDataSourcePath; bool                        mIsDataSourceSet; spISurface                mSurface; int                         mSharedFd; status_t                    mInit; int                         mDuration; #ifdef MAX_OPENCORE_INSTANCES static volatile int32_t     sNumInstances; #endif }; ImeciaplayerClient.h 多媒体的客户端(定义了媒体的客户端)  主要用作通知函数 Mediaplayer继承ImediaplayerClient 所以可以得到下层传弟的信息 部分代码如下 class IMediaPlayerClient: public IInterface { public: DECLARE_META_INTERFACE(MediaPlayerClient); virtual void notify(int msg, int ext1, int ext2)  0;//通知的信息是个消息 }; Imediaplayerservice.h 多媒体的服务(定义了多媒体服务的接口由下层服务去实现) 部分代码如下 class IMediaPlayerService: public IInterface { public: DECLARE_META_INTERFACE(MediaPlayerService); / virtual spIMediaRecorder  createMediaRecorder(pid_t pid)  0; virtual spIMediaMetadataRetriever createMetadataRetriever(pid_t pid)  0; /创建IMediaPlayer virtual spIMediaPlayer create(pid_t pid, const spIMediaPlayerClient client, const char* url, const KeyedVectorString8, String8 *headers  NULL, int audioSessionId  0)  0; virtual spIMediaPlayer create(pid_t pid, const spIMediaPlayerClient client, int fd, int64_t offset, int64_t length, int audioSessionId)  0; //用于直接解码 virtual spIMemory         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)  0; virtual spIMemory         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)  0; virtual spIOMX            getOMX()  0; }; // ---------------------------------------------------------------------------- class BnMediaPlayerService: public BnInterfaceIMediaPlayerService { public: virtual status_t    onTransact( uint32_t code, const Parcel data, Parcel* reply, uint32_t flags  0); }; 源文件的目录 \frameworks\base\media\libmedia 媒体记录器 头文件和实现文件的代码路径: \frameworks\base\include\media 主要的头文件有 MediaRecorder.h 媒体记录器的上层拉接口,每个函数都调用IMediaRecord来实现, 他也继承了BnMediaPlayerClient用于接收下层返回的通知 部分代码如下 class MediaRecorder : public BnMediaRecorderClient, public virtual IMediaDeathNotifier { public: MediaRecorder(); ~MediaRecorder(); void        died(); status_t    initCheck(); status_t    setCamera(const spICamera camera);  //设置camera作为输入设备 status_t    setPreviewSurface(const spSurface surface); //设置视频预览界面 status_t    setVideoSource(int vs);  //视频数据源( 枚举值) status_t    setAudioSource(int as);  //音频数据源 (同上) status_t    setOutputFormat(int of);  //设置输出格式 status_t    setVideoEncoder(int ve);  //设置视频编码格式 status_t    setAudioEncoder(int ae);   //设置音频编码格式 status_t    setOutputFile(const char* path);  //设置输出文件路径 status_t    setOutputFile(int fd, int64_t offset, int64_t length); //设置输出文件的文件描述符 status_t    setVideoSize(int width, int height);  //设置视频尺寸 status_t    setVideoFrameRate(int frames_per_second);  //设置视频帧率 status_t    setParameters(const String8 params);  //设置其他参数 status_t    setListener(const spMediaRecorderListener listener);  //设置临听 status_t    prepare();  //准备录制 status_t    getMaxAmplitude(int* max);  //获得最大增益 status_t    start();   //开始 status_t    stop();   //停止 status_t    reset();  //复位 status_t    init();  //初始化记录器 status_t    close(); //关闭记录器 status_t    release();  //释放资源 void        notify(int msg, int ext1, int ext2); private: void                    doCleanUp(); status_t                doReset(); spIMediaRecorder          mMediaRecorder; spMediaRecorderListener   mListener; media_recorder_states       mCurrentState; bool                        mIsAudioSourceSet; bool                        mIsVideoSourceSet; bool                        mIsAudioEncoderSet; bool                        mIsVideoEncoderSet; bool                        mIsOutputFileSet; Mutex                       mLock; Mutex                       mNotifyLock; }; };  IMediaRecorder.h 媒体记录器的部分实现接口  部分代码如下 class IMediaRecorder: public IInterface { public: DECLARE_META_INTERFACE(MediaRecorder); virtual status_t setCamera(const spICamera camera)  0; virtual status_t setPreviewSurface(const spISurface surface)  0; virtual status_t setVideoSource(int vs)  0; virtual status_t setAudioSource(int as)  0; virtual status_t setOutputFormat(int of)  0; virtual status_t setVideoEncoder(int ve)  0; virtual status_t setAudioEncoder(int ae)  0; virtual status_t setOutputFile(const char* path)  0; virtual status_t setOutputFile(int fd, int64_t offset, int64_t length)  0; virtual status_t setVideoSize(int width, int height)  0; virtual status_t setVideoFrameRate(int frames_per_second)  0; virtual     status_t                setParameters(const String8 params)  0; virtual     status_t                setListener(const spIMediaRecorderClient listener)  0; virtual status_t prepare()  0; virtual status_t getMaxAmplitude(int* max)  0; virtual status_t start()  0; virtual status_t stop()  0; virtual status_t reset()  0; virtual status_t        init()  0; virtual status_t        close()  0; virtual status_t release()  0; }; // ---------------------------------------------------------------------------- class BnMediaRecorder: public BnInterfaceIMediaRecorder { public: virtual status_t    onTransact( uint32_t code, const Parcel data, Parcel* reply, uint32_t flags  0); }; }; PVMediaRecorder.h 下层接口,由openCore实现 媒体元信息和扫描器 主要的头文件有 MediaMetadataRetriever.h 部分代码如下 class MediaMetadataRetriever: public RefBase { public: MediaMetadataRetriever(); ~MediaMetadataRetriever(); void disconnect(); status_t setDataSource(const char* dataSourceUrl);  //设置数据源(url) status_t setDataSource(int fd, int64_t offset, int64_t length);  //设置数据源(文件描述符) spIMemory getFrameAtTime(int64_t timeUs, int option); //捕获帧 spIMemory extractAlbumArt();  // 抽取 const char* extractMetadata(int keyCode);  //抽取元信息 IMediaMetadataRetriever MediaMetadataRetrieverInterface.h 实现的接口文件 PVMetadataRetriever.h     下层实现的接口 class MediaMetadataRetrieverBase : public RefBase{} class MediaMetadataRetrieverInterface : public MediaMetadataRetrieverBase{} class PVMetadataRetriever : public MediaMetadataRetrieverInterface{} 媒体扫描器的头文件 MediaScanner .h  scanner的接口扫描一个文件或者一个文件夹取得文件格式会调用MediaScannerClient 部分代码如下: struct MediaScanner { MediaScanner(); virtual ~MediaScanner(); virtual status_t processFile( const char *path, const char *mimeType, MediaScannerClient client)  0; typedef bool (*ExceptionCheck)(void* env); virtual status_t processDirectory( const char *path, const char *extensions, MediaScannerClient client, ExceptionCheck exceptionCheck, void *exceptionEnv); void setLocale(const char *locale); // extracts album art as a block of data virtual char *extractAlbumArt(int fd)  0; } class MediaScannerClient { public: MediaScannerClient(); virtual ~MediaScannerClient(); void setLocale(const char* locale); void beginFile(); bool addStringTag(const char* name, const char* value); void endFile(); virtual bool scanFile(const char* path, long long lastModified, long long fileSize)  0; virtual bool handleStringTag(const char* name, const char* value)  0; virtual bool setMimeType(const char* mimeType)  0; virtual bool addNoMediaFolder(const char* path)  0; } 多媒体服务 他包含媒体揪放器, 媒体记录器,媒体元信息管理 他和他的调用者是在两个不同的进程中,使用binder进行IPC通信 多媒体服务的守护进程main_mediaserver.cpp 代码中和路径: \frameworks\base\media\mediaserver 部分代码如下 int main(int argc, char** argv) { spProcessState proc(ProcessState::self()); spIServiceManager sm  defaultServiceManager(); LOGI(ServiceManager: %p, sm.get()); AudioFlinger::instantiate();     //用于声音的混合 MediaPlayerService::instantiate();  //用于音频播放 CameraService::instantiate();     //摄像头相关服务 AudioPolicyService::instantiate(); ProcessState::self()-startThreadPool(); IPCThreadState::self()-joinThreadPool(); } audioFlinger 是通过defaultServiceMannager获取IServiceMamager接口 通过addService方法注册为 Media.audido_flinger Mediaserver作为一个守护进程在android的init.rc中具有如下定义 Service media /system/bin/mediaserver User media Group system audio camera graphics inet net_bt net_bt_admin 由于没有定义oneshot所以这个进程一直存在如果被杀死init会将其重新启动 多媒体服务的实现 多媒体服务的路径:\frameworks\base\media\libmediaplayerservice mediaPlayerService.h头文件中定义了 ,是IMediaplayer的实现 class MediaPlayerService : public BnMediaPlayerService{ class AudioOutput : public MediaPlayerBase::AudioSink {} class AudioCache : public MediaPlayerBase::AudioSink{} class Client : public BnMediaPlayer {} } 是IMeciaRecorder的实现 class MediaRecorderClient : public BnMediaRecorder{} 是IMediadataRetriever的实现 class MetadataRetrieverClient : public BnMediaMetadataRetriever{} MediaPlayerService.cpp中定义了取得媒体记录器(IMediaRecorder)的接口 spIMediaRecorder MediaPlayerService::createMediaRecorder(pid_t pid) { spMediaRecorderClient recorder  new MediaRecorderClient(this, pid); wpMediaRecorderClient w  recorder; Mutex::Autolock lock(mLock); mMediaRecorderClients.add(w); LOGV(Create new media recorder client from pid %d, pid); return recorder; } 取得媒体播放器的媒体元信息 spIMediaMetadataRetriever MediaPlayerService::createMetadataRetriever(pid_t pid) { spMetadataRetrieverClient retriever  new MetadataRetrieverClient(pid); LOGV(Create new media retriever from pid %d, pid); return retriever; } MediaPlayService 类中创建媒体播放器的过程 1 spIMediaPlayer MediaPlayerService::create(pid_t pid, const spIMediaPlayerClient client, int fd, int64_t offset, int64_t length, int audioSessionId) { int32_t connId  android_atomic_inc(mNextConnId); //创建mediaPlayerService::Client类 spClient c  new Client(this, pid, connId, client, audioSessionId); LOGV(Create new client(%d) from pid %d, fd%d, offset%lld, length%lld, audioSessionId%d, connId, pid, fd, offset, length, audioSessionId); //设置源的url if (NO_ERROR ! c-setDataSource(fd, offset, length)) {//根据setDataSource()时根据输入的类型创建不同的mediaPlayBase, 接着调用下面的createPlayer方法创建不同的player c.clear(); } else { wpClient w  c; Mutex::Autolock lock(mLock); mClients.add(w); } ::close(fd); return c; } static spMediaPlayerBase createPlayer(player_type playerType, void* cookie, notify_callback_f notifyFunc) { spMediaPlayerBase p; switch (playerType) {  //根据playerType的类型建立不同的播放器 #ifndef NO_OPENCORE case PV_PLAYER: LOGV( create PVPlayer); p  new PVPlayer(); break; #endif case SONIVOX_PLAYER: LOGV( create MidiFile); p  new MidiFile(); break; case STAGEFRIGHT_PLAYER: LOGV( create StagefrightPlayer); p  new StagefrightPlayer; break; case TEST_PLAYER: LOGV(Create Test Player stub); p  new TestPlayerStub(); break; } if (p ! NULL) { if (p-initCheck()  NO_ERROR) { p-setNotifyCallback(cookie, notifyFunc); } else { p.clear(); } } if (p  NULL) { LOGE(Failed to create player object); } return p; } PVPlayer  MidiFile和VorbisPlayer三个都继承MediaPlayInterface得到的MediaPlayerInterface是继承MediaPlayerBase得到,  三者具有相同的接口类型,三者在建立之后通过MediaPlayerBase接口来控制他们 媒体播放器的实现结构如下图所示 MediaPlayerService::AudioOutput实现audio输出环节的封装由Audio系统来实现主要是调用AudioTrakc的接口 status_t MediaPlayerService::AudioOutput::open( uint32_t sampleRate, int channelCount, int format, int bufferCount, AudioCallback cb, void *cookie) { mCallback  cb; mCallbackCookie  cookie; // Check argument bufferCount against the mininum buffer count if (bufferCount  mMinBufferCount) { LOGD(bufferCount (%d) is too small and increased to %d, bufferCount, mMinBufferCount); bufferCount  mMinBufferCount; } LOGV(open(%u, %d, %d, %d, %d), sampleRate, channelCount, format, bufferCount,mSessionId); if (mTrack) close(); int afSampleRate; int afFrameCount; int frameCount; if (AudioSystem::getOutputFrameCount(afFrameCount, mStreamType) ! NO_ERROR) { return NO_INIT; } if (AudioSystem::getOutputSamplingRate(afSampleRate, mStreamType) ! NO_ERROR) { return NO_INIT; } //获得帧数和采样率 frameCount  (sampleRate*afFrameCount*bufferCount)/afSampleRate; AudioTrack *t; if (mCallback ! NULL) { t  new AudioTrack( mStreamType, sampleRate, format, (channelCount  2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO, frameCount, 0 /* flags */, CallbackWrapper, this, 0, mSessionId); } else { t  new AudioTrack( mStreamType, sampleRate, format, (channelCount  2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO, frameCount, 0, NULL, NULL, 0, mSessionId); } if ((t  0) || (t-initCheck() ! NO_ERROR)) { LOGE(Unable to create audio track); delete t; return NO_INIT; } LOGV(setVolume); t-setVolume(mLeftVolume, mRightVolume); mMsecsPerFrame  1.e3 / (float) sampleRate; mLatency  t-latency(); mTrack  t; t-setAuxEffectSendLevel(mSendLevel); return t-attachAuxEffect(mAuxEffectId);; } 音频输出的接口 ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size) { LOG_FATAL_IF(mCallback ! NULL, Dont call write if supplying a callback.); //LOGV(write(%p, %u), buffer, size); if (mTrack) { ssize_t ret  mTrack-write(buffer, size); return ret; } return NO_INIT; } 多媒体的JNI部分 本地调用部分的代码路径为 Frameworks/base/media/jni 主要文件有 Android 2。3后改用stagefright \frameworks\base\media\libstagefright 两者的处理机制不同 openCore 的处理流程如下  Stagefright部分的处理流程如下 从上面可以看出 1 OpenCore的 parser和 dec是分离的各行其职stagefright则是邦在一起作为一个独立的原子操作 2 stagefright通过callback 和videoevent 来驱动数据输出, openCore是通过sink-node节点控制输出 3 Opencore中parser/dec/sink是并行处理的 stagefright 是串行处理android_media_MediaPlayer.cpp//媒体播放器 android_media_MediaRecorder.cpp//媒体记录器 android_media_MediaMetadataRetriever.cpp//媒体元信息工具 android_media_MediaScanner.cpp//媒体扫描器 这部分内容最终编译成libmedia_jni.so, 设置surface作为视频输出和取景器预览的接口没有对java提供而是在preapare()函数中直接从环境中得到并设置了。 static void android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz) { spMediaPlayer mp  getMediaPlayer(env, thiz); if (mp  NULL ) { jniThrowException(env, java/lang/IllegalStateException, NULL); return; } setVideoSurface(mp, env, thiz);//调用mediaplayer函数作视频输出设置 process_media_player_call( env, thiz, mp-prepare(), java/io/IOException, Prepare failed. ); } static void android_media_MediaRecorder_prepare(JNIEnv *env, jobject thiz) { LOGV(prepare); spMediaRecorder mr  getMediaRecorder(env, thiz); jobject surface  env-GetObjectField(thiz, fields.surface); if (surface ! NULL) { const spSurface native_surface  get_surface(env, surface); // The application may misbehave and // the preview surface becomes unavailable if (native_surface.get()  0) { LOGE(Application lost the surface); jniThrowException(env, java/io/IOException, invalid preview surface); return; } LOGI(prepare: surface%p (identity%d), native_surface.get(), native_surface-getIdentity()); //调用mediaplayer函数作视频输出设置 if (process_media_recorder_call(env, mr-setPreviewSurface(native_surface), java/lang/RuntimeException, setPreviewSurface failed.)) { return; } } process_media_recorder_call(env, mr-prepare(), java/io/IOException, prepare failed.); } 多媒体部分的java部分代码 Java框架类的路径为: frameworks\base\media\java\android\media 主要文介绍;:  MediaFile.java 文件提供了媒体文件的文件类型 MediaPlayer  MediaRecorder  MediaMetadataRecorder 等类基本上和JNI层的内容一一对应 MediaScanner在这里实现有客户端内容比较多 其中MedisPlayer   中对视频输出和取景器预览的接口 public void setDisplay(SurfaceHolder sh) { mSurfaceHolder  sh; if (sh ! null) { mSurface  sh.getSurface(); } else { mSurface  null; } _setVideoSurface(); updateSurfaceScreenOn(); } MediaRecorder中对视频输出和取景器预览的接口 public void setPreviewDisplay(Surface sv) { mSurface  sv; } Java框架层没有直接使用传递参数的方式,而是使用了保存在环境中再传递的方式 Android.widgetVideoView类. 是一个UI元素 代码路径为frameworks\base\core\java\android\widget 使用该类可以不用再调用MediaPlayer类,节省了一些中间环节 public class VideoView extends SurfaceView implements MediaPlayerControl { public void setVideoPath(String path) { }//设置源文件路径 public void setVideoURI(Uri uri) {}//设置视频的URL public void start() {}//开始播放 public void stopPlayback() {}//停止播放 public void pause() { }//暂停播放 public void seekTo(int msec) {}//更改播放位置 多媒体实现的核心部分  OpenCore 多媒体系统框架PacketVideo的开源版本OpenCore是android 多媒体本地实现在的核心 它为android提供的引警如下 PVPlayer 媒体播放器的功能  音频和视频的回放功能       PVAuthor 媒体记录器功能   音频和视频的录制 OpenCore的层次结构 自上而下分为 OSCL  (operation system compatibility  library ,操作系统兼容库) 类似一个基础的c库 PVMF   (packetVideo  Multimedia  Framework  多媒体框架)  packetVideo 的基本框架, 例如nodea基类输入输出的抽象类 文件格式处理,   文件解析parser和组成(composer)两个部分,  各种Node   是packetVideo 中的基本功能模块,  播放器(Player Engine) 播放器引擎 记录器 (author Engine) 媒体记录器引擎 注 在openCore2.X之后 开始提供了2-way engine 两路引擎  用于构建视频电话 在使用OpenCore的SDK时需要在应用层实现一个适配器 PVPlaytr和PVAuthor就是基于OpenCore的下层功能和接口构建军的应用层的库 在android 系统中  OpenCore的代码路径为externam/opencore/ Stagefright整体框图: Android froyo版本对多媒体引擎作了变动.新添加了stagefright框架,但并没有完全抛弃opencore  主要是作了一个omx 层,仅是对opencore的omx-component部分作了引用,,它在android 系统中作为 共享库(libstagefright.so)存在,  其中的module--awesomePlayer用来播放video/audio Awesomeplayer 提供的API可以供上次的应用(java/JNI)来调用 StageFrigtht数据流封装 1 MediaExtractor.cpp根据数据源DataSource生成MediaExtractor  具体实现是通过调用(代码路径为frameworks\base\media\libstagefright) spMediaExtractor MediaExtractor::Create( const spDataSource source, const char *mime) {} 通过DateSource的source-sniff(tmp, confidence, meta)来探测数据类型 2  AwesomePlayer.cpp把音视频轨道分离,生成mVideoTrack 和MediaSource  部分代码如下 if (!haveVideo  !strncasecmp(mime, video/, 6)) { setVideoSource(extractor-getTrack(i)); haveVideo  true; } else if (!haveAudio  !strncasecmp(mime, audio/, 6)) { setAudioSource(extractor-getTrack(i)); haveAudio  true; if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { // Only do this for vorbis audio, none of the other audio // formats even support this ringtone specific hack and // retrieving the metadata on some extractors may turn out // to be very expensive. spMetaData fileMeta  extractor-getMetaData(); int32_t loop; if (fileMeta ! NULL fileMeta-findInt32(kKeyAutoLoop, loop)  loop ! 0) { mFlags | AUTO_LOOPING; } } } 3 得到的两个mediaSource  只具有parser功能,没有decode功能, 还需要对两个MediaSource做进一步的包装 mAudioSource  OMXCodec::Create( mClient.interface(), mAudioTrack-getFormat(), false, // createEncoder mAudioTrack); mVideoSource  OMXCodec::Create( mClient.interface(), mVideoTrack-getFormat(), false, // createEncoder mVideoTrack, NULL, flags); 当调用mediaSource.start() 方法后, 就会开始从数据源获取数据并解析,等到缓冲区满后就停止 awesomePlayer就可以调用mediaSource的read方法读取解码后的数据 对于mVideoSource来说,   读取数据mVideoource-read(mVideoBuffer,options) 交给显示模块进行渲染,  mVideoRenderer-render(mVideoBufer)  4 stageFright的decode 经过流的封装得到两个MediaSource ,其实是两个OMXCodec, AwesomePlayer和mAudioPlayer都是从mediaSource中得到数据进行播放, 最终需要渲染的原始视频数据,也就是说OMXCodec中得到的是原始数据 部分代码如下 spMediaSource OMXCodec::Create( const spIOMX omx, //OMXNodeInstance对象的实例 const spMetaData meta, bool createEncoder, //由MediaSource.getFormat获取得到, //他的对象成员是一个keyedVectoruint32_t,typed_data //里面存放的是代表mediaSource格式信息的键值对 const spMediaSource source,  //mediaExtractor const char *matchComponentName, //指定一种codec用于生成omxcodec uint32_t flags) { //首先调用findMatchingCodecs()方法,找到对应的Codec  findMatchingCodecs( mime, createEncoder, matchComponentName, flags, matchingCodecs); //找到以后为当前的IOMX分配并注册监听事件, status_t err  omx-allocateNode(componentName, observer, node); //这样就得到了OMXCodec spOMXCodec codec  new OMXCodec( omx, node, quirks, createEncoder, mime, componentName, source); } 在AwesomePlayer中得到这个OMXCodec后首先调用mVideoSource-start()进行初始化,主要有两件事 1  向openMAX发送命令    err  mOMX-sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle); 2 err  allocateBuffers(); 分配两个缓冲区    ,freeBuffersOnPort()   分别用于输入和输出 当awesomePlayer开始播放以后,通过mVideoSource-read(mVideoBuffer,options) 读取数据 OMXCodec.read分两部来实现数据读取, 1 通过调用draininputBuffers()对mPortBuffers[kPortindexOutput]进行填充这一步完成parse 由OpenMAX从数据源把demux后的数据读取到输入缓作为OpenMAX的输入 2 通过fillOutputBuffers()对mPortBuffers[kPortIndexInput]进行填充, 这一步完成decode, 由OpenMAX对输入缓冲区的数据进行解码 3 AwesomePlayer通过mVideoRenderer-reder()对经过parse和decode处理的数据进行渲染 mVideoRenderer  new AwesomeLocalRenderer( false,  // previewOnly component, (OMX_COLOR_FORMATTYPE)format, mISurface, mVideoWidth, mVideoHeight, decodedWidth, decodedHeight, rotationDegrees); StageFright的处理流程 Audioplayer是awesomePlayer的成员audioplayer通过callback来驱动数据的获取, Awesomeplayer则是通过videoevent来驱动数据获取由mSource-Read()来完成 Read内部将parset和decod 在一起 两者进行同步部分  audio完全是callback驱动数据流 Video部分在onvideoEvent会读取audio的时间戳是传统的AV时间戳同步 AwesomePlayer的Video主要有以下几个成员 mVideoSource(解码视频) mVideoTeack(从媒体文件中读取视频数据) mVideoRenderer(对解码好的视频进行格式转换,android 使用的格式为 RGB565)  mlSurface(重绘图层) mQueue(event事件对列) Audio部分的抽像流程如下 设置mUrl路径  启动mQueue,创建一个线程threadEntry(timedEventQueue,这个线程就是event调度器) 打开mUrl指定文件头部根据不同类型选择不同的分离器例如MPEG4Extractor 使用分离器(MPEG4Extractor对MP4进行音视频轨道的分离返回MPEG4Source类型的视频轨道给mVideoTrack 根据mVideoTrack 中的编码类型来选择解码器 avc的编码类型会选择AVCDecoder,并返回给mVideoSource并设置mVideoSource中的mSource为mVideoTrack 插入到onVideoEvent到queue中,开始解码播放 通过mVideoSource对象来读取解析好的视频buffer,如果解析好的buffer还没到AV时间戳同步的时刻则推迟到下一轮操作 mVideoRenderer为空则进行初始化(如果不使用OMX会将mVideoRenderer设置为AwesomeLocalRenderer) 通过mVideoRenderer对象将解析好的视频buffer转换成RGB565格式,并发给display模块进行图像绘制 将onVideoEvent重新插入event调度器来循环    数据源到最终解码后的流程如下 URI,FD-------DataSource----------MediaExtractor------------mVideoTrack mAudioTrack(音视频数据流)---------------mVideoSource   mAudioSource(音视频解码器) 注: URI可以为;http://    rtsp://   等 FD是本地文件描述符 打开log日志 代码标记Log 依据第4》项StageFright描述的Vide视频播放流程作Log标记跟踪视频DATA获取、CODEC过程。从AwesomePlayer.cpp中方法着手步骤如下 n    在修改的/mydroid/frameworks/base/media/libstagefrigh/下用mm编译并调试直到生成相应的.so文件。注允许单模块编译时需事先在/mydroid下允许. ./build/envsetup.sh文件。 n    在/mydroid/目录下make进行整体编译生成system.img文件。说明先单模块编译后再整体编译的好处是可以缩短调试编译的时间。 n    将system.img文件copy到/android-sdk-linux/platforms/android-8/下。注意事先备份原有的system.img。 n    带sdcard启动模拟器在/android-sdk-linux/tools/下运行./adb shell文件再运行logcat n    打开Gallery选择视频文件运行并同步查看log。
http://www.dnsts.com.cn/news/51974.html

相关文章:

  • 打折网站运营思路seo常见优化技术
  • 阿里巴巴做网站费用做贵网站多少钱
  • 在58做网站推广有效果吗WordPress知更鸟破解版
  • 揭阳网站建设方案外包工程公司财务制度及流程
  • 没有做网站经验可以学seo吗南通做外贸网站
  • 武陟外贸英文网站建设汕头网站建设推广方法
  • 中国建设银行杭州分行网站seo综合查询可以关了吗
  • 网站建设工具 公司网站优化文章
  • 中介如何做网站收客怎么免费网站
  • 网站如何做360度全景做网站放太多视频
  • 企业电子商务网站有哪些功能网站制作价格东莞
  • 网站文章突然不收录dede如何手机网站和电脑网站的数据同步更新
  • 网站设计怎么自学网站推广工具网络
  • 重庆多语网站建设品牌企业wordpress主题公园下载
  • 上虞做网站公司小说小程序搭建
  • 红色扁平化网站h5网站建设哪家好
  • 网上哪个网站教做西点宝塔wordpress无法打开503
  • 做网站的是什么职业我市精神文明建设的门户网站
  • 湖北黄石域名注册网站建设如何导出WordPress主题
  • 东莞企业网站推广怎么做郴州建设信息网站
  • 响应式网站pad尺寸凤山县住房和城乡建设局网站
  • 网站上的专题 怎么设计做网站设计软件
  • 网站建设html模板下载潍坊哪里可以做网站
  • 微商可以做网站推广吗WordPress nas
  • 视频号的网站链接网站建设公司需要哪些
  • 信誉好的合肥网站推广一流的学校网站建设
  • 铜梁城乡建设网站酷家乐装修设计软件手机版免费版
  • 培训教育类网站模板下载中国建材网官方网站
  • 和田做网站的联系电话厦门哪家做网站好
  • 网站建设贵不贵网站建设申请方案文样