PreviewPlayer.cpp revision 727f9e1e8e1306af761765e480ac5499224db646
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18// #define LOG_NDEBUG 0
19#define LOG_TAG "PreviewPlayer"
20#include <utils/Log.h>
21
22#include <binder/IPCThreadState.h>
23#include <binder/IServiceManager.h>
24#include <media/IMediaPlayerService.h>
25#include <media/stagefright/DataSource.h>
26#include <media/stagefright/MediaBuffer.h>
27#include <media/stagefright/MediaDefs.h>
28#include <media/stagefright/MediaExtractor.h>
29#include <media/stagefright/MediaSource.h>
30#include <media/stagefright/MetaData.h>
31#include <media/stagefright/OMXCodec.h>
32#include <media/stagefright/foundation/ADebug.h>
33#include <surfaceflinger/Surface.h>
34#include <gui/ISurfaceTexture.h>
35#include <gui/SurfaceTextureClient.h>
36#include <surfaceflinger/ISurfaceComposer.h>
37
38#include "VideoEditorPreviewController.h"
39#include "DummyAudioSource.h"
40#include "DummyVideoSource.h"
41#include "VideoEditorSRC.h"
42#include "PreviewPlayer.h"
43
44namespace android {
45
46
47void addBatteryData(uint32_t params) {
48    sp<IBinder> binder =
49        defaultServiceManager()->getService(String16("media.player"));
50    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
51    CHECK(service.get() != NULL);
52
53    service->addBatteryData(params);
54}
55
56struct PreviewPlayerEvent : public TimedEventQueue::Event {
57    PreviewPlayerEvent(
58            PreviewPlayer *player,
59            void (PreviewPlayer::*method)())
60        : mPlayer(player),
61          mMethod(method) {
62    }
63
64protected:
65    virtual ~PreviewPlayerEvent() {}
66
67    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
68        (mPlayer->*mMethod)();
69    }
70
71private:
72    PreviewPlayer *mPlayer;
73    void (PreviewPlayer::*mMethod)();
74
75    PreviewPlayerEvent(const PreviewPlayerEvent &);
76    PreviewPlayerEvent &operator=(const PreviewPlayerEvent &);
77};
78
79PreviewPlayer::PreviewPlayer(NativeWindowRenderer* renderer)
80    : mQueueStarted(false),
81      mTimeSource(NULL),
82      mVideoRendererIsPreview(false),
83      mAudioPlayer(NULL),
84      mDisplayWidth(0),
85      mDisplayHeight(0),
86      mFlags(0),
87      mExtractorFlags(0),
88      mVideoBuffer(NULL),
89      mLastVideoTimeUs(-1),
90      mNativeWindowRenderer(renderer),
91      mCurrFramingEffectIndex(0),
92      mFrameRGBBuffer(NULL),
93      mFrameYUVBuffer(NULL) {
94
95    CHECK_EQ(mClient.connect(), (status_t)OK);
96    DataSource::RegisterDefaultSniffers();
97
98
99    mVideoRenderer = NULL;
100    mEffectsSettings = NULL;
101    mAudioPlayer = NULL;
102    mAudioMixStoryBoardTS = 0;
103    mCurrentMediaBeginCutTime = 0;
104    mCurrentMediaVolumeValue = 0;
105    mNumberEffects = 0;
106    mDecodedVideoTs = 0;
107    mDecVideoTsStoryBoard = 0;
108    mCurrentVideoEffect = VIDEO_EFFECT_NONE;
109    mProgressCbInterval = 0;
110    mNumberDecVideoFrames = 0;
111    mOverlayUpdateEventPosted = false;
112    mIsChangeSourceRequired = true;
113
114    mVideoEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoEvent);
115    mVideoEventPending = false;
116    mVideoLagEvent = new PreviewPlayerEvent(this, &PreviewPlayer::onVideoLagUpdate);
117    mVideoEventPending = false;
118    mCheckAudioStatusEvent = new PreviewPlayerEvent(
119            this, &PreviewPlayer::onCheckAudioStatus);
120    mAudioStatusEventPending = false;
121    mStreamDoneEvent = new PreviewPlayerEvent(
122            this, &PreviewPlayer::onStreamDone);
123    mStreamDoneEventPending = false;
124    mProgressCbEvent = new PreviewPlayerEvent(this,
125         &PreviewPlayer::onProgressCbEvent);
126
127    mOverlayUpdateEvent = new PreviewPlayerEvent(this,
128        &PreviewPlayer::onUpdateOverlayEvent);
129    mProgressCbEventPending = false;
130
131    mOverlayUpdateEventPending = false;
132    mRenderingMode = (M4xVSS_MediaRendering)MEDIA_RENDERING_INVALID;
133    mIsFiftiesEffectStarted = false;
134    reset();
135}
136
137PreviewPlayer::~PreviewPlayer() {
138
139    if (mQueueStarted) {
140        mQueue.stop();
141    }
142
143    reset();
144
145    if (mVideoRenderer) {
146        mNativeWindowRenderer->destroyRenderInput(mVideoRenderer);
147    }
148
149    Mutex::Autolock lock(mLock);
150    clear_l();
151    mClient.disconnect();
152}
153
154void PreviewPlayer::cancelPlayerEvents_l(bool updateProgressCb) {
155    mQueue.cancelEvent(mVideoEvent->eventID());
156    mVideoEventPending = false;
157    mQueue.cancelEvent(mStreamDoneEvent->eventID());
158    mStreamDoneEventPending = false;
159    mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
160    mAudioStatusEventPending = false;
161    mQueue.cancelEvent(mVideoLagEvent->eventID());
162    mVideoLagEventPending = false;
163    if (updateProgressCb) {
164        mQueue.cancelEvent(mProgressCbEvent->eventID());
165        mProgressCbEventPending = false;
166    }
167}
168
169status_t PreviewPlayer::setDataSource(const char *path) {
170    Mutex::Autolock autoLock(mLock);
171    return setDataSource_l(path);
172}
173
174status_t PreviewPlayer::setDataSource_l(const char *path) {
175    reset_l();
176
177    mUri = path;
178
179    // The actual work will be done during preparation in the call to
180    // ::finishSetDataSource_l to avoid blocking the calling thread in
181    // setDataSource for any significant time.
182    return OK;
183}
184
185status_t PreviewPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
186    bool haveAudio = false;
187    bool haveVideo = false;
188    for (size_t i = 0; i < extractor->countTracks(); ++i) {
189        sp<MetaData> meta = extractor->getTrackMetaData(i);
190
191        const char *mime;
192        CHECK(meta->findCString(kKeyMIMEType, &mime));
193
194        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
195            setVideoSource(extractor->getTrack(i));
196            haveVideo = true;
197        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
198            setAudioSource(extractor->getTrack(i));
199            haveAudio = true;
200
201            if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
202                // Only do this for vorbis audio, none of the other audio
203                // formats even support this ringtone specific hack and
204                // retrieving the metadata on some extractors may turn out
205                // to be very expensive.
206                sp<MetaData> fileMeta = extractor->getMetaData();
207                int32_t loop;
208                if (fileMeta != NULL
209                        && fileMeta->findInt32(kKeyAutoLoop, &loop)
210                         && loop != 0) {
211                    mFlags |= AUTO_LOOPING;
212                }
213            }
214        }
215
216        if (haveAudio && haveVideo) {
217            break;
218        }
219    }
220
221    /* Add the support for Dummy audio*/
222    if( !haveAudio ){
223        mAudioTrack = DummyAudioSource::Create(32000, 2, 20000,
224                                              ((mPlayEndTimeMsec)*1000LL));
225        if(mAudioTrack != NULL) {
226            haveAudio = true;
227        }
228    }
229
230    if (!haveAudio && !haveVideo) {
231        return UNKNOWN_ERROR;
232    }
233
234    mExtractorFlags = extractor->flags();
235    return OK;
236}
237
238status_t PreviewPlayer::setDataSource_l_jpg() {
239    ALOGV("setDataSource_l_jpg");
240
241    M4OSA_ERR err = M4NO_ERROR;
242
243    mAudioSource = DummyAudioSource::Create(32000, 2, 20000,
244                                          ((mPlayEndTimeMsec)*1000LL));
245    if(mAudioSource != NULL) {
246        setAudioSource(mAudioSource);
247    }
248    status_t error = mAudioSource->start();
249    if (error != OK) {
250        ALOGE("Error starting dummy audio source");
251        mAudioSource.clear();
252        return err;
253    }
254
255    mDurationUs = (mPlayEndTimeMsec - mPlayBeginTimeMsec)*1000LL;
256
257    mVideoSource = DummyVideoSource::Create(mVideoWidth, mVideoHeight,
258                                            mDurationUs, mUri);
259
260    updateSizeToRender(mVideoSource->getFormat());
261    setVideoSource(mVideoSource);
262    status_t err1 = mVideoSource->start();
263    if (err1 != OK) {
264        mVideoSource.clear();
265        return err;
266    }
267
268    mIsVideoSourceJpg = true;
269    return OK;
270}
271
272void PreviewPlayer::reset_l() {
273
274    if (mFlags & PREPARING) {
275        mFlags |= PREPARE_CANCELLED;
276    }
277
278    while (mFlags & PREPARING) {
279        mPreparedCondition.wait(mLock);
280    }
281
282    cancelPlayerEvents_l();
283    mAudioTrack.clear();
284    mVideoTrack.clear();
285
286    // Shutdown audio first, so that the respone to the reset request
287    // appears to happen instantaneously as far as the user is concerned
288    // If we did this later, audio would continue playing while we
289    // shutdown the video-related resources and the player appear to
290    // not be as responsive to a reset request.
291    if (mAudioPlayer == NULL && mAudioSource != NULL) {
292        // If we had an audio player, it would have effectively
293        // taken possession of the audio source and stopped it when
294        // _it_ is stopped. Otherwise this is still our responsibility.
295        mAudioSource->stop();
296    }
297    mAudioSource.clear();
298
299    mTimeSource = NULL;
300
301    //Single audio player instance used
302    //So donot delete it here
303    //It is deleted from PreviewController class
304    //delete mAudioPlayer;
305    mAudioPlayer = NULL;
306
307    if (mVideoBuffer) {
308        mVideoBuffer->release();
309        mVideoBuffer = NULL;
310    }
311
312    if (mVideoSource != NULL) {
313        mVideoSource->stop();
314
315        // The following hack is necessary to ensure that the OMX
316        // component is completely released by the time we may try
317        // to instantiate it again.
318        wp<MediaSource> tmp = mVideoSource;
319        mVideoSource.clear();
320        while (tmp.promote() != NULL) {
321            usleep(1000);
322        }
323        IPCThreadState::self()->flushCommands();
324    }
325
326    mDurationUs = -1;
327    mFlags = 0;
328    mExtractorFlags = 0;
329    mVideoWidth = mVideoHeight = -1;
330    mTimeSourceDeltaUs = 0;
331    mVideoTimeUs = 0;
332
333    mSeeking = NO_SEEK;
334    mSeekNotificationSent = false;
335    mSeekTimeUs = 0;
336
337    mUri.setTo("");
338
339    mCurrentVideoEffect = VIDEO_EFFECT_NONE;
340    mIsVideoSourceJpg = false;
341    mFrameRGBBuffer = NULL;
342    if(mFrameYUVBuffer != NULL) {
343        free(mFrameYUVBuffer);
344        mFrameYUVBuffer = NULL;
345    }
346}
347
348status_t PreviewPlayer::play() {
349    ALOGV("play");
350    Mutex::Autolock autoLock(mLock);
351
352    mFlags &= ~CACHE_UNDERRUN;
353    mFlags &= ~INFORMED_AV_EOS;
354    return play_l();
355}
356
357status_t PreviewPlayer::startAudioPlayer_l() {
358    ALOGV("startAudioPlayer_l");
359    CHECK(!(mFlags & AUDIO_RUNNING));
360
361    if (mAudioSource == NULL || mAudioPlayer == NULL) {
362        return OK;
363    }
364
365    if (!(mFlags & AUDIOPLAYER_STARTED)) {
366        mFlags |= AUDIOPLAYER_STARTED;
367
368        // We've already started the MediaSource in order to enable
369        // the prefetcher to read its data.
370        status_t err = mAudioPlayer->start(
371                true /* sourceAlreadyStarted */);
372
373        if (err != OK) {
374            notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
375            return err;
376        }
377    } else {
378        mAudioPlayer->resume();
379    }
380
381    mFlags |= AUDIO_RUNNING;
382
383    mWatchForAudioEOS = true;
384
385    return OK;
386}
387
388status_t PreviewPlayer::setAudioPlayer(VideoEditorAudioPlayer *audioPlayer) {
389    ALOGV("setAudioPlayer");
390    Mutex::Autolock autoLock(mLock);
391    CHECK(!(mFlags & PLAYING));
392    mAudioPlayer = audioPlayer;
393
394    ALOGV("SetAudioPlayer");
395    mIsChangeSourceRequired = true;
396
397    // check if the new and old source are dummy
398    sp<MediaSource> anAudioSource = mAudioPlayer->getSource();
399    if (anAudioSource == NULL) {
400        // Audio player does not have any source set.
401        ALOGV("setAudioPlayer: Audio player does not have any source set");
402        return OK;
403    }
404
405    // If new video source is not dummy, then always change source
406    // Else audio player continues using old audio source and there are
407    // frame drops to maintain AV sync
408    sp<MetaData> meta;
409    if (mVideoSource != NULL) {
410        meta = mVideoSource->getFormat();
411        const char *pVidSrcType;
412        if (meta->findCString(kKeyDecoderComponent, &pVidSrcType)) {
413            if (strcmp(pVidSrcType, "DummyVideoSource") != 0) {
414                ALOGV(" Video clip with silent audio; need to change source");
415                return OK;
416            }
417        }
418    }
419
420    const char *pSrcType1;
421    const char *pSrcType2;
422    meta = anAudioSource->getFormat();
423
424    if (meta->findCString(kKeyDecoderComponent, &pSrcType1)) {
425        if (strcmp(pSrcType1, "DummyAudioSource") == 0) {
426            meta = mAudioSource->getFormat();
427            if (meta->findCString(kKeyDecoderComponent, &pSrcType2)) {
428                if (strcmp(pSrcType2, "DummyAudioSource") == 0) {
429                    mIsChangeSourceRequired = false;
430                    // Just set the new play duration for the existing source
431                    MediaSource *pMediaSrc = anAudioSource.get();
432                    DummyAudioSource *pDummyAudioSource = (DummyAudioSource*)pMediaSrc;
433                    //Increment the duration of audio source
434                    pDummyAudioSource->setDuration(
435                        (int64_t)((mPlayEndTimeMsec)*1000LL));
436
437                    // Stop the new audio source
438                    // since we continue using old source
439                    ALOGV("setAudioPlayer: stop new audio source");
440                    mAudioSource->stop();
441                }
442            }
443        }
444    }
445
446    return OK;
447}
448
449void PreviewPlayer::onStreamDone() {
450    ALOGV("onStreamDone");
451    // Posted whenever any stream finishes playing.
452
453    Mutex::Autolock autoLock(mLock);
454    if (!mStreamDoneEventPending) {
455        return;
456    }
457    mStreamDoneEventPending = false;
458
459    if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
460        ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
461
462        notifyListener_l(
463                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
464
465        pause_l(true /* at eos */);
466
467        mFlags |= AT_EOS;
468        return;
469    }
470
471    const bool allDone =
472        (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
473            && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
474
475    if (!allDone) {
476        return;
477    }
478
479    if (mFlags & (LOOPING | AUTO_LOOPING)) {
480        seekTo_l(0);
481
482        if (mVideoSource != NULL) {
483            postVideoEvent_l();
484        }
485    } else {
486        ALOGV("MEDIA_PLAYBACK_COMPLETE");
487        //pause before sending event
488        pause_l(true /* at eos */);
489
490        //This lock is used to syncronize onStreamDone() in PreviewPlayer and
491        //stopPreview() in PreviewController
492        Mutex::Autolock autoLock(mLockControl);
493        /* Make sure PreviewPlayer only notifies MEDIA_PLAYBACK_COMPLETE once for each clip!
494         * It happens twice in following scenario.
495         * To make the clips in preview storyboard are played and switched smoothly,
496         * PreviewController uses two PreviewPlayer instances and one AudioPlayer.
497         * The two PreviewPlayer use the same AudioPlayer to play the audio,
498         * and change the audio source of the AudioPlayer.
499         * If the audio source of current playing clip and next clip are dummy
500         * audio source(image or video without audio), it will not change the audio source
501         * to avoid the "audio glitch", and keep using the current audio source.
502         * When the video of current clip reached the EOS, PreviewPlayer will set EOS flag
503         * for video and audio, and it will notify MEDIA_PLAYBACK_COMPLETE.
504         * But the audio(dummy audio source) is still playing(for next clip),
505         * and when it reached the EOS, and video reached EOS,
506         * PreviewPlayer will notify MEDIA_PLAYBACK_COMPLETE again. */
507        if (!(mFlags & INFORMED_AV_EOS)) {
508            notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
509            mFlags |= INFORMED_AV_EOS;
510        }
511        mFlags |= AT_EOS;
512        ALOGV("onStreamDone end");
513        return;
514    }
515}
516
517
518status_t PreviewPlayer::play_l() {
519    ALOGV("play_l");
520
521    mFlags &= ~SEEK_PREVIEW;
522
523    if (mFlags & PLAYING) {
524        return OK;
525    }
526    mStartNextPlayer = false;
527
528    if (!(mFlags & PREPARED)) {
529        status_t err = prepare_l();
530
531        if (err != OK) {
532            return err;
533        }
534    }
535
536    mFlags |= PLAYING;
537    mFlags |= FIRST_FRAME;
538
539    bool deferredAudioSeek = false;
540
541    if (mAudioSource != NULL) {
542        if (mAudioPlayer == NULL) {
543            if (mAudioSink != NULL) {
544
545                mAudioPlayer = new VideoEditorAudioPlayer(mAudioSink, this);
546                mAudioPlayer->setSource(mAudioSource);
547
548                mAudioPlayer->setAudioMixSettings(
549                 mPreviewPlayerAudioMixSettings);
550
551                mAudioPlayer->setAudioMixPCMFileHandle(
552                 mAudioMixPCMFileHandle);
553
554                mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
555                 mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
556                 mCurrentMediaVolumeValue);
557
558                 mFlags |= AUDIOPLAYER_STARTED;
559                // We've already started the MediaSource in order to enable
560                // the prefetcher to read its data.
561                status_t err = mAudioPlayer->start(
562                        true /* sourceAlreadyStarted */);
563
564                if (err != OK) {
565                    //delete mAudioPlayer;
566                    mAudioPlayer = NULL;
567
568                    mFlags &= ~(PLAYING | FIRST_FRAME);
569                    return err;
570                }
571
572                mTimeSource = mAudioPlayer;
573                mFlags |= AUDIO_RUNNING;
574                deferredAudioSeek = true;
575                mWatchForAudioSeekComplete = false;
576                mWatchForAudioEOS = true;
577            }
578        } else {
579            bool isAudioPlayerStarted = mAudioPlayer->isStarted();
580
581            if (mIsChangeSourceRequired == true) {
582                ALOGV("play_l: Change audio source required");
583
584                if (isAudioPlayerStarted == true) {
585                    mAudioPlayer->pause();
586                }
587
588                mAudioPlayer->setSource(mAudioSource);
589                mAudioPlayer->setObserver(this);
590
591                mAudioPlayer->setAudioMixSettings(
592                 mPreviewPlayerAudioMixSettings);
593
594                mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
595                    mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
596                    mCurrentMediaVolumeValue);
597
598                if (isAudioPlayerStarted == true) {
599                    mAudioPlayer->resume();
600                } else {
601                    status_t err = OK;
602                    err = mAudioPlayer->start(true);
603                    if (err != OK) {
604                        mAudioPlayer = NULL;
605                        mAudioPlayer = NULL;
606
607                        mFlags &= ~(PLAYING | FIRST_FRAME);
608                        return err;
609                    }
610                }
611            } else {
612                ALOGV("play_l: No Source change required");
613                mAudioPlayer->setAudioMixStoryBoardSkimTimeStamp(
614                    mAudioMixStoryBoardTS, mCurrentMediaBeginCutTime,
615                    mCurrentMediaVolumeValue);
616
617                mAudioPlayer->resume();
618            }
619
620            mFlags |= AUDIOPLAYER_STARTED;
621            mFlags |= AUDIO_RUNNING;
622            mTimeSource = mAudioPlayer;
623            deferredAudioSeek = true;
624            mWatchForAudioSeekComplete = false;
625            mWatchForAudioEOS = true;
626        }
627    }
628
629    if (mTimeSource == NULL && mAudioPlayer == NULL) {
630        mTimeSource = &mSystemTimeSource;
631    }
632
633    // Set the seek option for Image source files and read.
634    // This resets the timestamping for image play
635    if (mIsVideoSourceJpg) {
636        MediaSource::ReadOptions options;
637        MediaBuffer *aLocalBuffer;
638        options.setSeekTo(mSeekTimeUs);
639        mVideoSource->read(&aLocalBuffer, &options);
640        aLocalBuffer->release();
641    }
642
643    if (mVideoSource != NULL) {
644        // Kick off video playback
645        postVideoEvent_l();
646    }
647
648    if (deferredAudioSeek) {
649        // If there was a seek request while we were paused
650        // and we're just starting up again, honor the request now.
651        seekAudioIfNecessary_l();
652    }
653
654    if (mFlags & AT_EOS) {
655        // Legacy behaviour, if a stream finishes playing and then
656        // is started again, we play from the start...
657        seekTo_l(0);
658    }
659
660    return OK;
661}
662
663
664status_t PreviewPlayer::initRenderer_l() {
665    if (mSurface != NULL) {
666        if(mVideoRenderer == NULL) {
667            mVideoRenderer = mNativeWindowRenderer->createRenderInput();
668            if (mVideoSource != NULL) {
669                updateSizeToRender(mVideoSource->getFormat());
670            }
671        }
672    }
673    return OK;
674}
675
676
677status_t PreviewPlayer::seekTo(int64_t timeUs) {
678    Mutex::Autolock autoLock(mLock);
679    if ((mExtractorFlags & MediaExtractor::CAN_SEEK) || (mIsVideoSourceJpg)) {
680        return seekTo_l(timeUs);
681    }
682
683    return OK;
684}
685
686
687status_t PreviewPlayer::getVideoDimensions(
688        int32_t *width, int32_t *height) const {
689    Mutex::Autolock autoLock(mLock);
690
691    if (mVideoWidth < 0 || mVideoHeight < 0) {
692        return UNKNOWN_ERROR;
693    }
694
695    *width = mVideoWidth;
696    *height = mVideoHeight;
697
698    return OK;
699}
700
701
702status_t PreviewPlayer::initAudioDecoder_l() {
703    sp<MetaData> meta = mAudioTrack->getFormat();
704    const char *mime;
705    CHECK(meta->findCString(kKeyMIMEType, &mime));
706
707    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
708        mAudioSource = mAudioTrack;
709    } else {
710        sp<MediaSource> aRawSource;
711        aRawSource = OMXCodec::Create(
712                mClient.interface(), mAudioTrack->getFormat(),
713                false, // createEncoder
714                mAudioTrack);
715
716        if(aRawSource != NULL) {
717            mAudioSource = new VideoEditorSRC(aRawSource);
718        }
719    }
720
721    if (mAudioSource != NULL) {
722        int64_t durationUs;
723        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
724            setDuration_l(durationUs);
725        }
726        status_t err = mAudioSource->start();
727
728        if (err != OK) {
729            mAudioSource.clear();
730            return err;
731        }
732    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
733        // For legacy reasons we're simply going to ignore the absence
734        // of an audio decoder for QCELP instead of aborting playback
735        // altogether.
736        return OK;
737    }
738
739    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
740}
741
742status_t PreviewPlayer::initVideoDecoder_l(uint32_t flags) {
743    initRenderer_l();
744
745    if (mVideoRenderer == NULL) {
746        ALOGE("Cannot create renderer");
747        return UNKNOWN_ERROR;
748    }
749
750    mVideoSource = OMXCodec::Create(
751            mClient.interface(), mVideoTrack->getFormat(),
752            false,
753            mVideoTrack,
754            NULL, flags, mVideoRenderer->getTargetWindow());
755
756    if (mVideoSource != NULL) {
757        int64_t durationUs;
758        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
759            setDuration_l(durationUs);
760        }
761
762        updateSizeToRender(mVideoTrack->getFormat());
763
764        status_t err = mVideoSource->start();
765
766        if (err != OK) {
767            mVideoSource.clear();
768            return err;
769        }
770    }
771
772    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
773}
774
775
776void PreviewPlayer::onVideoEvent() {
777    uint32_t i=0;
778    M4OSA_ERR err1 = M4NO_ERROR;
779    int64_t imageFrameTimeUs = 0;
780
781    Mutex::Autolock autoLock(mLock);
782    if (!mVideoEventPending) {
783        // The event has been cancelled in reset_l() but had already
784        // been scheduled for execution at that time.
785        return;
786    }
787    mVideoEventPending = false;
788
789    if (mFlags & SEEK_PREVIEW) {
790        mFlags &= ~SEEK_PREVIEW;
791        return;
792    }
793
794    TimeSource *ts_st =  &mSystemTimeSource;
795    int64_t timeStartUs = ts_st->getRealTimeUs();
796
797    if (mSeeking != NO_SEEK) {
798
799        if(mAudioSource != NULL) {
800
801            // We're going to seek the video source first, followed by
802            // the audio source.
803            // In order to avoid jumps in the DataSource offset caused by
804            // the audio codec prefetching data from the old locations
805            // while the video codec is already reading data from the new
806            // locations, we'll "pause" the audio source, causing it to
807            // stop reading input data until a subsequent seek.
808
809            if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
810                mAudioPlayer->pause();
811                mFlags &= ~AUDIO_RUNNING;
812            }
813            mAudioSource->pause();
814        }
815    }
816
817    if (!mVideoBuffer) {
818        MediaSource::ReadOptions options;
819        if (mSeeking != NO_SEEK) {
820            ALOGV("LV PLAYER seeking to %lld us (%.2f secs)", mSeekTimeUs,
821                                                      mSeekTimeUs / 1E6);
822
823            options.setSeekTo(
824                    mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
825        }
826        for (;;) {
827            status_t err = mVideoSource->read(&mVideoBuffer, &options);
828            options.clearSeekTo();
829
830            if (err != OK) {
831                CHECK(!mVideoBuffer);
832
833                if (err == INFO_FORMAT_CHANGED) {
834                    ALOGV("LV PLAYER VideoSource signalled format change");
835                    notifyVideoSize_l();
836
837                    if (mVideoRenderer != NULL) {
838                        mVideoRendererIsPreview = false;
839                        err = initRenderer_l();
840                        if (err != OK) {
841                            postStreamDoneEvent_l(err);
842                        }
843
844                    }
845
846                    updateSizeToRender(mVideoSource->getFormat());
847                    continue;
848                }
849                // So video playback is complete, but we may still have
850                // a seek request pending that needs to be applied to the audio track
851                if (mSeeking != NO_SEEK) {
852                    ALOGV("video stream ended while seeking!");
853                }
854                finishSeekIfNecessary(-1);
855                ALOGV("PreviewPlayer: onVideoEvent EOS reached.");
856                mFlags |= VIDEO_AT_EOS;
857                mFlags |= AUDIO_AT_EOS;
858                mOverlayUpdateEventPosted = false;
859                postStreamDoneEvent_l(err);
860                // Set the last decoded timestamp to duration
861                mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
862                return;
863            }
864
865            if (mVideoBuffer->range_length() == 0) {
866                // Some decoders, notably the PV AVC software decoder
867                // return spurious empty buffers that we just want to ignore.
868
869                mVideoBuffer->release();
870                mVideoBuffer = NULL;
871                continue;
872            }
873
874            int64_t videoTimeUs;
875            CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
876
877            if (mSeeking != NO_SEEK) {
878                if (videoTimeUs < mSeekTimeUs) {
879                    // buffers are before seek time
880                    // ignore them
881                    mVideoBuffer->release();
882                    mVideoBuffer = NULL;
883                    continue;
884                }
885            } else {
886                if((videoTimeUs/1000) < mPlayBeginTimeMsec) {
887                    // Frames are before begin cut time
888                    // Donot render
889                    mVideoBuffer->release();
890                    mVideoBuffer = NULL;
891                    continue;
892                }
893            }
894            break;
895        }
896    }
897
898    mNumberDecVideoFrames++;
899
900    int64_t timeUs;
901    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
902    setPosition_l(timeUs);
903
904    if (!mStartNextPlayer) {
905        int64_t playbackTimeRemaining = (mPlayEndTimeMsec * 1000LL) - timeUs;
906        if (playbackTimeRemaining <= 1500000) {
907            //When less than 1.5 sec of playback left
908            // send notification to start next player
909
910            mStartNextPlayer = true;
911            notifyListener_l(0xAAAAAAAA);
912        }
913    }
914
915    SeekType wasSeeking = mSeeking;
916    finishSeekIfNecessary(timeUs);
917    if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING))) {
918        status_t err = startAudioPlayer_l();
919        if (err != OK) {
920            ALOGE("Starting the audio player failed w/ err %d", err);
921            return;
922        }
923    }
924
925    TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
926
927    if(ts == NULL) {
928        mVideoBuffer->release();
929        mVideoBuffer = NULL;
930        return;
931    }
932
933    if(!mIsVideoSourceJpg) {
934        if (mFlags & FIRST_FRAME) {
935            mFlags &= ~FIRST_FRAME;
936
937            mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
938        }
939
940        int64_t realTimeUs, mediaTimeUs;
941        if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
942            && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
943            mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
944        }
945
946        int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
947
948        int64_t latenessUs = nowUs - timeUs;
949
950        if (wasSeeking != NO_SEEK) {
951            // Let's display the first frame after seeking right away.
952            latenessUs = 0;
953        }
954        ALOGV("Audio time stamp = %lld and video time stamp = %lld",
955                                            ts->getRealTimeUs(),timeUs);
956        if (latenessUs > 40000) {
957            // We're more than 40ms late.
958
959            ALOGV("LV PLAYER we're late by %lld us (%.2f secs)",
960                                           latenessUs, latenessUs / 1E6);
961
962            mVideoBuffer->release();
963            mVideoBuffer = NULL;
964            postVideoEvent_l(0);
965            return;
966        }
967
968        if (latenessUs < -25000) {
969            // We're more than 25ms early.
970            ALOGV("We're more than 25ms early, lateness %lld", latenessUs);
971
972            postVideoEvent_l(25000);
973            return;
974        }
975    }
976
977    if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
978        mVideoRendererIsPreview = false;
979
980        status_t err = initRenderer_l();
981        if (err != OK) {
982            postStreamDoneEvent_l(err);
983        }
984    }
985
986    // If timestamp exceeds endCutTime of clip, donot render
987    if((timeUs/1000) > mPlayEndTimeMsec) {
988        mVideoBuffer->release();
989        mVideoBuffer = NULL;
990        mFlags |= VIDEO_AT_EOS;
991        mFlags |= AUDIO_AT_EOS;
992        ALOGV("PreviewPlayer: onVideoEvent timeUs > mPlayEndTime; send EOS..");
993        mOverlayUpdateEventPosted = false;
994        // Set the last decoded timestamp to duration
995        mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
996        postStreamDoneEvent_l(ERROR_END_OF_STREAM);
997        return;
998    }
999    // Capture the frame timestamp to be rendered
1000    mDecodedVideoTs = timeUs;
1001
1002    // Post processing to apply video effects
1003    for(i=0;i<mNumberEffects;i++) {
1004        // First check if effect starttime matches the clip being previewed
1005        if((mEffectsSettings[i].uiStartTime < (mDecVideoTsStoryBoard/1000)) ||
1006        (mEffectsSettings[i].uiStartTime >=
1007         ((mDecVideoTsStoryBoard/1000) + mPlayEndTimeMsec - mPlayBeginTimeMsec)))
1008        {
1009            // This effect doesn't belong to this clip, check next one
1010            continue;
1011        }
1012        // Check if effect applies to this particular frame timestamp
1013        if((mEffectsSettings[i].uiStartTime <=
1014         (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec)) &&
1015            ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
1016             (((timeUs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec))
1017              && (mEffectsSettings[i].uiDuration != 0)) {
1018            setVideoPostProcessingNode(
1019             mEffectsSettings[i].VideoEffectType, TRUE);
1020        }
1021        else {
1022            setVideoPostProcessingNode(
1023             mEffectsSettings[i].VideoEffectType, FALSE);
1024        }
1025    }
1026
1027    //Provide the overlay Update indication when there is an overlay effect
1028    if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
1029        mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
1030        if (!mOverlayUpdateEventPosted) {
1031            // Find the effect in effectSettings array
1032            M4OSA_UInt32 index;
1033            for (index = 0; index < mNumberEffects; index++) {
1034                M4OSA_UInt32 timeMs = mDecodedVideoTs/1000;
1035                M4OSA_UInt32 timeOffset = mDecVideoTsStoryBoard/1000;
1036                if(mEffectsSettings[index].VideoEffectType ==
1037                    (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
1038                    if (((mEffectsSettings[index].uiStartTime + 1) <=
1039                        timeMs + timeOffset - mPlayBeginTimeMsec) &&
1040                        ((mEffectsSettings[index].uiStartTime - 1 +
1041                        mEffectsSettings[index].uiDuration) >=
1042                        timeMs + timeOffset - mPlayBeginTimeMsec))
1043                    {
1044                        break;
1045                    }
1046                }
1047            }
1048            if (index < mNumberEffects) {
1049                mCurrFramingEffectIndex = index;
1050                mOverlayUpdateEventPosted = true;
1051                postOverlayUpdateEvent_l();
1052                ALOGV("Framing index = %ld", mCurrFramingEffectIndex);
1053            } else {
1054                ALOGV("No framing effects found");
1055            }
1056        }
1057
1058    } else if (mOverlayUpdateEventPosted) {
1059        //Post the event when the overlay is no more valid
1060        ALOGV("Overlay is Done");
1061        mOverlayUpdateEventPosted = false;
1062        postOverlayUpdateEvent_l();
1063    }
1064
1065    if (mVideoRenderer != NULL) {
1066        mVideoRenderer->render(mVideoBuffer, mCurrentVideoEffect,
1067                mRenderingMode, mIsVideoSourceJpg);
1068    }
1069
1070    mVideoBuffer->release();
1071    mVideoBuffer = NULL;
1072
1073    // Post progress callback based on callback interval set
1074    if(mNumberDecVideoFrames >= mProgressCbInterval) {
1075        postProgressCallbackEvent_l();
1076        mNumberDecVideoFrames = 0;  // reset counter
1077    }
1078
1079    // if reached EndCutTime of clip, post EOS event
1080    if((timeUs/1000) >= mPlayEndTimeMsec) {
1081        ALOGV("PreviewPlayer: onVideoEvent EOS.");
1082        mFlags |= VIDEO_AT_EOS;
1083        mFlags |= AUDIO_AT_EOS;
1084        mOverlayUpdateEventPosted = false;
1085        // Set the last decoded timestamp to duration
1086        mDecodedVideoTs = (mPlayEndTimeMsec*1000LL);
1087        postStreamDoneEvent_l(ERROR_END_OF_STREAM);
1088    }
1089    else {
1090        if ((wasSeeking != NO_SEEK) && (mFlags & SEEK_PREVIEW)) {
1091            mFlags &= ~SEEK_PREVIEW;
1092            return;
1093        }
1094
1095        if(!mIsVideoSourceJpg) {
1096            postVideoEvent_l(0);
1097        }
1098        else {
1099            postVideoEvent_l(33000);
1100        }
1101    }
1102}
1103
1104status_t PreviewPlayer::prepare() {
1105    ALOGV("prepare");
1106    Mutex::Autolock autoLock(mLock);
1107    return prepare_l();
1108}
1109
1110status_t PreviewPlayer::prepare_l() {
1111    ALOGV("prepare_l");
1112    if (mFlags & PREPARED) {
1113        return OK;
1114    }
1115
1116    if (mFlags & PREPARING) {
1117        return UNKNOWN_ERROR;
1118    }
1119
1120    mIsAsyncPrepare = false;
1121    status_t err = prepareAsync_l();
1122
1123    if (err != OK) {
1124        return err;
1125    }
1126
1127    while (mFlags & PREPARING) {
1128        mPreparedCondition.wait(mLock);
1129    }
1130
1131    return mPrepareResult;
1132}
1133
1134status_t PreviewPlayer::prepareAsync() {
1135    ALOGV("prepareAsync");
1136    Mutex::Autolock autoLock(mLock);
1137    return prepareAsync_l();
1138}
1139
1140status_t PreviewPlayer::prepareAsync_l() {
1141    ALOGV("prepareAsync_l");
1142    if (mFlags & PREPARING) {
1143        return UNKNOWN_ERROR;  // async prepare already pending
1144    }
1145
1146    if (!mQueueStarted) {
1147        mQueue.start();
1148        mQueueStarted = true;
1149    }
1150
1151    mFlags |= PREPARING;
1152    mAsyncPrepareEvent = new PreviewPlayerEvent(
1153            this, &PreviewPlayer::onPrepareAsyncEvent);
1154
1155    mQueue.postEvent(mAsyncPrepareEvent);
1156
1157    return OK;
1158}
1159
1160status_t PreviewPlayer::finishSetDataSource_l() {
1161    sp<DataSource> dataSource;
1162    sp<MediaExtractor> extractor;
1163
1164    dataSource = DataSource::CreateFromURI(mUri.string(), NULL);
1165
1166    if (dataSource == NULL) {
1167        return UNKNOWN_ERROR;
1168    }
1169
1170    //If file type is .rgb, then no need to check for Extractor
1171    int uriLen = strlen(mUri);
1172    int startOffset = uriLen - 4;
1173    if(!strncasecmp(mUri+startOffset, ".rgb", 4)) {
1174        extractor = NULL;
1175    }
1176    else {
1177        extractor = MediaExtractor::Create(dataSource,
1178                                        MEDIA_MIMETYPE_CONTAINER_MPEG4);
1179    }
1180
1181    if (extractor == NULL) {
1182        ALOGV("finishSetDataSource_l: failed to create extractor");
1183        return setDataSource_l_jpg();
1184    }
1185
1186    return setDataSource_l(extractor);
1187}
1188
1189void PreviewPlayer::onPrepareAsyncEvent() {
1190    Mutex::Autolock autoLock(mLock);
1191    ALOGV("onPrepareAsyncEvent");
1192
1193    if (mFlags & PREPARE_CANCELLED) {
1194        ALOGV("prepare was cancelled before doing anything");
1195        abortPrepare(UNKNOWN_ERROR);
1196        return;
1197    }
1198
1199    if (mUri.size() > 0) {
1200        status_t err = finishSetDataSource_l();
1201
1202        if (err != OK) {
1203            abortPrepare(err);
1204            return;
1205        }
1206    }
1207
1208    if (mVideoTrack != NULL && mVideoSource == NULL) {
1209        status_t err = initVideoDecoder_l(OMXCodec::kHardwareCodecsOnly);
1210
1211        if (err != OK) {
1212            abortPrepare(err);
1213            return;
1214        }
1215    }
1216
1217    if (mAudioTrack != NULL && mAudioSource == NULL) {
1218        status_t err = initAudioDecoder_l();
1219
1220        if (err != OK) {
1221            abortPrepare(err);
1222            return;
1223        }
1224    }
1225    finishAsyncPrepare_l();
1226
1227}
1228
1229void PreviewPlayer::finishAsyncPrepare_l() {
1230    ALOGV("finishAsyncPrepare_l");
1231    if (mIsAsyncPrepare) {
1232        if (mVideoSource == NULL) {
1233            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1234        } else {
1235            notifyVideoSize_l();
1236        }
1237        notifyListener_l(MEDIA_PREPARED);
1238    }
1239
1240    mPrepareResult = OK;
1241    mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1242    mFlags |= PREPARED;
1243    mAsyncPrepareEvent = NULL;
1244    mPreparedCondition.broadcast();
1245}
1246
1247void PreviewPlayer::acquireLock() {
1248    ALOGV("acquireLock");
1249    mLockControl.lock();
1250}
1251
1252void PreviewPlayer::releaseLock() {
1253    ALOGV("releaseLock");
1254    mLockControl.unlock();
1255}
1256
1257status_t PreviewPlayer::loadEffectsSettings(
1258        M4VSS3GPP_EffectSettings* pEffectSettings, int nEffects) {
1259
1260    ALOGV("loadEffectsSettings");
1261    mNumberEffects = nEffects;
1262    mEffectsSettings = pEffectSettings;
1263    return OK;
1264}
1265
1266status_t PreviewPlayer::loadAudioMixSettings(
1267        M4xVSS_AudioMixingSettings* pAudioMixSettings) {
1268
1269    ALOGV("loadAudioMixSettings");
1270    mPreviewPlayerAudioMixSettings = pAudioMixSettings;
1271    return OK;
1272}
1273
1274status_t PreviewPlayer::setAudioMixPCMFileHandle(
1275        M4OSA_Context pAudioMixPCMFileHandle) {
1276
1277    ALOGV("setAudioMixPCMFileHandle");
1278    mAudioMixPCMFileHandle = pAudioMixPCMFileHandle;
1279    return OK;
1280}
1281
1282status_t PreviewPlayer::setAudioMixStoryBoardParam(
1283        M4OSA_UInt32 audioMixStoryBoardTS,
1284        M4OSA_UInt32 currentMediaBeginCutTime,
1285        M4OSA_UInt32 primaryTrackVolValue ) {
1286
1287    ALOGV("setAudioMixStoryBoardParam");
1288    mAudioMixStoryBoardTS = audioMixStoryBoardTS;
1289    mCurrentMediaBeginCutTime = currentMediaBeginCutTime;
1290    mCurrentMediaVolumeValue = primaryTrackVolValue;
1291    return OK;
1292}
1293
1294status_t PreviewPlayer::setPlaybackBeginTime(uint32_t msec) {
1295
1296    mPlayBeginTimeMsec = msec;
1297    return OK;
1298}
1299
1300status_t PreviewPlayer::setPlaybackEndTime(uint32_t msec) {
1301
1302    mPlayEndTimeMsec = msec;
1303    return OK;
1304}
1305
1306status_t PreviewPlayer::setStoryboardStartTime(uint32_t msec) {
1307
1308    mStoryboardStartTimeMsec = msec;
1309    mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL;
1310    return OK;
1311}
1312
1313status_t PreviewPlayer::setProgressCallbackInterval(uint32_t cbInterval) {
1314
1315    mProgressCbInterval = cbInterval;
1316    return OK;
1317}
1318
1319
1320status_t PreviewPlayer::setMediaRenderingMode(
1321        M4xVSS_MediaRendering mode,
1322        M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
1323
1324    mRenderingMode = mode;
1325
1326    /* get the video width and height by resolution */
1327    return getVideoSizeByResolution(
1328                outputVideoSize,
1329                    &mOutputVideoWidth, &mOutputVideoHeight);
1330
1331}
1332
1333status_t PreviewPlayer::resetJniCallbackTimeStamp() {
1334
1335    mDecVideoTsStoryBoard = mStoryboardStartTimeMsec * 1000LL;
1336    return OK;
1337}
1338
1339void PreviewPlayer::postProgressCallbackEvent_l() {
1340    if (mProgressCbEventPending) {
1341        return;
1342    }
1343    mProgressCbEventPending = true;
1344
1345    mQueue.postEvent(mProgressCbEvent);
1346}
1347
1348
1349void PreviewPlayer::onProgressCbEvent() {
1350    Mutex::Autolock autoLock(mLock);
1351    if (!mProgressCbEventPending) {
1352        return;
1353    }
1354    mProgressCbEventPending = false;
1355    // If playback starts from previous I-frame,
1356    // then send frame storyboard duration
1357    if ((mDecodedVideoTs/1000) < mPlayBeginTimeMsec) {
1358        notifyListener_l(MEDIA_INFO, 0, mDecVideoTsStoryBoard/1000);
1359    } else {
1360        notifyListener_l(MEDIA_INFO, 0,
1361        (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec));
1362    }
1363}
1364
1365void PreviewPlayer::postOverlayUpdateEvent_l() {
1366    if (mOverlayUpdateEventPending) {
1367        return;
1368    }
1369    mOverlayUpdateEventPending = true;
1370    mQueue.postEvent(mOverlayUpdateEvent);
1371}
1372
1373void PreviewPlayer::onUpdateOverlayEvent() {
1374    Mutex::Autolock autoLock(mLock);
1375
1376    if (!mOverlayUpdateEventPending) {
1377        return;
1378    }
1379    mOverlayUpdateEventPending = false;
1380
1381    int updateState = mOverlayUpdateEventPosted? 1: 0;
1382    notifyListener_l(0xBBBBBBBB, updateState, mCurrFramingEffectIndex);
1383}
1384
1385
1386void PreviewPlayer::setVideoPostProcessingNode(
1387        M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
1388
1389    uint32_t effect = VIDEO_EFFECT_NONE;
1390
1391    //Map M4VSS3GPP_VideoEffectType to local enum
1392    switch(type) {
1393        case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
1394            effect = VIDEO_EFFECT_FADEFROMBLACK;
1395            break;
1396
1397        case M4VSS3GPP_kVideoEffectType_FadeToBlack:
1398            effect = VIDEO_EFFECT_FADETOBLACK;
1399            break;
1400
1401        case M4xVSS_kVideoEffectType_BlackAndWhite:
1402            effect = VIDEO_EFFECT_BLACKANDWHITE;
1403            break;
1404
1405        case M4xVSS_kVideoEffectType_Pink:
1406            effect = VIDEO_EFFECT_PINK;
1407            break;
1408
1409        case M4xVSS_kVideoEffectType_Green:
1410            effect = VIDEO_EFFECT_GREEN;
1411            break;
1412
1413        case M4xVSS_kVideoEffectType_Sepia:
1414            effect = VIDEO_EFFECT_SEPIA;
1415            break;
1416
1417        case M4xVSS_kVideoEffectType_Negative:
1418            effect = VIDEO_EFFECT_NEGATIVE;
1419            break;
1420
1421        case M4xVSS_kVideoEffectType_Framing:
1422            effect = VIDEO_EFFECT_FRAMING;
1423            break;
1424
1425        case M4xVSS_kVideoEffectType_Fifties:
1426            effect = VIDEO_EFFECT_FIFTIES;
1427            break;
1428
1429        case M4xVSS_kVideoEffectType_ColorRGB16:
1430            effect = VIDEO_EFFECT_COLOR_RGB16;
1431            break;
1432
1433        case M4xVSS_kVideoEffectType_Gradient:
1434            effect = VIDEO_EFFECT_GRADIENT;
1435            break;
1436
1437        default:
1438            effect = VIDEO_EFFECT_NONE;
1439            break;
1440    }
1441
1442    if (enable == M4OSA_TRUE) {
1443        //If already set, then no need to set again
1444        if (!(mCurrentVideoEffect & effect)) {
1445            mCurrentVideoEffect |= effect;
1446            if (effect == VIDEO_EFFECT_FIFTIES) {
1447                mIsFiftiesEffectStarted = true;
1448            }
1449        }
1450    } else  {
1451        //Reset only if already set
1452        if (mCurrentVideoEffect & effect) {
1453            mCurrentVideoEffect &= ~effect;
1454        }
1455    }
1456}
1457
1458status_t PreviewPlayer::setImageClipProperties(uint32_t width,uint32_t height) {
1459    mVideoWidth = width;
1460    mVideoHeight = height;
1461    return OK;
1462}
1463
1464status_t PreviewPlayer::readFirstVideoFrame() {
1465    ALOGV("readFirstVideoFrame");
1466
1467    if (!mVideoBuffer) {
1468        MediaSource::ReadOptions options;
1469        if (mSeeking != NO_SEEK) {
1470            ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs,
1471                    mSeekTimeUs / 1E6);
1472
1473            options.setSeekTo(
1474                    mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST);
1475        }
1476        for (;;) {
1477            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1478            options.clearSeekTo();
1479
1480            if (err != OK) {
1481                CHECK(!mVideoBuffer);
1482
1483                if (err == INFO_FORMAT_CHANGED) {
1484                    ALOGV("VideoSource signalled format change");
1485                    notifyVideoSize_l();
1486
1487                    if (mVideoRenderer != NULL) {
1488                        mVideoRendererIsPreview = false;
1489                        err = initRenderer_l();
1490                        if (err != OK) {
1491                            postStreamDoneEvent_l(err);
1492                        }
1493                    }
1494
1495                    updateSizeToRender(mVideoSource->getFormat());
1496                    continue;
1497                }
1498                ALOGV("EOS reached.");
1499                mFlags |= VIDEO_AT_EOS;
1500                mFlags |= AUDIO_AT_EOS;
1501                postStreamDoneEvent_l(err);
1502                return OK;
1503            }
1504
1505            if (mVideoBuffer->range_length() == 0) {
1506                // Some decoders, notably the PV AVC software decoder
1507                // return spurious empty buffers that we just want to ignore.
1508
1509                mVideoBuffer->release();
1510                mVideoBuffer = NULL;
1511                continue;
1512            }
1513
1514            int64_t videoTimeUs;
1515            CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &videoTimeUs));
1516            if (mSeeking != NO_SEEK) {
1517                if (videoTimeUs < mSeekTimeUs) {
1518                    // buffers are before seek time
1519                    // ignore them
1520                    mVideoBuffer->release();
1521                    mVideoBuffer = NULL;
1522                    continue;
1523                }
1524            } else {
1525                if ((videoTimeUs/1000) < mPlayBeginTimeMsec) {
1526                    // buffers are before begin cut time
1527                    // ignore them
1528                    mVideoBuffer->release();
1529                    mVideoBuffer = NULL;
1530                    continue;
1531                }
1532            }
1533            break;
1534        }
1535    }
1536
1537    int64_t timeUs;
1538    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1539    setPosition_l(timeUs);
1540
1541    mDecodedVideoTs = timeUs;
1542
1543    return OK;
1544
1545}
1546
1547status_t PreviewPlayer::getLastRenderedTimeMs(uint32_t *lastRenderedTimeMs) {
1548    *lastRenderedTimeMs = (((mDecodedVideoTs+mDecVideoTsStoryBoard)/1000)-mPlayBeginTimeMsec);
1549    return OK;
1550}
1551
1552void PreviewPlayer::updateSizeToRender(sp<MetaData> meta) {
1553    if (mVideoRenderer) {
1554        mVideoRenderer->updateVideoSize(meta);
1555    }
1556}
1557
1558void PreviewPlayer::setListener(const wp<MediaPlayerBase> &listener) {
1559    Mutex::Autolock autoLock(mLock);
1560    mListener = listener;
1561}
1562
1563status_t PreviewPlayer::setDataSource(const sp<IStreamSource> &source) {
1564    return INVALID_OPERATION;
1565}
1566
1567void PreviewPlayer::reset() {
1568    Mutex::Autolock autoLock(mLock);
1569    reset_l();
1570}
1571
1572void PreviewPlayer::clear_l() {
1573    mDisplayWidth = 0;
1574    mDisplayHeight = 0;
1575
1576    if (mFlags & PLAYING) {
1577        updateBatteryUsage_l();
1578    }
1579
1580    if (mFlags & PREPARING) {
1581        mFlags |= PREPARE_CANCELLED;
1582
1583        if (mFlags & PREPARING_CONNECTED) {
1584            // We are basically done preparing, we're just buffering
1585            // enough data to start playback, we can safely interrupt that.
1586            finishAsyncPrepare_l();
1587        }
1588    }
1589
1590    while (mFlags & PREPARING) {
1591        mPreparedCondition.wait(mLock);
1592    }
1593
1594    cancelPlayerEvents_l(true);
1595
1596    mAudioTrack.clear();
1597    mVideoTrack.clear();
1598
1599    // Shutdown audio first, so that the respone to the reset request
1600    // appears to happen instantaneously as far as the user is concerned
1601    // If we did this later, audio would continue playing while we
1602    // shutdown the video-related resources and the player appear to
1603    // not be as responsive to a reset request.
1604    if (mAudioPlayer == NULL && mAudioSource != NULL) {
1605        // If we had an audio player, it would have effectively
1606        // taken possession of the audio source and stopped it when
1607        // _it_ is stopped. Otherwise this is still our responsibility.
1608        mAudioSource->stop();
1609    }
1610    mAudioSource.clear();
1611
1612    mTimeSource = NULL;
1613
1614    delete mAudioPlayer;
1615    mAudioPlayer = NULL;
1616
1617    if (mVideoSource != NULL) {
1618        shutdownVideoDecoder_l();
1619    }
1620
1621    mDurationUs = -1;
1622    mFlags = 0;
1623    mExtractorFlags = 0;
1624    mTimeSourceDeltaUs = 0;
1625    mVideoTimeUs = 0;
1626
1627    mSeeking = NO_SEEK;
1628    mSeekNotificationSent = false;
1629    mSeekTimeUs = 0;
1630
1631    mUri.setTo("");
1632
1633    mBitrate = -1;
1634    mLastVideoTimeUs = -1;
1635}
1636
1637void PreviewPlayer::notifyListener_l(int msg, int ext1, int ext2) {
1638    if (mListener != NULL) {
1639        sp<MediaPlayerBase> listener = mListener.promote();
1640
1641        if (listener != NULL) {
1642            listener->sendEvent(msg, ext1, ext2);
1643        }
1644    }
1645}
1646
1647void PreviewPlayer::onVideoLagUpdate() {
1648    Mutex::Autolock autoLock(mLock);
1649    if (!mVideoLagEventPending) {
1650        return;
1651    }
1652    mVideoLagEventPending = false;
1653
1654    int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
1655    int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
1656
1657    if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
1658        ALOGV("video late by %lld ms.", videoLateByUs / 1000ll);
1659
1660        notifyListener_l(
1661                MEDIA_INFO,
1662                MEDIA_INFO_VIDEO_TRACK_LAGGING,
1663                videoLateByUs / 1000ll);
1664    }
1665
1666    postVideoLagEvent_l();
1667}
1668
1669void PreviewPlayer::notifyVideoSize_l() {
1670    sp<MetaData> meta = mVideoSource->getFormat();
1671
1672    int32_t vWidth, vHeight;
1673    int32_t cropLeft, cropTop, cropRight, cropBottom;
1674
1675    CHECK(meta->findInt32(kKeyWidth, &vWidth));
1676    CHECK(meta->findInt32(kKeyHeight, &vHeight));
1677
1678    mGivenWidth = vWidth;
1679    mGivenHeight = vHeight;
1680
1681    if (!meta->findRect(
1682                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
1683
1684        cropLeft = cropTop = 0;
1685        cropRight = vWidth - 1;
1686        cropBottom = vHeight - 1;
1687
1688        ALOGD("got dimensions only %d x %d", vWidth, vHeight);
1689    } else {
1690        ALOGD("got crop rect %d, %d, %d, %d",
1691             cropLeft, cropTop, cropRight, cropBottom);
1692    }
1693
1694    mCropRect.left = cropLeft;
1695    mCropRect.right = cropRight;
1696    mCropRect.top = cropTop;
1697    mCropRect.bottom = cropBottom;
1698
1699    int32_t displayWidth;
1700    if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
1701        ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
1702        mDisplayWidth = displayWidth;
1703    }
1704    int32_t displayHeight;
1705    if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
1706        ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
1707        mDisplayHeight = displayHeight;
1708    }
1709
1710    int32_t usableWidth = cropRight - cropLeft + 1;
1711    int32_t usableHeight = cropBottom - cropTop + 1;
1712    if (mDisplayWidth != 0) {
1713        usableWidth = mDisplayWidth;
1714    }
1715    if (mDisplayHeight != 0) {
1716        usableHeight = mDisplayHeight;
1717    }
1718
1719    int32_t rotationDegrees;
1720    if (!mVideoTrack->getFormat()->findInt32(
1721                kKeyRotation, &rotationDegrees)) {
1722        rotationDegrees = 0;
1723    }
1724
1725    if (rotationDegrees == 90 || rotationDegrees == 270) {
1726        notifyListener_l(
1727                MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
1728    } else {
1729        notifyListener_l(
1730                MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
1731    }
1732}
1733
1734status_t PreviewPlayer::pause() {
1735    Mutex::Autolock autoLock(mLock);
1736
1737    mFlags &= ~CACHE_UNDERRUN;
1738
1739    return pause_l();
1740}
1741
1742status_t PreviewPlayer::pause_l(bool at_eos) {
1743    if (!(mFlags & PLAYING)) {
1744        return OK;
1745    }
1746
1747    cancelPlayerEvents_l();
1748
1749    if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
1750        if (at_eos) {
1751            // If we played the audio stream to completion we
1752            // want to make sure that all samples remaining in the audio
1753            // track's queue are played out.
1754            mAudioPlayer->pause(true /* playPendingSamples */);
1755        } else {
1756            mAudioPlayer->pause();
1757        }
1758
1759        mFlags &= ~AUDIO_RUNNING;
1760    }
1761
1762    mFlags &= ~PLAYING;
1763    updateBatteryUsage_l();
1764
1765    return OK;
1766}
1767
1768bool PreviewPlayer::isPlaying() const {
1769    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
1770}
1771
1772void PreviewPlayer::setSurface(const sp<Surface> &surface) {
1773    Mutex::Autolock autoLock(mLock);
1774
1775    mSurface = surface;
1776    setNativeWindow_l(surface);
1777}
1778
1779void PreviewPlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
1780    Mutex::Autolock autoLock(mLock);
1781
1782    mSurface.clear();
1783    if (surfaceTexture != NULL) {
1784        setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
1785    }
1786}
1787
1788void PreviewPlayer::shutdownVideoDecoder_l() {
1789    if (mVideoBuffer) {
1790        mVideoBuffer->release();
1791        mVideoBuffer = NULL;
1792    }
1793
1794    mVideoSource->stop();
1795
1796    // The following hack is necessary to ensure that the OMX
1797    // component is completely released by the time we may try
1798    // to instantiate it again.
1799    wp<MediaSource> tmp = mVideoSource;
1800    mVideoSource.clear();
1801    while (tmp.promote() != NULL) {
1802        usleep(1000);
1803    }
1804    IPCThreadState::self()->flushCommands();
1805}
1806
1807void PreviewPlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
1808    mNativeWindow = native;
1809
1810    if (mVideoSource == NULL) {
1811        return;
1812    }
1813
1814    ALOGI("attempting to reconfigure to use new surface");
1815
1816    bool wasPlaying = (mFlags & PLAYING) != 0;
1817
1818    pause_l();
1819
1820    shutdownVideoDecoder_l();
1821
1822    CHECK_EQ(initVideoDecoder_l(), (status_t)OK);
1823
1824    if (mLastVideoTimeUs >= 0) {
1825        mSeeking = SEEK;
1826        mSeekNotificationSent = true;
1827        mSeekTimeUs = mLastVideoTimeUs;
1828        mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1829    }
1830
1831    if (wasPlaying) {
1832        play_l();
1833    }
1834}
1835
1836void PreviewPlayer::setAudioSink(
1837        const sp<MediaPlayerBase::AudioSink> &audioSink) {
1838    Mutex::Autolock autoLock(mLock);
1839
1840    mAudioSink = audioSink;
1841}
1842
1843status_t PreviewPlayer::setLooping(bool shouldLoop) {
1844    Mutex::Autolock autoLock(mLock);
1845
1846    mFlags = mFlags & ~LOOPING;
1847
1848    if (shouldLoop) {
1849        mFlags |= LOOPING;
1850    }
1851
1852    return OK;
1853}
1854
1855void PreviewPlayer::setDuration_l(int64_t durationUs) {
1856    if (mDurationUs < 0 || durationUs > mDurationUs) {
1857        mDurationUs = durationUs;
1858    }
1859}
1860
1861status_t PreviewPlayer::getDuration(int64_t *durationUs) {
1862    Mutex::Autolock autoLock(mLock);
1863    if (mDurationUs < 0) {
1864        return UNKNOWN_ERROR;
1865    }
1866
1867    *durationUs = mDurationUs;
1868    return OK;
1869}
1870
1871status_t PreviewPlayer::getPosition(int64_t *positionUs) {
1872    Mutex::Autolock autoLock(mLock);
1873
1874    if (mSeeking != NO_SEEK) {
1875        *positionUs = mSeekTimeUs;
1876    } else if (mVideoSource != NULL
1877            && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
1878        *positionUs = mVideoTimeUs;
1879    } else if (mAudioPlayer != NULL) {
1880        *positionUs = mAudioPlayer->getMediaTimeUs();
1881    } else {
1882        *positionUs = 0;
1883    }
1884
1885    return OK;
1886}
1887
1888void PreviewPlayer::setPosition_l(int64_t timeUs) {
1889    mVideoTimeUs = timeUs;
1890}
1891
1892status_t PreviewPlayer::seekTo_l(int64_t timeUs) {
1893    ALOGV("seekTo_l");
1894    if (mFlags & CACHE_UNDERRUN) {
1895        mFlags &= ~CACHE_UNDERRUN;
1896        play_l();
1897    }
1898
1899    if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1900        // Video playback completed before, there's no pending
1901        // video event right now. In order for this new seek
1902        // to be honored, we need to post one.
1903
1904        postVideoEvent_l();
1905    }
1906
1907    mSeeking = SEEK;
1908    mSeekNotificationSent = false;
1909    mSeekTimeUs = timeUs;
1910    mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1911
1912    seekAudioIfNecessary_l();
1913
1914    if (!(mFlags & PLAYING)) {
1915        ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
1916             " immediately.");
1917
1918        notifyListener_l(MEDIA_SEEK_COMPLETE);
1919        mSeekNotificationSent = true;
1920
1921        if ((mFlags & PREPARED) && mVideoSource != NULL) {
1922            mFlags |= SEEK_PREVIEW;
1923            postVideoEvent_l();
1924        }
1925    }
1926
1927    return OK;
1928}
1929
1930void PreviewPlayer::seekAudioIfNecessary_l() {
1931    if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
1932        mAudioPlayer->seekTo(mSeekTimeUs);
1933
1934        mWatchForAudioSeekComplete = true;
1935        mWatchForAudioEOS = true;
1936    }
1937}
1938
1939void PreviewPlayer::setAudioSource(const sp<MediaSource>& source) {
1940    CHECK(source != NULL);
1941    mAudioTrack = source;
1942}
1943
1944void PreviewPlayer::setVideoSource(const sp<MediaSource>& source) {
1945    CHECK(source != NULL);
1946    mVideoTrack = source;
1947}
1948
1949void PreviewPlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1950    if (mSeeking == SEEK_VIDEO_ONLY) {
1951        mSeeking = NO_SEEK;
1952        return;
1953    }
1954
1955    if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
1956        return;
1957    }
1958
1959    if (mAudioPlayer != NULL) {
1960        ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
1961
1962        // If we don't have a video time, seek audio to the originally
1963        // requested seek time instead.
1964
1965        mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1966        mWatchForAudioSeekComplete = true;
1967        mWatchForAudioEOS = true;
1968    } else if (!mSeekNotificationSent) {
1969        // If we're playing video only, report seek complete now,
1970        // otherwise audio player will notify us later.
1971        notifyListener_l(MEDIA_SEEK_COMPLETE);
1972        mSeekNotificationSent = true;
1973    }
1974
1975    mFlags |= FIRST_FRAME;
1976    mSeeking = NO_SEEK;
1977}
1978
1979void PreviewPlayer::onCheckAudioStatus() {
1980    Mutex::Autolock autoLock(mLock);
1981    if (!mAudioStatusEventPending) {
1982        // Event was dispatched and while we were blocking on the mutex,
1983        // has already been cancelled.
1984        return;
1985    }
1986
1987    mAudioStatusEventPending = false;
1988
1989    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1990        mWatchForAudioSeekComplete = false;
1991
1992        if (!mSeekNotificationSent) {
1993            notifyListener_l(MEDIA_SEEK_COMPLETE);
1994            mSeekNotificationSent = true;
1995        }
1996
1997        mSeeking = NO_SEEK;
1998    }
1999
2000    status_t finalStatus;
2001    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
2002        mWatchForAudioEOS = false;
2003        mFlags |= AUDIO_AT_EOS;
2004        mFlags |= FIRST_FRAME;
2005        postStreamDoneEvent_l(finalStatus);
2006    }
2007}
2008
2009void PreviewPlayer::postVideoEvent_l(int64_t delayUs) {
2010    if (mVideoEventPending) {
2011        return;
2012    }
2013
2014    mVideoEventPending = true;
2015    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
2016}
2017
2018void PreviewPlayer::postStreamDoneEvent_l(status_t status) {
2019    if (mStreamDoneEventPending) {
2020        return;
2021    }
2022    mStreamDoneEventPending = true;
2023
2024    mStreamDoneStatus = status;
2025    mQueue.postEvent(mStreamDoneEvent);
2026}
2027
2028void PreviewPlayer::postVideoLagEvent_l() {
2029    if (mVideoLagEventPending) {
2030        return;
2031    }
2032    mVideoLagEventPending = true;
2033    mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
2034}
2035
2036void PreviewPlayer::postCheckAudioStatusEvent_l(int64_t delayUs) {
2037    if (mAudioStatusEventPending) {
2038        return;
2039    }
2040    mAudioStatusEventPending = true;
2041    mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
2042}
2043
2044void PreviewPlayer::abortPrepare(status_t err) {
2045    CHECK(err != OK);
2046
2047    if (mIsAsyncPrepare) {
2048        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2049    }
2050
2051    mPrepareResult = err;
2052    mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
2053    mAsyncPrepareEvent = NULL;
2054    mPreparedCondition.broadcast();
2055}
2056
2057uint32_t PreviewPlayer::getSourceSeekFlags() const {
2058    Mutex::Autolock lock(mLock);
2059    return mExtractorFlags;
2060}
2061
2062void PreviewPlayer::postAudioEOS(int64_t delayUs) {
2063    Mutex::Autolock autoLock(mLock);
2064    postCheckAudioStatusEvent_l(delayUs);
2065}
2066
2067void PreviewPlayer::postAudioSeekComplete() {
2068    Mutex::Autolock autoLock(mLock);
2069    postCheckAudioStatusEvent_l(0 /* delayUs */);
2070}
2071
2072void PreviewPlayer::updateBatteryUsage_l() {
2073    uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
2074    if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
2075        params |= IMediaPlayerService::kBatteryDataTrackAudio;
2076    }
2077    if (mVideoSource != NULL) {
2078        params |= IMediaPlayerService::kBatteryDataTrackVideo;
2079    }
2080    addBatteryData(params);
2081}
2082
2083}  // namespace android
2084