VideoEditorAudioPlayer.cpp revision 5df818550a13d5bd21798badcb413e7a945e15e8
1/*
2 * Copyright (C) 2011 NXP Software
3 * Copyright (C) 2011 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#define LOG_NDEBUG 1
19#define LOG_TAG "VideoEditorAudioPlayer"
20#include <utils/Log.h>
21
22#include <binder/IPCThreadState.h>
23#include <media/AudioTrack.h>
24#include <VideoEditorAudioPlayer.h>
25#include <media/stagefright/MediaDebug.h>
26#include <media/stagefright/MediaDefs.h>
27#include <media/stagefright/MediaErrors.h>
28#include <media/stagefright/MediaSource.h>
29#include <media/stagefright/MetaData.h>
30
31#include "PreviewPlayer.h"
32namespace android {
33
34VideoEditorAudioPlayer::VideoEditorAudioPlayer(
35        const sp<MediaPlayerBase::AudioSink> &audioSink,
36        AwesomePlayer *observer)
37    : AudioPlayer(audioSink, observer) {
38
39    LOGV("VideoEditorAudioPlayer");
40    mBGAudioPCMFileHandle = NULL;
41    mBGAudioPCMFileLength = 0;
42    mBGAudioPCMFileTrimmedLength = 0;
43    mBGAudioPCMFileDuration = 0;
44    mBGAudioPCMFileSeekPoint = 0;
45    mBGAudioPCMFileOriginalSeekPoint = 0;
46    mBGAudioStoryBoardSkimTimeStamp = 0;
47    mBGAudioStoryBoardCurrentMediaBeginCutTS = 0;
48    mBGAudioStoryBoardCurrentMediaVolumeVal = 0;
49    mSeekTimeUs = 0;
50}
51
52VideoEditorAudioPlayer::~VideoEditorAudioPlayer() {
53
54    LOGV("~VideoEditorAudioPlayer");
55    if (mStarted) {
56        reset();
57    }
58    if (mAudioProcess != NULL) {
59        delete mAudioProcess;
60        mAudioProcess = NULL;
61    }
62}
63
64status_t VideoEditorAudioPlayer::start(bool sourceAlreadyStarted) {
65
66    CHECK(!mStarted);
67    CHECK(mSource != NULL);
68    LOGV("Start");
69    status_t err;
70    M4OSA_ERR result = M4NO_ERROR;
71    M4OSA_UInt32 startTime = 0;
72    M4OSA_UInt32 seekTimeStamp = 0;
73    M4OSA_Bool bStoryBoardTSBeyondBTEndCutTime = M4OSA_FALSE;
74
75    if (!sourceAlreadyStarted) {
76        err = mSource->start();
77        if (err != OK) {
78            return err;
79        }
80    }
81
82    // Create the BG Audio handler
83    mAudioProcess = new VideoEditorBGAudioProcessing();
84    veAudMixSettings audioMixSettings;
85
86    // Pass on the audio ducking parameters
87    audioMixSettings.lvInDucking_threshold = mAudioMixSettings->uiInDucking_threshold;
88    audioMixSettings.lvInDucking_lowVolume = ((M4OSA_Float)mAudioMixSettings->uiInDucking_lowVolume) / 100.0;
89    audioMixSettings.lvInDucking_enable = mAudioMixSettings->bInDucking_enable;
90    audioMixSettings.lvPTVolLevel = ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal) / 100.0;
91    audioMixSettings.lvBTVolLevel = ((M4OSA_Float)mAudioMixSettings->uiAddVolume) /100.0;
92    audioMixSettings.lvBTChannelCount = mAudioMixSettings->uiBTChannelCount;
93    audioMixSettings.lvPTChannelCount = mAudioMixSettings->uiNbChannels;
94
95    // Call to Audio mix param setting
96    mAudioProcess->veSetAudioProcessingParams(audioMixSettings);
97
98    // Get the BG Audio PCM file details
99    if ( mBGAudioPCMFileHandle ) {
100
101        // TODO : 32bits required for OSAL, to be updated once OSAL is updated
102        M4OSA_UInt32 tmp32 = 0;
103        result = M4OSA_fileReadGetOption(mBGAudioPCMFileHandle,
104                                        M4OSA_kFileReadGetFileSize,
105                                        (M4OSA_Void**)&tmp32);
106        mBGAudioPCMFileLength = tmp32;
107        mBGAudioPCMFileTrimmedLength = mBGAudioPCMFileLength;
108
109
110        LOGV("VideoEditorAudioPlayer::start M4OSA_kFileReadGetFileSize = %lld",
111                            mBGAudioPCMFileLength);
112
113        // Get the duration in time of the audio BT
114        if ( result == M4NO_ERROR ) {
115         LOGV("VEAP: channels = %d freq = %d",
116         mAudioMixSettings->uiNbChannels,  mAudioMixSettings->uiSamplingFrequency);
117
118            // No trim
119            mBGAudioPCMFileDuration = ((
120                    (int64_t)(mBGAudioPCMFileLength/sizeof(M4OSA_UInt16)/
121                    mAudioMixSettings->uiNbChannels))*1000 ) /
122                    mAudioMixSettings->uiSamplingFrequency;
123
124            LOGV("VideoEditorAudioPlayer:: beginCutMs %d , endCutMs %d",
125                    (unsigned int) mAudioMixSettings->beginCutMs,
126                    (unsigned int) mAudioMixSettings->endCutMs);
127
128            // Remove the trim part
129            if ((mAudioMixSettings->beginCutMs == 0) &&
130                (mAudioMixSettings->endCutMs != 0)) {
131                // End time itself the file duration
132                mBGAudioPCMFileDuration = mAudioMixSettings->endCutMs;
133                // Limit the file length also
134                mBGAudioPCMFileTrimmedLength = ((
135                     (int64_t)(mBGAudioPCMFileDuration *
136                     mAudioMixSettings->uiSamplingFrequency) *
137                     mAudioMixSettings->uiNbChannels) *
138                     sizeof(M4OSA_UInt16)) / 1000;
139            }
140            else if ((mAudioMixSettings->beginCutMs != 0) &&
141                     (mAudioMixSettings->endCutMs == mBGAudioPCMFileDuration)) {
142                // End time itself the file duration
143                mBGAudioPCMFileDuration = mBGAudioPCMFileDuration -
144                      mAudioMixSettings->beginCutMs;
145                // Limit the file length also
146                mBGAudioPCMFileTrimmedLength = ((
147                     (int64_t)(mBGAudioPCMFileDuration *
148                     mAudioMixSettings->uiSamplingFrequency) *
149                     mAudioMixSettings->uiNbChannels) *
150                     sizeof(M4OSA_UInt16)) / 1000;
151            }
152            else if ((mAudioMixSettings->beginCutMs != 0) &&
153                    (mAudioMixSettings->endCutMs != 0)) {
154                // End time itself the file duration
155                mBGAudioPCMFileDuration = mAudioMixSettings->endCutMs -
156                    mAudioMixSettings->beginCutMs;
157                // Limit the file length also
158                mBGAudioPCMFileTrimmedLength = ((
159                    (int64_t)(mBGAudioPCMFileDuration *
160                    mAudioMixSettings->uiSamplingFrequency) *
161                    mAudioMixSettings->uiNbChannels) *
162                    sizeof(M4OSA_UInt16)) / 1000; /*make to sec from ms*/
163            }
164
165            LOGV("VideoEditorAudioPlayer: file duration recorded : %lld",
166                    mBGAudioPCMFileDuration);
167        }
168
169        // Last played location to be seeked at for next media item
170        if ( result == M4NO_ERROR ) {
171            LOGV("VideoEditorAudioPlayer::mBGAudioStoryBoardSkimTimeStamp %lld",
172                    mBGAudioStoryBoardSkimTimeStamp);
173            LOGV("VideoEditorAudioPlayer::uiAddCts %d",
174                    mAudioMixSettings->uiAddCts);
175            if (mBGAudioStoryBoardSkimTimeStamp >= mAudioMixSettings->uiAddCts) {
176                startTime = (mBGAudioStoryBoardSkimTimeStamp -
177                 mAudioMixSettings->uiAddCts);
178            }
179            else {
180                // do nothing
181            }
182
183            LOGV("VideoEditorAudioPlayer::startTime %d", startTime);
184            seekTimeStamp = 0;
185            if (startTime) {
186                if (startTime >= mBGAudioPCMFileDuration) {
187                    // The BG track should be looped and started again
188                    if (mAudioMixSettings->bLoop) {
189                        // Add begin cut time to the mod value
190                        seekTimeStamp = ((startTime%mBGAudioPCMFileDuration) +
191                        mAudioMixSettings->beginCutMs);
192                    }else {
193                        // Looping disabled, donot do BT Mix , set to file end
194                        seekTimeStamp = (mBGAudioPCMFileDuration +
195                        mAudioMixSettings->beginCutMs);
196                    }
197                }else {
198                    // BT still present , just seek to story board time
199                    seekTimeStamp = startTime + mAudioMixSettings->beginCutMs;
200                }
201            }
202            else {
203                seekTimeStamp = mAudioMixSettings->beginCutMs;
204            }
205
206            // Convert the seekTimeStamp to file location
207            mBGAudioPCMFileOriginalSeekPoint = (
208                                        (int64_t)(mAudioMixSettings->beginCutMs)
209                                        * mAudioMixSettings->uiSamplingFrequency
210                                        * mAudioMixSettings->uiNbChannels
211                                        * sizeof(M4OSA_UInt16))/ 1000 ; /*make to sec from ms*/
212
213            mBGAudioPCMFileSeekPoint = ((int64_t)(seekTimeStamp)
214                                        * mAudioMixSettings->uiSamplingFrequency
215                                        * mAudioMixSettings->uiNbChannels
216                                        * sizeof(M4OSA_UInt16))/ 1000 ;
217        }
218    }
219
220    // We allow an optional INFO_FORMAT_CHANGED at the very beginning
221    // of playback, if there is one, getFormat below will retrieve the
222    // updated format, if there isn't, we'll stash away the valid buffer
223    // of data to be used on the first audio callback.
224
225    CHECK(mFirstBuffer == NULL);
226
227    mFirstBufferResult = mSource->read(&mFirstBuffer);
228    if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
229        LOGV("INFO_FORMAT_CHANGED!!!");
230
231        CHECK(mFirstBuffer == NULL);
232        mFirstBufferResult = OK;
233        mIsFirstBuffer = false;
234    } else {
235        mIsFirstBuffer = true;
236    }
237
238    sp<MetaData> format = mSource->getFormat();
239    const char *mime;
240    bool success = format->findCString(kKeyMIMEType, &mime);
241    CHECK(success);
242    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
243
244    success = format->findInt32(kKeySampleRate, &mSampleRate);
245    CHECK(success);
246
247    int32_t numChannels;
248    success = format->findInt32(kKeyChannelCount, &numChannels);
249    CHECK(success);
250
251    if (mAudioSink.get() != NULL) {
252        status_t err = mAudioSink->open(
253                mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
254                DEFAULT_AUDIOSINK_BUFFERCOUNT,
255                &VideoEditorAudioPlayer::AudioSinkCallback, this);
256        if (err != OK) {
257            if (mFirstBuffer != NULL) {
258                mFirstBuffer->release();
259                mFirstBuffer = NULL;
260            }
261
262            if (!sourceAlreadyStarted) {
263                mSource->stop();
264            }
265
266            return err;
267        }
268
269        mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
270        mFrameSize = mAudioSink->frameSize();
271
272        mAudioSink->start();
273    } else {
274        mAudioTrack = new AudioTrack(
275                AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
276                (numChannels == 2)
277                    ? AudioSystem::CHANNEL_OUT_STEREO
278                    : AudioSystem::CHANNEL_OUT_MONO,
279                0, 0, &AudioCallback, this, 0);
280
281        if ((err = mAudioTrack->initCheck()) != OK) {
282            delete mAudioTrack;
283            mAudioTrack = NULL;
284
285            if (mFirstBuffer != NULL) {
286                mFirstBuffer->release();
287                mFirstBuffer = NULL;
288            }
289
290            if (!sourceAlreadyStarted) {
291                mSource->stop();
292            }
293
294            return err;
295        }
296
297        mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
298        mFrameSize = mAudioTrack->frameSize();
299
300        mAudioTrack->start();
301    }
302
303    mStarted = true;
304
305    return OK;
306}
307
308void VideoEditorAudioPlayer::reset() {
309
310    LOGV("reset");
311    AudioPlayer::reset();
312
313    // Capture the current seek point
314    mBGAudioPCMFileSeekPoint = 0;
315    mBGAudioStoryBoardSkimTimeStamp =0;
316    mBGAudioStoryBoardCurrentMediaBeginCutTS=0;
317}
318
319size_t VideoEditorAudioPlayer::AudioSinkCallback(
320        MediaPlayerBase::AudioSink *audioSink,
321        void *buffer, size_t size, void *cookie) {
322    VideoEditorAudioPlayer *me = (VideoEditorAudioPlayer *)cookie;
323
324    return me->fillBuffer(buffer, size);
325}
326
327
328size_t VideoEditorAudioPlayer::fillBuffer(void *data, size_t size) {
329
330    if (mReachedEOS) {
331        return 0;
332    }
333
334    size_t size_done = 0;
335    size_t size_remaining = size;
336
337    M4OSA_ERR err = M4NO_ERROR;
338    M4AM_Buffer bgFrame = {NULL, 0};
339    M4AM_Buffer mixFrame = {NULL, 0};
340    M4AM_Buffer ptFrame = {NULL, 0};
341    int64_t currentSteamTS = 0;
342    int64_t startTimeForBT = 0;
343    M4OSA_Float fPTVolLevel =
344     ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal)/100;
345    M4OSA_Int16     *pPTMdata;
346    M4OSA_UInt32     uiPCMsize = 0;
347
348    while ((size_remaining > 0)&&(err==M4NO_ERROR)) {
349        MediaSource::ReadOptions options;
350
351        {
352            Mutex::Autolock autoLock(mLock);
353            if (mSeeking) {
354                if (mIsFirstBuffer) {
355                    if (mFirstBuffer != NULL) {
356                        mFirstBuffer->release();
357                        mFirstBuffer = NULL;
358                    }
359                    mIsFirstBuffer = false;
360                }
361
362                options.setSeekTo(mSeekTimeUs);
363
364                if (mInputBuffer != NULL) {
365                    mInputBuffer->release();
366                    mInputBuffer = NULL;
367                }
368
369                mSeeking = false;
370                if (mObserver) {
371                    mObserver->postAudioSeekComplete();
372                }
373            }
374        }
375
376        if (mInputBuffer == NULL) {
377            status_t status = OK;
378
379            if (mIsFirstBuffer) {
380                mInputBuffer = mFirstBuffer;
381                mFirstBuffer = NULL;
382                status = mFirstBufferResult;
383
384                mIsFirstBuffer = false;
385            } else {
386                status = mSource->read(&mInputBuffer, &options);
387                // Data is Primary Track, mix with background track
388                // after reading same size from Background track PCM file
389                if (status == OK)
390                {
391                    // Mix only when skim point is after startTime of BT
392                    if (((mBGAudioStoryBoardSkimTimeStamp* 1000) +
393                          (mPositionTimeMediaUs - mSeekTimeUs)) >=
394                          (int64_t)(mAudioMixSettings->uiAddCts * 1000)) {
395
396                        LOGV("VideoEditorAudioPlayer::INSIDE MIXING");
397                        LOGV("Checking %lld <= %lld - %d",
398                            mBGAudioPCMFileSeekPoint-mBGAudioPCMFileOriginalSeekPoint,
399                            mBGAudioPCMFileTrimmedLength, len);
400
401
402                        M4OSA_Void* ptr;
403                        ptr = (M4OSA_Void*)((unsigned int)mInputBuffer->data() +
404                        mInputBuffer->range_offset());
405
406                        M4OSA_UInt32 len = mInputBuffer->range_length();
407                        M4OSA_Context fp = M4OSA_NULL;
408
409                        uiPCMsize = (mInputBuffer->range_length())/2;
410                        pPTMdata = (M4OSA_Int16*) ((uint8_t*) mInputBuffer->data()
411                                + mInputBuffer->range_offset());
412
413                        LOGV("mix with background malloc to do len %d", len);
414
415                        bgFrame.m_dataAddress = (M4OSA_UInt16*)M4OSA_malloc( len, 1,
416                                                       (M4OSA_Char*)"bgFrame");
417                        if (NULL == bgFrame.m_dataAddress) {
418                            LOGE("mBackgroundAudioSetting Malloc failed");
419                        }
420
421                        bgFrame.m_bufferSize = len;
422
423                        mixFrame.m_dataAddress = (M4OSA_UInt16*)M4OSA_malloc(len, 1,
424                                                    (M4OSA_Char*)"mixFrame");
425                        if (NULL == mixFrame.m_dataAddress) {
426                            LOGE("mBackgroundAudioSetting Malloc failed");
427                        }
428
429                        mixFrame.m_bufferSize = len;
430
431                        LOGV("mix with bgm with size %lld", mBGAudioPCMFileLength);
432
433                        CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime,
434                                         &mPositionTimeMediaUs));
435
436                        if (mBGAudioPCMFileSeekPoint -
437                             mBGAudioPCMFileOriginalSeekPoint <=
438                              (mBGAudioPCMFileTrimmedLength - len)) {
439
440                            LOGV("Checking mBGAudioPCMFileHandle %d",
441                                (unsigned int)mBGAudioPCMFileHandle);
442
443                            if (mBGAudioPCMFileHandle != M4OSA_NULL) {
444                                LOGV("fillBuffer seeking file to %lld",
445                                    mBGAudioPCMFileSeekPoint);
446
447                            // TODO : 32bits required for OSAL
448                                M4OSA_UInt32 tmp32 =
449                                    (M4OSA_UInt32)mBGAudioPCMFileSeekPoint;
450                                err = M4OSA_fileReadSeek(mBGAudioPCMFileHandle,
451                                                M4OSA_kFileSeekBeginning,
452                                                (M4OSA_FilePosition*)&tmp32);
453
454                                mBGAudioPCMFileSeekPoint = tmp32;
455
456                                if (err != M4NO_ERROR){
457                                    LOGE("M4OSA_fileReadSeek err %d", err);
458                                }
459
460                                err = M4OSA_fileReadData(mBGAudioPCMFileHandle,
461                                       (M4OSA_Int8*)bgFrame.m_dataAddress,
462                                       (M4OSA_UInt32*)&len);
463                                if (err == M4WAR_NO_DATA_YET ) {
464
465                                    LOGV("fillBuffer End of file reached");
466                                    err = M4NO_ERROR;
467
468                                    // We reached the end of file
469                                    // move to begin cut time equal value
470                                    if (mAudioMixSettings->bLoop) {
471                                        mBGAudioPCMFileSeekPoint =
472                                         (((int64_t)(mAudioMixSettings->beginCutMs) *
473                                          mAudioMixSettings->uiSamplingFrequency) *
474                                          mAudioMixSettings->uiNbChannels *
475                                           sizeof(M4OSA_UInt16)) / 1000;
476                                        LOGV("fillBuffer Looping \
477                                            to mBGAudioPCMFileSeekPoint %lld",
478                                            mBGAudioPCMFileSeekPoint);
479                                    }
480                                    else {
481                                            // No mixing;
482                                            // take care of volume of primary track
483                                        if (fPTVolLevel < 1.0) {
484                                            setPrimaryTrackVolume(pPTMdata,
485                                             uiPCMsize, fPTVolLevel);
486                                        }
487                                    }
488                                } else if (err != M4NO_ERROR ) {
489                                     LOGV("fileReadData for audio err %d", err);
490                                } else {
491                                    mBGAudioPCMFileSeekPoint += len;
492                                    LOGV("fillBuffer mBGAudioPCMFileSeekPoint \
493                                         %lld", mBGAudioPCMFileSeekPoint);
494
495                                    // Assign the ptr data to primary track
496                                    ptFrame.m_dataAddress = (M4OSA_UInt16*)ptr;
497                                    ptFrame.m_bufferSize = len;
498
499                                    // Call to mix and duck
500                                    mAudioProcess->veProcessAudioMixNDuck(
501                                         &ptFrame, &bgFrame, &mixFrame);
502
503                                        // Overwrite the decoded buffer
504                                    M4OSA_memcpy((M4OSA_MemAddr8)ptr,
505                                         (M4OSA_MemAddr8)mixFrame.m_dataAddress, len);
506                                }
507                            }
508                        } else if (mAudioMixSettings->bLoop){
509                            // Move to begin cut time equal value
510                            mBGAudioPCMFileSeekPoint =
511                                mBGAudioPCMFileOriginalSeekPoint;
512                        } else {
513                            // No mixing;
514                            // take care of volume level of primary track
515                            if(fPTVolLevel < 1.0) {
516                                setPrimaryTrackVolume(
517                                      pPTMdata, uiPCMsize, fPTVolLevel);
518                            }
519                        }
520                        if (bgFrame.m_dataAddress) {
521                            M4OSA_free((M4OSA_MemAddr32)bgFrame.m_dataAddress);
522                        }
523                        if (mixFrame.m_dataAddress) {
524                            M4OSA_free((M4OSA_MemAddr32)mixFrame.m_dataAddress);
525                        }
526                    } else {
527                        // No mixing;
528                        // take care of volume level of primary track
529                        if(fPTVolLevel < 1.0) {
530                            setPrimaryTrackVolume(pPTMdata, uiPCMsize,
531                                                 fPTVolLevel);
532                        }
533                    }
534                }
535            }
536
537            CHECK((status == OK && mInputBuffer != NULL)
538                   || (status != OK && mInputBuffer == NULL));
539
540            Mutex::Autolock autoLock(mLock);
541
542            if (status != OK) {
543                LOGV("fillBuffer: mSource->read returned err %d", status);
544                if (mObserver && !mReachedEOS) {
545                    mObserver->postAudioEOS();
546                }
547
548                mReachedEOS = true;
549                mFinalStatus = status;
550                break;
551            }
552
553            CHECK(mInputBuffer->meta_data()->findInt64(
554                        kKeyTime, &mPositionTimeMediaUs));
555
556            mPositionTimeRealUs =
557                ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
558                    / mSampleRate;
559
560            LOGV("buffer->size() = %d, "
561                     "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
562                 mInputBuffer->range_length(),
563                 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
564        }
565
566        if (mInputBuffer->range_length() == 0) {
567            mInputBuffer->release();
568            mInputBuffer = NULL;
569
570            continue;
571        }
572
573        size_t copy = size_remaining;
574        if (copy > mInputBuffer->range_length()) {
575            copy = mInputBuffer->range_length();
576        }
577
578        memcpy((char *)data + size_done,
579           (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
580               copy);
581
582        mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
583                            mInputBuffer->range_length() - copy);
584
585        size_done += copy;
586        size_remaining -= copy;
587    }
588
589    Mutex::Autolock autoLock(mLock);
590    mNumFramesPlayed += size_done / mFrameSize;
591
592    return size_done;
593}
594
595void VideoEditorAudioPlayer::setAudioMixSettings(
596                            M4xVSS_AudioMixingSettings* pAudioMixSettings) {
597    mAudioMixSettings = pAudioMixSettings;
598}
599
600void VideoEditorAudioPlayer::setAudioMixPCMFileHandle(
601                            M4OSA_Context pBGAudioPCMFileHandle){
602    mBGAudioPCMFileHandle = pBGAudioPCMFileHandle;
603}
604
605void VideoEditorAudioPlayer::setAudioMixStoryBoardSkimTimeStamp(
606                            M4OSA_UInt32 pBGAudioStoryBoardSkimTimeStamp,
607                            M4OSA_UInt32 pBGAudioCurrentMediaBeginCutTS,
608                            M4OSA_UInt32 pBGAudioCurrentMediaVolumeVal) {
609
610    mBGAudioStoryBoardSkimTimeStamp = pBGAudioStoryBoardSkimTimeStamp;
611    mBGAudioStoryBoardCurrentMediaBeginCutTS = pBGAudioCurrentMediaBeginCutTS;
612    mBGAudioStoryBoardCurrentMediaVolumeVal = pBGAudioCurrentMediaVolumeVal;
613}
614
615void VideoEditorAudioPlayer::setPrimaryTrackVolume(
616    M4OSA_Int16 *data, M4OSA_UInt32 size, M4OSA_Float volLevel) {
617
618    while(size-- > 0) {
619        *data = (M4OSA_Int16)((*data)*volLevel);
620        data++;
621    }
622}
623
624}
625