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#define LOG_NDEBUG 1
18#define LOG_TAG "VideoEditorAudioPlayer"
19#include <utils/Log.h>
20
21#include <binder/IPCThreadState.h>
22#include <media/AudioTrack.h>
23#include <VideoEditorAudioPlayer.h>
24#include <media/stagefright/foundation/ADebug.h>
25#include <media/stagefright/MediaDefs.h>
26#include <media/stagefright/MediaErrors.h>
27#include <media/stagefright/MediaSource.h>
28#include <media/stagefright/MetaData.h>
29
30#include <system/audio.h>
31
32#include "PreviewPlayer.h"
33namespace android {
34
35VideoEditorAudioPlayer::VideoEditorAudioPlayer(
36        const sp<MediaPlayerBase::AudioSink> &audioSink,
37        PreviewPlayer *observer)
38    : mAudioTrack(NULL),
39      mInputBuffer(NULL),
40      mSampleRate(0),
41      mLatencyUs(0),
42      mFrameSize(0),
43      mNumFramesPlayed(0),
44      mPositionTimeMediaUs(-1),
45      mPositionTimeRealUs(-1),
46      mSeeking(false),
47      mReachedEOS(false),
48      mFinalStatus(OK),
49      mStarted(false),
50      mIsFirstBuffer(false),
51      mFirstBufferResult(OK),
52      mFirstBuffer(NULL),
53      mAudioSink(audioSink),
54      mObserver(observer) {
55
56    ALOGV("Constructor");
57    mBGAudioPCMFileHandle = NULL;
58    mAudioProcess = NULL;
59    mBGAudioPCMFileLength = 0;
60    mBGAudioPCMFileTrimmedLength = 0;
61    mBGAudioPCMFileDuration = 0;
62    mBGAudioPCMFileSeekPoint = 0;
63    mBGAudioPCMFileOriginalSeekPoint = 0;
64    mBGAudioStoryBoardSkimTimeStamp = 0;
65    mBGAudioStoryBoardCurrentMediaBeginCutTS = 0;
66    mBGAudioStoryBoardCurrentMediaVolumeVal = 0;
67    mSeekTimeUs = 0;
68    mSource = NULL;
69}
70
71VideoEditorAudioPlayer::~VideoEditorAudioPlayer() {
72
73    ALOGV("Destructor");
74    if (mStarted) {
75        reset();
76    }
77    if (mAudioProcess != NULL) {
78        delete mAudioProcess;
79        mAudioProcess = NULL;
80    }
81}
82
83void VideoEditorAudioPlayer::pause(bool playPendingSamples) {
84    ALOGV("pause: playPendingSamples=%d", playPendingSamples);
85    CHECK(mStarted);
86
87    if (playPendingSamples) {
88        if (mAudioSink.get() != NULL) {
89            mAudioSink->stop();
90        } else {
91            mAudioTrack->stop();
92        }
93    } else {
94        if (mAudioSink.get() != NULL) {
95            mAudioSink->pause();
96        } else {
97            mAudioTrack->pause();
98        }
99    }
100}
101
102void VideoEditorAudioPlayer::clear() {
103    ALOGV("clear");
104    if (!mStarted) {
105        return;
106    }
107
108    if (mAudioSink.get() != NULL) {
109        mAudioSink->stop();
110        mAudioSink->close();
111    } else {
112        mAudioTrack->stop();
113
114        delete mAudioTrack;
115        mAudioTrack = NULL;
116    }
117
118    // Make sure to release any buffer we hold onto so that the
119    // source is able to stop().
120
121    if (mFirstBuffer != NULL) {
122        mFirstBuffer->release();
123        mFirstBuffer = NULL;
124    }
125
126    if (mInputBuffer != NULL) {
127        ALOGV("AudioPlayerBase releasing input buffer.");
128
129        mInputBuffer->release();
130        mInputBuffer = NULL;
131    }
132
133    mSource->stop();
134
135    // The following hack is necessary to ensure that the OMX
136    // component is completely released by the time we may try
137    // to instantiate it again.
138    wp<MediaSource> tmp = mSource;
139    mSource.clear();
140    while (tmp.promote() != NULL) {
141        usleep(1000);
142    }
143    IPCThreadState::self()->flushCommands();
144
145    mNumFramesPlayed = 0;
146    mPositionTimeMediaUs = -1;
147    mPositionTimeRealUs = -1;
148    mSeeking = false;
149    mReachedEOS = false;
150    mFinalStatus = OK;
151    mStarted = false;
152}
153
154void VideoEditorAudioPlayer::resume() {
155    ALOGV("resume");
156
157    AudioMixSettings audioMixSettings;
158
159    // Single audio player is used;
160    // Pass on the audio ducking parameters
161    // which might have changed with new audio source
162    audioMixSettings.lvInDucking_threshold =
163        mAudioMixSettings->uiInDucking_threshold;
164    audioMixSettings.lvInDucking_lowVolume =
165        ((M4OSA_Float)mAudioMixSettings->uiInDucking_lowVolume) / 100.0;
166    audioMixSettings.lvInDucking_enable =
167        mAudioMixSettings->bInDucking_enable;
168    audioMixSettings.lvPTVolLevel =
169        ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal) / 100.0;
170    audioMixSettings.lvBTVolLevel =
171        ((M4OSA_Float)mAudioMixSettings->uiAddVolume) / 100.0;
172    audioMixSettings.lvBTChannelCount = mAudioMixSettings->uiBTChannelCount;
173    audioMixSettings.lvPTChannelCount = mAudioMixSettings->uiNbChannels;
174
175    // Call to Audio mix param setting
176    mAudioProcess->setMixParams(audioMixSettings);
177
178    CHECK(mStarted);
179
180    if (mAudioSink.get() != NULL) {
181        mAudioSink->start();
182    } else {
183        mAudioTrack->start();
184    }
185}
186
187status_t VideoEditorAudioPlayer::seekTo(int64_t time_us) {
188    ALOGV("seekTo: %lld", time_us);
189    Mutex::Autolock autoLock(mLock);
190
191    mSeeking = true;
192    mPositionTimeRealUs = mPositionTimeMediaUs = -1;
193    mReachedEOS = false;
194    mSeekTimeUs = time_us;
195
196    if (mAudioSink != NULL) {
197        mAudioSink->flush();
198    } else {
199        mAudioTrack->flush();
200    }
201
202    return OK;
203}
204
205bool VideoEditorAudioPlayer::isSeeking() {
206    Mutex::Autolock lock(mLock);
207    ALOGV("isSeeking: mSeeking=%d", mSeeking);
208    return mSeeking;
209}
210
211bool VideoEditorAudioPlayer::reachedEOS(status_t *finalStatus) {
212    ALOGV("reachedEOS: status=%d", mFinalStatus);
213    *finalStatus = OK;
214
215    Mutex::Autolock autoLock(mLock);
216    *finalStatus = mFinalStatus;
217    return mReachedEOS;
218}
219
220int64_t VideoEditorAudioPlayer::getRealTimeUs() {
221    Mutex::Autolock autoLock(mLock);
222    return getRealTimeUs_l();
223}
224
225int64_t VideoEditorAudioPlayer::getRealTimeUs_l() {
226    return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
227}
228
229int64_t VideoEditorAudioPlayer::getMediaTimeUs() {
230    ALOGV("getMediaTimeUs");
231    Mutex::Autolock autoLock(mLock);
232
233    if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
234        if (mSeeking) {
235            return mSeekTimeUs;
236        }
237
238        return 0;
239    }
240
241    int64_t realTimeOffset = getRealTimeUs_l() - mPositionTimeRealUs;
242    if (realTimeOffset < 0) {
243        realTimeOffset = 0;
244    }
245
246    return mPositionTimeMediaUs + realTimeOffset;
247}
248
249bool VideoEditorAudioPlayer::getMediaTimeMapping(
250        int64_t *realtime_us, int64_t *mediatime_us) {
251    ALOGV("getMediaTimeMapping");
252    Mutex::Autolock autoLock(mLock);
253
254    *realtime_us = mPositionTimeRealUs;
255    *mediatime_us = mPositionTimeMediaUs;
256
257    return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
258}
259
260void VideoEditorAudioPlayer::setSource(const sp<MediaSource> &source) {
261    Mutex::Autolock autoLock(mLock);
262
263    // Before setting source, stop any existing source.
264    // Make sure to release any buffer we hold onto so that the
265    // source is able to stop().
266
267    if (mFirstBuffer != NULL) {
268        mFirstBuffer->release();
269        mFirstBuffer = NULL;
270    }
271
272    if (mInputBuffer != NULL) {
273        ALOGV("VideoEditorAudioPlayer releasing input buffer.");
274
275        mInputBuffer->release();
276        mInputBuffer = NULL;
277    }
278
279    if (mSource != NULL) {
280        mSource->stop();
281        mSource.clear();
282    }
283
284    mSource = source;
285    mReachedEOS = false;
286}
287
288sp<MediaSource> VideoEditorAudioPlayer::getSource() {
289    Mutex::Autolock autoLock(mLock);
290    return mSource;
291}
292
293void VideoEditorAudioPlayer::setObserver(PreviewPlayer *observer) {
294    ALOGV("setObserver");
295    //CHECK(!mStarted);
296    mObserver = observer;
297}
298
299bool VideoEditorAudioPlayer::isStarted() {
300    return mStarted;
301}
302
303// static
304void VideoEditorAudioPlayer::AudioCallback(int event, void *user, void *info) {
305    static_cast<VideoEditorAudioPlayer *>(user)->AudioCallback(event, info);
306}
307
308
309void VideoEditorAudioPlayer::AudioCallback(int event, void *info) {
310    if (event != AudioTrack::EVENT_MORE_DATA) {
311        return;
312    }
313
314    AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
315    size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
316
317    buffer->size = numBytesWritten;
318}
319
320status_t VideoEditorAudioPlayer::start(bool sourceAlreadyStarted) {
321    Mutex::Autolock autoLock(mLock);
322    CHECK(!mStarted);
323    CHECK(mSource != NULL);
324    ALOGV("Start");
325    status_t err;
326    M4OSA_ERR result = M4NO_ERROR;
327    M4OSA_UInt32 startTime = 0;
328    M4OSA_UInt32 seekTimeStamp = 0;
329    M4OSA_Bool bStoryBoardTSBeyondBTEndCutTime = M4OSA_FALSE;
330
331    if (!sourceAlreadyStarted) {
332        err = mSource->start();
333        if (err != OK) {
334            return err;
335        }
336    }
337
338    // Create the BG Audio handler
339    mAudioProcess = new VideoEditorBGAudioProcessing();
340    AudioMixSettings audioMixSettings;
341
342    // Pass on the audio ducking parameters
343    audioMixSettings.lvInDucking_threshold =
344        mAudioMixSettings->uiInDucking_threshold;
345    audioMixSettings.lvInDucking_lowVolume =
346        ((M4OSA_Float)mAudioMixSettings->uiInDucking_lowVolume) / 100.0;
347    audioMixSettings.lvInDucking_enable =
348        mAudioMixSettings->bInDucking_enable;
349    audioMixSettings.lvPTVolLevel =
350        ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal) / 100.0;
351    audioMixSettings.lvBTVolLevel =
352        ((M4OSA_Float)mAudioMixSettings->uiAddVolume) / 100.0;
353    audioMixSettings.lvBTChannelCount = mAudioMixSettings->uiBTChannelCount;
354    audioMixSettings.lvPTChannelCount = mAudioMixSettings->uiNbChannels;
355
356    // Call to Audio mix param setting
357    mAudioProcess->setMixParams(audioMixSettings);
358
359    // Get the BG Audio PCM file details
360    if ( mBGAudioPCMFileHandle ) {
361
362        // TODO : 32bits required for OSAL, to be updated once OSAL is updated
363        M4OSA_UInt32 tmp32 = 0;
364        result = M4OSA_fileReadGetOption(mBGAudioPCMFileHandle,
365                                        M4OSA_kFileReadGetFileSize,
366                                        (M4OSA_Void**)&tmp32);
367        mBGAudioPCMFileLength = tmp32;
368        mBGAudioPCMFileTrimmedLength = mBGAudioPCMFileLength;
369
370
371        ALOGV("VideoEditorAudioPlayer::start M4OSA_kFileReadGetFileSize = %lld",
372                            mBGAudioPCMFileLength);
373
374        // Get the duration in time of the audio BT
375        if ( result == M4NO_ERROR ) {
376         ALOGV("VEAP: channels = %d freq = %d",
377         mAudioMixSettings->uiNbChannels,  mAudioMixSettings->uiSamplingFrequency);
378
379            // No trim
380            mBGAudioPCMFileDuration = ((
381                    (int64_t)(mBGAudioPCMFileLength/sizeof(M4OSA_UInt16)/
382                    mAudioMixSettings->uiNbChannels))*1000 ) /
383                    mAudioMixSettings->uiSamplingFrequency;
384
385            ALOGV("VideoEditorAudioPlayer:: beginCutMs %d , endCutMs %d",
386                    (unsigned int) mAudioMixSettings->beginCutMs,
387                    (unsigned int) mAudioMixSettings->endCutMs);
388
389            // Remove the trim part
390            if ((mAudioMixSettings->beginCutMs == 0) &&
391                (mAudioMixSettings->endCutMs != 0)) {
392                // End time itself the file duration
393                mBGAudioPCMFileDuration = mAudioMixSettings->endCutMs;
394                // Limit the file length also
395                mBGAudioPCMFileTrimmedLength = ((
396                     (int64_t)(mBGAudioPCMFileDuration *
397                     mAudioMixSettings->uiSamplingFrequency) *
398                     mAudioMixSettings->uiNbChannels) *
399                     sizeof(M4OSA_UInt16)) / 1000;
400            }
401            else if ((mAudioMixSettings->beginCutMs != 0) &&
402                     (mAudioMixSettings->endCutMs == mBGAudioPCMFileDuration)) {
403                // End time itself the file duration
404                mBGAudioPCMFileDuration = mBGAudioPCMFileDuration -
405                      mAudioMixSettings->beginCutMs;
406                // Limit the file length also
407                mBGAudioPCMFileTrimmedLength = ((
408                     (int64_t)(mBGAudioPCMFileDuration *
409                     mAudioMixSettings->uiSamplingFrequency) *
410                     mAudioMixSettings->uiNbChannels) *
411                     sizeof(M4OSA_UInt16)) / 1000;
412            }
413            else if ((mAudioMixSettings->beginCutMs != 0) &&
414                    (mAudioMixSettings->endCutMs != 0)) {
415                // End time itself the file duration
416                mBGAudioPCMFileDuration = mAudioMixSettings->endCutMs -
417                    mAudioMixSettings->beginCutMs;
418                // Limit the file length also
419                mBGAudioPCMFileTrimmedLength = ((
420                    (int64_t)(mBGAudioPCMFileDuration *
421                    mAudioMixSettings->uiSamplingFrequency) *
422                    mAudioMixSettings->uiNbChannels) *
423                    sizeof(M4OSA_UInt16)) / 1000; /*make to sec from ms*/
424            }
425
426            ALOGV("VideoEditorAudioPlayer: file duration recorded : %lld",
427                    mBGAudioPCMFileDuration);
428        }
429
430        // Last played location to be seeked at for next media item
431        if ( result == M4NO_ERROR ) {
432            ALOGV("VideoEditorAudioPlayer::mBGAudioStoryBoardSkimTimeStamp %lld",
433                    mBGAudioStoryBoardSkimTimeStamp);
434            ALOGV("VideoEditorAudioPlayer::uiAddCts %d",
435                    mAudioMixSettings->uiAddCts);
436            if (mBGAudioStoryBoardSkimTimeStamp >= mAudioMixSettings->uiAddCts) {
437                startTime = (mBGAudioStoryBoardSkimTimeStamp -
438                 mAudioMixSettings->uiAddCts);
439            }
440            else {
441                // do nothing
442            }
443
444            ALOGV("VideoEditorAudioPlayer::startTime %d", startTime);
445            seekTimeStamp = 0;
446            if (startTime) {
447                if (startTime >= mBGAudioPCMFileDuration) {
448                    // The BG track should be looped and started again
449                    if (mAudioMixSettings->bLoop) {
450                        // Add begin cut time to the mod value
451                        seekTimeStamp = ((startTime%mBGAudioPCMFileDuration) +
452                        mAudioMixSettings->beginCutMs);
453                    }else {
454                        // Looping disabled, donot do BT Mix , set to file end
455                        seekTimeStamp = (mBGAudioPCMFileDuration +
456                        mAudioMixSettings->beginCutMs);
457                    }
458                }else {
459                    // BT still present , just seek to story board time
460                    seekTimeStamp = startTime + mAudioMixSettings->beginCutMs;
461                }
462            }
463            else {
464                seekTimeStamp = mAudioMixSettings->beginCutMs;
465            }
466
467            // Convert the seekTimeStamp to file location
468            mBGAudioPCMFileOriginalSeekPoint = (
469                                        (int64_t)(mAudioMixSettings->beginCutMs)
470                                        * mAudioMixSettings->uiSamplingFrequency
471                                        * mAudioMixSettings->uiNbChannels
472                                        * sizeof(M4OSA_UInt16))/ 1000 ; /*make to sec from ms*/
473
474            mBGAudioPCMFileSeekPoint = ((int64_t)(seekTimeStamp)
475                                        * mAudioMixSettings->uiSamplingFrequency
476                                        * mAudioMixSettings->uiNbChannels
477                                        * sizeof(M4OSA_UInt16))/ 1000 ;
478        }
479    }
480
481    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
482    // of playback, if there is one, getFormat below will retrieve the
483    // updated format, if there isn't, we'll stash away the valid buffer
484    // of data to be used on the first audio callback.
485
486    CHECK(mFirstBuffer == NULL);
487
488    mFirstBufferResult = mSource->read(&mFirstBuffer);
489    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
490        ALOGV("INFO_FORMAT_CHANGED!!!");
491
492        CHECK(mFirstBuffer == NULL);
493        mFirstBufferResult = OK;
494        mIsFirstBuffer = false;
495    } else {
496        mIsFirstBuffer = true;
497    }
498
499    sp<MetaData> format = mSource->getFormat();
500    const char *mime;
501    bool success = format->findCString(kKeyMIMEType, &mime);
502    CHECK(success);
503    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
504
505    success = format->findInt32(kKeySampleRate, &mSampleRate);
506    CHECK(success);
507
508    int32_t numChannels;
509    success = format->findInt32(kKeyChannelCount, &numChannels);
510    CHECK(success);
511
512    if (mAudioSink.get() != NULL) {
513        status_t err = mAudioSink->open(
514                mSampleRate, numChannels, CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT,
515                DEFAULT_AUDIOSINK_BUFFERCOUNT,
516                &VideoEditorAudioPlayer::AudioSinkCallback, this);
517        if (err != OK) {
518            if (mFirstBuffer != NULL) {
519                mFirstBuffer->release();
520                mFirstBuffer = NULL;
521            }
522
523            if (!sourceAlreadyStarted) {
524                mSource->stop();
525            }
526
527            return err;
528        }
529
530        mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
531        mFrameSize = mAudioSink->frameSize();
532
533        mAudioSink->start();
534    } else {
535        mAudioTrack = new AudioTrack(
536                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
537                audio_channel_out_mask_from_count(numChannels),
538                0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);
539
540        if ((err = mAudioTrack->initCheck()) != OK) {
541            delete mAudioTrack;
542            mAudioTrack = NULL;
543
544            if (mFirstBuffer != NULL) {
545                mFirstBuffer->release();
546                mFirstBuffer = NULL;
547            }
548
549            if (!sourceAlreadyStarted) {
550                mSource->stop();
551            }
552
553            return err;
554        }
555
556        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
557        mFrameSize = mAudioTrack->frameSize();
558
559        mAudioTrack->start();
560    }
561
562    mStarted = true;
563
564    return OK;
565}
566
567
568void VideoEditorAudioPlayer::reset() {
569
570    ALOGV("reset");
571    clear();
572
573    // Capture the current seek point
574    mBGAudioPCMFileSeekPoint = 0;
575    mBGAudioStoryBoardSkimTimeStamp =0;
576    mBGAudioStoryBoardCurrentMediaBeginCutTS=0;
577}
578
579size_t VideoEditorAudioPlayer::AudioSinkCallback(
580        MediaPlayerBase::AudioSink *audioSink,
581        void *buffer, size_t size, void *cookie) {
582    VideoEditorAudioPlayer *me = (VideoEditorAudioPlayer *)cookie;
583
584    return me->fillBuffer(buffer, size);
585}
586
587
588size_t VideoEditorAudioPlayer::fillBuffer(void *data, size_t size) {
589
590    if (mReachedEOS) {
591        return 0;
592    }
593
594    size_t size_done = 0;
595    size_t size_remaining = size;
596
597    M4OSA_ERR err = M4NO_ERROR;
598    M4AM_Buffer16 bgFrame = {NULL, 0};
599    M4AM_Buffer16 mixFrame = {NULL, 0};
600    M4AM_Buffer16 ptFrame = {NULL, 0};
601    int64_t currentSteamTS = 0;
602    int64_t startTimeForBT = 0;
603    M4OSA_Float fPTVolLevel =
604     ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal)/100;
605    M4OSA_Int16     *pPTMdata=NULL;
606    M4OSA_UInt32     uiPCMsize = 0;
607
608    bool postSeekComplete = false;
609    bool postEOS = false;
610
611    while ((size_remaining > 0)&&(err==M4NO_ERROR)) {
612        MediaSource::ReadOptions options;
613
614        {
615            Mutex::Autolock autoLock(mLock);
616            if (mSeeking) {
617                if (mIsFirstBuffer) {
618                    if (mFirstBuffer != NULL) {
619                        mFirstBuffer->release();
620                        mFirstBuffer = NULL;
621                    }
622                    mIsFirstBuffer = false;
623                }
624
625                options.setSeekTo(mSeekTimeUs);
626
627                if (mInputBuffer != NULL) {
628                    mInputBuffer->release();
629                    mInputBuffer = NULL;
630                }
631
632                mSeeking = false;
633
634                if (mObserver) {
635                    postSeekComplete = true;
636                }
637            }
638        }
639
640        if (mInputBuffer == NULL) {
641            status_t status = OK;
642
643            if (mIsFirstBuffer) {
644                mInputBuffer = mFirstBuffer;
645                mFirstBuffer = NULL;
646                status = mFirstBufferResult;
647
648                mIsFirstBuffer = false;
649            } else {
650
651                {
652                    Mutex::Autolock autoLock(mLock);
653                    status = mSource->read(&mInputBuffer, &options);
654                }
655                // Data is Primary Track, mix with background track
656                // after reading same size from Background track PCM file
657                if (status == OK)
658                {
659                    // Mix only when skim point is after startTime of BT
660                    if (((mBGAudioStoryBoardSkimTimeStamp* 1000) +
661                          (mPositionTimeMediaUs - mSeekTimeUs)) >=
662                          (int64_t)(mAudioMixSettings->uiAddCts * 1000)) {
663
664                        ALOGV("VideoEditorAudioPlayer::INSIDE MIXING");
665                        ALOGV("Checking %lld <= %lld",
666                            mBGAudioPCMFileSeekPoint-mBGAudioPCMFileOriginalSeekPoint,
667                            mBGAudioPCMFileTrimmedLength);
668
669
670                        M4OSA_Void* ptr;
671                        ptr = (M4OSA_Void*)((unsigned int)mInputBuffer->data() +
672                        mInputBuffer->range_offset());
673
674                        M4OSA_UInt32 len = mInputBuffer->range_length();
675                        M4OSA_Context fp = M4OSA_NULL;
676
677                        uiPCMsize = (mInputBuffer->range_length())/2;
678                        pPTMdata = (M4OSA_Int16*) ((uint8_t*) mInputBuffer->data()
679                                + mInputBuffer->range_offset());
680
681                        ALOGV("mix with background malloc to do len %d", len);
682
683                        bgFrame.m_dataAddress = (M4OSA_UInt16*)M4OSA_32bitAlignedMalloc( len, 1,
684                                                       (M4OSA_Char*)"bgFrame");
685                        bgFrame.m_bufferSize = len;
686
687                        mixFrame.m_dataAddress = (M4OSA_UInt16*)M4OSA_32bitAlignedMalloc(len, 1,
688                                                    (M4OSA_Char*)"mixFrame");
689                        mixFrame.m_bufferSize = len;
690
691                        ALOGV("mix with bgm with size %lld", mBGAudioPCMFileLength);
692
693                        CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime,
694                                         &mPositionTimeMediaUs));
695
696                        if (mBGAudioPCMFileSeekPoint -
697                             mBGAudioPCMFileOriginalSeekPoint <=
698                              (mBGAudioPCMFileTrimmedLength - len)) {
699
700                            ALOGV("Checking mBGAudioPCMFileHandle %d",
701                                (unsigned int)mBGAudioPCMFileHandle);
702
703                            if (mBGAudioPCMFileHandle != M4OSA_NULL) {
704                                ALOGV("fillBuffer seeking file to %lld",
705                                    mBGAudioPCMFileSeekPoint);
706
707                            // TODO : 32bits required for OSAL
708                                M4OSA_UInt32 tmp32 =
709                                    (M4OSA_UInt32)mBGAudioPCMFileSeekPoint;
710                                err = M4OSA_fileReadSeek(mBGAudioPCMFileHandle,
711                                                M4OSA_kFileSeekBeginning,
712                                                (M4OSA_FilePosition*)&tmp32);
713
714                                mBGAudioPCMFileSeekPoint = tmp32;
715
716                                if (err != M4NO_ERROR){
717                                    ALOGE("M4OSA_fileReadSeek err %d",(int)err);
718                                }
719
720                                err = M4OSA_fileReadData(mBGAudioPCMFileHandle,
721                                       (M4OSA_Int8*)bgFrame.m_dataAddress,
722                                       (M4OSA_UInt32*)&len);
723                                if (err == M4WAR_NO_DATA_YET ) {
724
725                                    ALOGV("fillBuffer End of file reached");
726                                    err = M4NO_ERROR;
727
728                                    // We reached the end of file
729                                    // move to begin cut time equal value
730                                    if (mAudioMixSettings->bLoop) {
731                                        mBGAudioPCMFileSeekPoint =
732                                         (((int64_t)(mAudioMixSettings->beginCutMs) *
733                                          mAudioMixSettings->uiSamplingFrequency) *
734                                          mAudioMixSettings->uiNbChannels *
735                                           sizeof(M4OSA_UInt16)) / 1000;
736                                        ALOGV("fillBuffer Looping \
737                                            to mBGAudioPCMFileSeekPoint %lld",
738                                            mBGAudioPCMFileSeekPoint);
739                                    }
740                                    else {
741                                            // No mixing;
742                                            // take care of volume of primary track
743                                        if (fPTVolLevel < 1.0) {
744                                            setPrimaryTrackVolume(pPTMdata,
745                                             uiPCMsize, fPTVolLevel);
746                                        }
747                                    }
748                                } else if (err != M4NO_ERROR ) {
749                                     ALOGV("fileReadData for audio err %d", err);
750                                } else {
751                                    mBGAudioPCMFileSeekPoint += len;
752                                    ALOGV("fillBuffer mBGAudioPCMFileSeekPoint \
753                                         %lld", mBGAudioPCMFileSeekPoint);
754
755                                    // Assign the ptr data to primary track
756                                    ptFrame.m_dataAddress = (M4OSA_UInt16*)ptr;
757                                    ptFrame.m_bufferSize = len;
758
759                                    // Call to mix and duck
760                                    mAudioProcess->mixAndDuck(
761                                         &ptFrame, &bgFrame, &mixFrame);
762
763                                        // Overwrite the decoded buffer
764                                    memcpy((void *)ptr,
765                                         (void *)mixFrame.m_dataAddress, len);
766                                }
767                            }
768                        } else if (mAudioMixSettings->bLoop){
769                            // Move to begin cut time equal value
770                            mBGAudioPCMFileSeekPoint =
771                                mBGAudioPCMFileOriginalSeekPoint;
772                        } else {
773                            // No mixing;
774                            // take care of volume level of primary track
775                            if(fPTVolLevel < 1.0) {
776                                setPrimaryTrackVolume(
777                                      pPTMdata, uiPCMsize, fPTVolLevel);
778                            }
779                        }
780                        if (bgFrame.m_dataAddress) {
781                            free(bgFrame.m_dataAddress);
782                        }
783                        if (mixFrame.m_dataAddress) {
784                            free(mixFrame.m_dataAddress);
785                        }
786                    } else {
787                        // No mixing;
788                        // take care of volume level of primary track
789                        if(fPTVolLevel < 1.0) {
790                            setPrimaryTrackVolume(pPTMdata, uiPCMsize,
791                                                 fPTVolLevel);
792                        }
793                    }
794                }
795            }
796
797            CHECK((status == OK && mInputBuffer != NULL)
798                   || (status != OK && mInputBuffer == NULL));
799
800            Mutex::Autolock autoLock(mLock);
801
802            if (status != OK) {
803                ALOGV("fillBuffer: mSource->read returned err %d", status);
804                if (mObserver && !mReachedEOS) {
805                    postEOS = true;
806                }
807
808                mReachedEOS = true;
809                mFinalStatus = status;
810                break;
811            }
812
813            CHECK(mInputBuffer->meta_data()->findInt64(
814                        kKeyTime, &mPositionTimeMediaUs));
815
816            mPositionTimeRealUs =
817                ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
818                    / mSampleRate;
819
820            ALOGV("buffer->size() = %d, "
821                     "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
822                 mInputBuffer->range_length(),
823                 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
824        }
825
826        if (mInputBuffer->range_length() == 0) {
827            mInputBuffer->release();
828            mInputBuffer = NULL;
829
830            continue;
831        }
832
833        size_t copy = size_remaining;
834        if (copy > mInputBuffer->range_length()) {
835            copy = mInputBuffer->range_length();
836        }
837
838        memcpy((char *)data + size_done,
839           (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
840               copy);
841
842        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
843                            mInputBuffer->range_length() - copy);
844
845        size_done += copy;
846        size_remaining -= copy;
847    }
848
849    {
850        Mutex::Autolock autoLock(mLock);
851        mNumFramesPlayed += size_done / mFrameSize;
852    }
853
854    if (postEOS) {
855        mObserver->postAudioEOS();
856    }
857
858    if (postSeekComplete) {
859        mObserver->postAudioSeekComplete();
860    }
861
862    return size_done;
863}
864
865void VideoEditorAudioPlayer::setAudioMixSettings(
866                            M4xVSS_AudioMixingSettings* pAudioMixSettings) {
867    mAudioMixSettings = pAudioMixSettings;
868}
869
870void VideoEditorAudioPlayer::setAudioMixPCMFileHandle(
871                            M4OSA_Context pBGAudioPCMFileHandle){
872    mBGAudioPCMFileHandle = pBGAudioPCMFileHandle;
873}
874
875void VideoEditorAudioPlayer::setAudioMixStoryBoardSkimTimeStamp(
876                            M4OSA_UInt32 pBGAudioStoryBoardSkimTimeStamp,
877                            M4OSA_UInt32 pBGAudioCurrentMediaBeginCutTS,
878                            M4OSA_UInt32 pBGAudioCurrentMediaVolumeVal) {
879
880    mBGAudioStoryBoardSkimTimeStamp = pBGAudioStoryBoardSkimTimeStamp;
881    mBGAudioStoryBoardCurrentMediaBeginCutTS = pBGAudioCurrentMediaBeginCutTS;
882    mBGAudioStoryBoardCurrentMediaVolumeVal = pBGAudioCurrentMediaVolumeVal;
883}
884
885void VideoEditorAudioPlayer::setPrimaryTrackVolume(
886    M4OSA_Int16 *data, M4OSA_UInt32 size, M4OSA_Float volLevel) {
887
888    while(size-- > 0) {
889        *data = (M4OSA_Int16)((*data)*volLevel);
890        data++;
891    }
892}
893
894}
895