• Android MediaPlayer stream实现


    对于Ait类的Camera,使用已编码数据(H264)进行Preview.若使用原始的SurfaceTexture实现,需要扩展ANativeWindow支持的视频格式,也会涉及到OpenGL相关的内容,工作量巨大。

    另一种方式是使用MediaPlayer实现,MediaPlayer支持三种源,我们应该要使用Stream方式,但也不确定,看一下service的底层实现,也就是与Hardcodec的对接。另外关注一下Buffer的传递过程。

    Java Framework

      frameworks/base/media/java/android/media/MediaPlayer.java

    JNI

      frameworks/base/media/jni/android_media_MediaPlayer.cpp

    cpp Framework(libmedia.so):client

      frameworks/av/media/libmedia

    include 

      frameworks/av/include/media

    Service

      frameworks/av/media/libmediaplayerservice

    1、APP@packages/apps/Launchertv/src/com/xxxx/Launcher/VideoMediaPlayer.java

    对于一个简单的APP,例如Jervis的Launcher 播放窗口,app需要做的较为简单

    mMediaPlayer = new MediaPlayer();
    mMediaPlayer.reset();
    mMediaPlayer.setDataSource(VIDEO_PATH + mFileName.get(mCurrentItem));// 针对与本地视频文件播放
    mMediaPlayer.prepare(); 
    mMediaPlayer.start();

    2、实现

    源码中有一个stream的参考,framework/av/cmds/stagefright/stream.cpp,但不可用,看了以下代码,没有mMediaPlayer.prepare的调用,且原代码中并非对框架中MediaPlayer的调用,而是自己申请service。

    因此新建类MyClient

    struct MyClient : RefBase {
        MyClient()
            : mEOS(false) {
            mp = new MediaPlayer();
            mp->setListener(new MyListener(this));
        }
    
        class MyListener: public MediaPlayerListener {
        public:
            MyListener(sp<MyClient> mc) {
            mc4listener = mc;
            }
    
            ~MyListener() {
            }
    
    
                virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) {
                    Mutex::Autolock autoLock(mc4listener->mLock);
                
            
            fprintf(stderr, "leon msg=%d
    ", msg);
                    if (msg == MEDIA_ERROR || msg == MEDIA_PLAYBACK_COMPLETE) {
                        mc4listener->mEOS = true;
                        mc4listener->mCondition.signal();
                    }
                }
            sp<MyClient> mc4listener;
        };
    
        void waitForEOS() {
            Mutex::Autolock autoLock(mLock);
            while (!mEOS) {
                mCondition.wait(mLock);
            }
        }
    
        sp<MediaPlayer> mp;
    protected:
        virtual ~MyClient() {
        }
    
    private:
        Mutex mLock;
        Condition mCondition;
    
        bool mEOS;
    
        DISALLOW_EVIL_CONSTRUCTORS(MyClient);
    };

    在构造函数中new 一个MediaPlayer类,并设置Listener,此Listener是Service想MediaPlayer的通知。

    另外新建streamSource类,在本例中,是通过打开一个Ts文件,读取数据并通知service进行播放,他继承了BnStreamSource类,并实现了三个重要的虚函数

    struct MyStreamSource : public BnStreamSource {
        // Object assumes ownership of fd.
        MyStreamSource(int fd);
    
        virtual void setListener(const sp<IStreamListener> &listener);
        virtual void setBuffers(const Vector<sp<IMemory> > &buffers);
    
        virtual void onBufferAvailable(size_t index);
    
    protected:
        virtual ~MyStreamSource();
    
    private:
        int mFd;
        off64_t mFileSize;
        uint64_t mNumPacketsSent;
    
        sp<IStreamListener> mListener;
        Vector<sp<IMemory> > mBuffers;
    
        DISALLOW_EVIL_CONSTRUCTORS(MyStreamSource);
    };

     setListener:设置mListener,通过此listener可调用service的一些函数实现。例如下面的两个函数

    void MyStreamSource::setListener(const sp<IStreamListener> &listener) {
        mListener = listener;
    }

    setBuffers:将server中申请的IMemory容器传递给StreamSource类,用于向其中写入ts数据。

    void MyStreamSource::setBuffers(const Vector<sp<IMemory> > &buffers) {
        mBuffers = buffers;
    }

    onBufferAvailable(size_t index):向可用的内存块中写入数据,完成后通过IStreamListener通知server

    void MyStreamSource::onBufferAvailable(size_t index) {
        //CHECK_LT(index, mBuffers.size());
        if (index<0 || index >=8 )
        {
            fprintf(stderr, "size=%d,	index=%u
    ", mBuffers.size(), index);
            return;
        }
        sp<IMemory> mem = mBuffers.itemAt(index);
    
        ssize_t n = read(mFd, mem->pointer(), mem->size());
        if (n <= 0) {
            mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
        } else {
            mListener->queueBuffer(index, n);
    
            mNumPacketsSent += n / 188;
        }
    }

    3、CameraHD应用中的考虑

    在Camera Service中将MyClient中的实现移植到startPreview中,获取到H264数据后,打包成TS流,通过MyStreamSource将数据写入MediaPlayerService的buffer中。

    http://pan.baidu.com/share/link?shareid=3224742726&uk=2852507874

    这是将H264数据打包为TS流的工程,备份

  • 相关阅读:
    Hadoop.2.x_集群初建
    Hadoop.2.x_网站PV示例
    Hadoop_简单操作ZooKeeper
    Hadoop.2.x_时间服务器搭建(CentOs6.6)
    Linux_Scp命令
    Java_Eclipse_Maven环境搭建
    Java_Eclipse_Maven插件部署
    HDU 1394 线段树or 树状数组~
    hdu
    HDU 4070 + 赤裸裸的贪心~~
  • 原文地址:https://www.cnblogs.com/leino11121/p/3160248.html
Copyright © 2020-2023  润新知