Android mediaplayer analysis-mediaplayerservice. cpp

Source: Internet
Author: User

Frameworks/base/libmediaplayerservice/mediaplayerservice. cpp

Because MX51 is the working platform, MX51 10.3 code is analyzed. This article mainly analyzes the code of the video play part and ignores the recorder and audio parts.

Mediaplayer service is a system service that allows Android video playback, recording and recording, metadata retrieval, and other client applications to interact with mediaplayer service. mediaplayer service enables video playback, video recording, and metadata retrieval.


 251 MediaPlayerService::MediaPlayerService() 252 { 253     LOGV("MediaPlayerService created"); 254     mNextConnId = 1; 255 }

Mediaplayerservice Constructor

Mnextconnid records the available connect IDs of the client. Each time a client is created, mnextconnid increments by 1. The used connect IDs cannot be reused.

sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pid){    sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);    LOGV("Create new media retriever from pid %d", pid);    return retriever;}

Create a metadata retriever client. We can guess from the class name that this function is used to obtain the metadata of the media file. View the definition file libmediaplayerservice/metadataretrieverclient. cpp of metadataretrieverclient. You can see that this class provides the following methods:

  • Getframeattime obtains the frame content of the video file at the specified time. It can be used to obtain the thumbnail of the media file.
  • Extractalbumart gets the albumart of the media file. albumart is the preview cover of the media file. Generally, if this is not extracted, use getframeattime to get the first frame instead.
  • Extractmetadata: Get the metadata of the media file: album, artist, author, date, genre, video_format, video_height, etc.
 286 sp<IMediaPlayer> MediaPlayerService::create( 287         pid_t pid, const sp<IMediaPlayerClient>& client, const char* url, 288         const KeyedVector<String8, String8> *headers, int audioSessionId) 289 { 290     int32_t connId = android_atomic_inc(&mNextConnId); 291     sp<Client> c = new Client(this, pid, connId, client, audioSessionId); 292     LOGV("Create new client(%d) from pid %d, url=%s, connId=%d, audioSessionId=%d", 293             connId, pid, url, connId, audioSessionId); 294     if (NO_ERROR != c->setDataSource(url, headers)) 295     { 296         c.clear(); 297         return c; 298     } 299     wp<Client> w = c; 300     Mutex::Autolock lock(mLock); 301     mClients.add(w); 302     return c; 303 }

Create an object for the mediaplayer Client

@ PID: ID of the process where the client is located

@ Client: mediaplayer Client

@ URL: Media File URL

@ Headers: Unknown

@ Audiosessionid:

301 mclients is an array of client objects. Each newly created client is added to this array.

 305 sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, 306         int fd, int64_t offset, int64_t length, int audioSessionId) 307 { 308     int32_t connId = android_atomic_inc(&mNextConnId); 309     sp<Client> c = new Client(this, pid, connId, client, audioSessionId); 310     LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld, audioSessionId=%d", 311             connId, pid, fd, offset, length, audioSessionId); 312     if (NO_ERROR != c->setDataSource(fd, offset, length)) { 313         c.clear(); 314     } else { 315         wp<Client> w = c; 316         Mutex::Autolock lock(mLock); 317         mClients.add(w); 318     } 319     ::close(fd); 320     return c; 321 }

Another reload form of create is

 305 sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, 306         int fd, int64_t offset, int64_t length, int audioSessionId) 307 { 308     int32_t connId = android_atomic_inc(&mNextConnId); 309     sp<Client> c = new Client(this, pid, connId, client, audioSessionId); 310     LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld, audioSessionId=%d", 311             connId, pid, fd, offset, length, audioSessionId); 312     if (NO_ERROR != c->setDataSource(fd, offset, length)) { 313         c.clear(); 314     } else { 315         wp<Client> w = c; 316         Mutex::Autolock lock(mLock); 317         mClients.add(w); 318     } 319     ::close(fd); 320     return c; 321 }

@ FD: open media file descriptor

@ Offset: it is confusing to introduce the offset and length parameters to Android. Isn't the operation on the media file started from the start position of FD? It may be true that the media content is in another file container, so that the offset and length are used to define the location of the media content.

@ Length:

MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t pid,        int32_t connId, const sp<IMediaPlayerClient>& client, int audioSessionId){    LOGV("Client(%d) constructor", connId);    mPid = pid;    mConnId = connId;    mService = service;    mClient = client;    mLoop = false;    mStatus = NO_INIT;    mAudioSessionId = audioSessionId;#if CALLBACK_ANTAGONIZER    LOGD("create Antagonizer");    mAntagonizer = new Antagonizer(notify, this);#endif}

For a video to be played, two clients are created, one in the user space mediaplayer instance (this client is responsible for communicating with mediaplayerservice), and the other in the mediaplayer service space mediaplayerservice: Client :: client instance, used to maintain the status of the client on the mediaplayer Service side.

The server client is created in mediaplayerservice: Create. The newly created client object is added to the mclients array.

player_type getPlayerType(int fd, int64_t offset, int64_t length)........

This function first reads some bytes from the file header, and then returns the corresponding player type based on the file type identified by the header.

player_type getPlayerType(const char* url)............

Determine the player type based on the URL

static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,        notify_callback_f notifyFunc){    sp<MediaPlayerBase> p;    switch (playerType & 0xff) {#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;#ifdef PREBUILT_FSL_IMX_OMX        case OMX_PLAYER:            LOGV(" Create OMXPlayer.\n");            p = new OMXPlayer(playerType >> 8);            break;#endif        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;}

Create a corresponding Player Based on the specified player type and return it. You can see that pvplayer, midifile, stagefrightplayer, and omxplayer are currently supported.

Omxplayer is a dedicated Freescale player.

status_t MediaPlayerService::Client::setDataSource(        const char *url, const KeyedVector<String8, String8> *headers){    LOGV("setDataSource(%s)", url);    if (url == NULL)        return UNKNOWN_ERROR;    if (strncmp(url, "content://", 10) == 0) {        // get a filedescriptor for the content Uri and        // pass it to the setDataSource(fd) method        String16 url16(url);        int fd = android::openContentProviderFile(url16);        if (fd < 0)        {            LOGE("Couldn't open fd for %s", url);            return UNKNOWN_ERROR;        }        setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus        close(fd);        return mStatus;    } else {        player_type playerType = getPlayerType(url);        LOGV("player type = %d", playerType);        // create the right type of player        sp<MediaPlayerBase> p = createPlayer(playerType);        if (p == NULL) return NO_INIT;        if (!p->hardwareOutput()) {            mAudioOutput = new AudioOutput(mAudioSessionId);            static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);        }        // now set data source        LOGV(" setDataSource");        mStatus = p->setDataSource(url, headers);        if (mStatus == NO_ERROR) {            mPlayer = p;        } else {            LOGE("  error: %d", mStatus);        }        return mStatus;    }}

As the name suggests, setdatasource sets data-related content to the player. If stagefright player is used, the setdatasource member function of awesome player is called. Awesomeplayer: setdatasource has two overload functions: one Stores @ headers directly, and the other calls the corresponding extractor to extract the required information such as mflags and mbitrate from the file.

status_t MediaPlayerService::Client::setVideoSurface(const sp<ISurface>& surface){    LOGV("[%d] setVideoSurface(%p)", mConnId, surface.get());    sp<MediaPlayerBase> p = getPlayer();    if (p == 0) return UNKNOWN_ERROR;    return p->setVideoSurface(surface);}   

Set the surface object for the player

sp<IMemory> MediaPlayerService::Client::captureCurrentFrame(){    LOGV("captureCurrentFrame");    sp<MediaPlayerBase> p = getPlayer();    if (p == NULL) {        LOGE("media player is not initialized");        return NULL;    }    Mutex::Autolock lock(mLock);    mVideoFrame.clear();    mVideoFrameDealer.clear();    VideoFrame *frame = NULL;    p->captureCurrentFrame(&frame);    if (frame == NULL) {        LOGE("failed to capture a video frame");        return NULL;    }    size_t size = sizeof(VideoFrame) + frame->mSize;    mVideoFrameDealer = new MemoryDealer(size);    if (mVideoFrameDealer == NULL) {        LOGE("failed to create MemoryDealer");        return NULL;    }    mVideoFrame = mVideoFrameDealer->allocate(size);    if (mVideoFrame == NULL) {        LOGE("not enough memory for VideoFrame size=%u", size);        mVideoFrameDealer.clear();        return NULL;    }    VideoFrame *frameCopy = static_cast<VideoFrame *>(mVideoFrame->pointer());    frameCopy->mWidth = frame->mWidth;    frameCopy->mHeight = frame->mHeight;    frameCopy->mDisplayWidth = frame->mDisplayWidth;    frameCopy->mDisplayHeight = frame->mDisplayHeight;    frameCopy->mSize = frame->mSize;    frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame);    memcpy(frameCopy->mData, frame->mData, frame->mSize);    return mVideoFrame;}

Get the data of the current frame and return a piece of memory space. The first part of the memory is the basic information of the frame: width, height, displaywidth, displayheight, size, followed by the frame data.

The video-related code in mediaplayerservice. cpp is analyzed.

The main task of mediaplayerservice is to create a corresponding client proxy in the service when the client application requests playback. The service processes the requests sent by the client application based on the opened file or Uri type, select the Player Plug-in.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.