blob: 3fa8b87a6a43fc56d2e5b36bed15208b3f035514 [file] [log] [blame]
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001/*
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08002 * 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>
James Dongc4689fa2012-02-08 13:51:46 -080024#include <media/stagefright/foundation/ADebug.h>
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080025#include <media/stagefright/MediaDefs.h>
26#include <media/stagefright/MediaErrors.h>
27#include <media/stagefright/MediaSource.h>
28#include <media/stagefright/MetaData.h>
29
Dima Zavin272eb552011-05-11 14:15:37 -070030#include <system/audio.h>
Dima Zavin68598372011-04-05 16:13:49 -070031
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080032#include "PreviewPlayer.h"
33namespace android {
34
35VideoEditorAudioPlayer::VideoEditorAudioPlayer(
36 const sp<MediaPlayerBase::AudioSink> &audioSink,
James Dong00f742c2012-01-13 17:34:42 -080037 PreviewPlayer *observer)
Glenn Kasten2799d742013-05-30 14:33:29 -070038 : mInputBuffer(NULL),
James Dong727f9e12012-01-20 13:09:13 -080039 mSampleRate(0),
40 mLatencyUs(0),
41 mFrameSize(0),
42 mNumFramesPlayed(0),
43 mPositionTimeMediaUs(-1),
44 mPositionTimeRealUs(-1),
45 mSeeking(false),
46 mReachedEOS(false),
47 mFinalStatus(OK),
48 mStarted(false),
49 mIsFirstBuffer(false),
50 mFirstBufferResult(OK),
51 mFirstBuffer(NULL),
52 mAudioSink(audioSink),
53 mObserver(observer) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080054
James Dong727f9e12012-01-20 13:09:13 -080055 ALOGV("Constructor");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080056 mBGAudioPCMFileHandle = NULL;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -080057 mAudioProcess = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080058 mBGAudioPCMFileLength = 0;
59 mBGAudioPCMFileTrimmedLength = 0;
60 mBGAudioPCMFileDuration = 0;
61 mBGAudioPCMFileSeekPoint = 0;
62 mBGAudioPCMFileOriginalSeekPoint = 0;
63 mBGAudioStoryBoardSkimTimeStamp = 0;
64 mBGAudioStoryBoardCurrentMediaBeginCutTS = 0;
65 mBGAudioStoryBoardCurrentMediaVolumeVal = 0;
66 mSeekTimeUs = 0;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -080067 mSource = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080068}
69
70VideoEditorAudioPlayer::~VideoEditorAudioPlayer() {
71
James Dong727f9e12012-01-20 13:09:13 -080072 ALOGV("Destructor");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080073 if (mStarted) {
74 reset();
75 }
Santosh Madhava5df81852011-02-11 00:43:26 -080076 if (mAudioProcess != NULL) {
77 delete mAudioProcess;
78 mAudioProcess = NULL;
79 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080080}
James Dong727f9e12012-01-20 13:09:13 -080081
82void VideoEditorAudioPlayer::pause(bool playPendingSamples) {
83 ALOGV("pause: playPendingSamples=%d", playPendingSamples);
84 CHECK(mStarted);
85
86 if (playPendingSamples) {
87 if (mAudioSink.get() != NULL) {
88 mAudioSink->stop();
89 } else {
90 mAudioTrack->stop();
91 }
92 } else {
93 if (mAudioSink.get() != NULL) {
94 mAudioSink->pause();
95 } else {
96 mAudioTrack->pause();
97 }
98 }
99}
100
101void VideoEditorAudioPlayer::clear() {
102 ALOGV("clear");
103 if (!mStarted) {
104 return;
105 }
106
107 if (mAudioSink.get() != NULL) {
108 mAudioSink->stop();
109 mAudioSink->close();
110 } else {
111 mAudioTrack->stop();
112
Glenn Kasten2799d742013-05-30 14:33:29 -0700113 mAudioTrack.clear();
James Dong727f9e12012-01-20 13:09:13 -0800114 }
115
116 // Make sure to release any buffer we hold onto so that the
117 // source is able to stop().
118
119 if (mFirstBuffer != NULL) {
120 mFirstBuffer->release();
121 mFirstBuffer = NULL;
122 }
123
124 if (mInputBuffer != NULL) {
125 ALOGV("AudioPlayerBase releasing input buffer.");
126
127 mInputBuffer->release();
128 mInputBuffer = NULL;
129 }
130
131 mSource->stop();
132
133 // The following hack is necessary to ensure that the OMX
134 // component is completely released by the time we may try
135 // to instantiate it again.
136 wp<MediaSource> tmp = mSource;
137 mSource.clear();
138 while (tmp.promote() != NULL) {
139 usleep(1000);
140 }
141 IPCThreadState::self()->flushCommands();
142
143 mNumFramesPlayed = 0;
144 mPositionTimeMediaUs = -1;
145 mPositionTimeRealUs = -1;
146 mSeeking = false;
147 mReachedEOS = false;
148 mFinalStatus = OK;
149 mStarted = false;
150}
151
152void VideoEditorAudioPlayer::resume() {
153 ALOGV("resume");
154
James Dong3bd45592012-01-20 19:28:01 -0800155 AudioMixSettings audioMixSettings;
James Dong727f9e12012-01-20 13:09:13 -0800156
157 // Single audio player is used;
158 // Pass on the audio ducking parameters
159 // which might have changed with new audio source
160 audioMixSettings.lvInDucking_threshold =
161 mAudioMixSettings->uiInDucking_threshold;
162 audioMixSettings.lvInDucking_lowVolume =
163 ((M4OSA_Float)mAudioMixSettings->uiInDucking_lowVolume) / 100.0;
164 audioMixSettings.lvInDucking_enable =
165 mAudioMixSettings->bInDucking_enable;
166 audioMixSettings.lvPTVolLevel =
167 ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal) / 100.0;
168 audioMixSettings.lvBTVolLevel =
169 ((M4OSA_Float)mAudioMixSettings->uiAddVolume) / 100.0;
170 audioMixSettings.lvBTChannelCount = mAudioMixSettings->uiBTChannelCount;
171 audioMixSettings.lvPTChannelCount = mAudioMixSettings->uiNbChannels;
172
173 // Call to Audio mix param setting
James Dong3bd45592012-01-20 19:28:01 -0800174 mAudioProcess->setMixParams(audioMixSettings);
James Dong727f9e12012-01-20 13:09:13 -0800175
176 CHECK(mStarted);
177
178 if (mAudioSink.get() != NULL) {
179 mAudioSink->start();
180 } else {
181 mAudioTrack->start();
182 }
183}
184
185status_t VideoEditorAudioPlayer::seekTo(int64_t time_us) {
186 ALOGV("seekTo: %lld", time_us);
187 Mutex::Autolock autoLock(mLock);
188
189 mSeeking = true;
190 mPositionTimeRealUs = mPositionTimeMediaUs = -1;
191 mReachedEOS = false;
192 mSeekTimeUs = time_us;
193
194 if (mAudioSink != NULL) {
195 mAudioSink->flush();
196 } else {
197 mAudioTrack->flush();
198 }
199
200 return OK;
201}
202
203bool VideoEditorAudioPlayer::isSeeking() {
204 Mutex::Autolock lock(mLock);
205 ALOGV("isSeeking: mSeeking=%d", mSeeking);
206 return mSeeking;
207}
208
209bool VideoEditorAudioPlayer::reachedEOS(status_t *finalStatus) {
210 ALOGV("reachedEOS: status=%d", mFinalStatus);
211 *finalStatus = OK;
212
213 Mutex::Autolock autoLock(mLock);
214 *finalStatus = mFinalStatus;
215 return mReachedEOS;
216}
217
218int64_t VideoEditorAudioPlayer::getRealTimeUs() {
219 Mutex::Autolock autoLock(mLock);
220 return getRealTimeUs_l();
221}
222
223int64_t VideoEditorAudioPlayer::getRealTimeUs_l() {
224 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
225}
226
227int64_t VideoEditorAudioPlayer::getMediaTimeUs() {
228 ALOGV("getMediaTimeUs");
229 Mutex::Autolock autoLock(mLock);
230
231 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
232 if (mSeeking) {
233 return mSeekTimeUs;
234 }
235
236 return 0;
237 }
238
239 int64_t realTimeOffset = getRealTimeUs_l() - mPositionTimeRealUs;
240 if (realTimeOffset < 0) {
241 realTimeOffset = 0;
242 }
243
244 return mPositionTimeMediaUs + realTimeOffset;
245}
246
247bool VideoEditorAudioPlayer::getMediaTimeMapping(
248 int64_t *realtime_us, int64_t *mediatime_us) {
249 ALOGV("getMediaTimeMapping");
250 Mutex::Autolock autoLock(mLock);
251
252 *realtime_us = mPositionTimeRealUs;
253 *mediatime_us = mPositionTimeMediaUs;
254
255 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
256}
257
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800258void VideoEditorAudioPlayer::setSource(const sp<MediaSource> &source) {
259 Mutex::Autolock autoLock(mLock);
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800260
261 // Before setting source, stop any existing source.
262 // Make sure to release any buffer we hold onto so that the
263 // source is able to stop().
264
265 if (mFirstBuffer != NULL) {
266 mFirstBuffer->release();
267 mFirstBuffer = NULL;
268 }
269
270 if (mInputBuffer != NULL) {
Steve Block2703f232011-10-20 11:56:09 +0100271 ALOGV("VideoEditorAudioPlayer releasing input buffer.");
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800272
273 mInputBuffer->release();
274 mInputBuffer = NULL;
275 }
276
277 if (mSource != NULL) {
278 mSource->stop();
279 mSource.clear();
280 }
281
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800282 mSource = source;
283 mReachedEOS = false;
284}
285
286sp<MediaSource> VideoEditorAudioPlayer::getSource() {
287 Mutex::Autolock autoLock(mLock);
288 return mSource;
289}
290
James Dong00f742c2012-01-13 17:34:42 -0800291void VideoEditorAudioPlayer::setObserver(PreviewPlayer *observer) {
Steve Block2703f232011-10-20 11:56:09 +0100292 ALOGV("setObserver");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800293 //CHECK(!mStarted);
294 mObserver = observer;
295}
296
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800297bool VideoEditorAudioPlayer::isStarted() {
298 return mStarted;
299}
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800300
James Dong727f9e12012-01-20 13:09:13 -0800301// static
302void VideoEditorAudioPlayer::AudioCallback(int event, void *user, void *info) {
303 static_cast<VideoEditorAudioPlayer *>(user)->AudioCallback(event, info);
304}
305
306
307void VideoEditorAudioPlayer::AudioCallback(int event, void *info) {
308 if (event != AudioTrack::EVENT_MORE_DATA) {
309 return;
310 }
311
312 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
313 size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
314
315 buffer->size = numBytesWritten;
316}
317
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800318status_t VideoEditorAudioPlayer::start(bool sourceAlreadyStarted) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800319 Mutex::Autolock autoLock(mLock);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800320 CHECK(!mStarted);
321 CHECK(mSource != NULL);
Steve Block2703f232011-10-20 11:56:09 +0100322 ALOGV("Start");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800323 status_t err;
324 M4OSA_ERR result = M4NO_ERROR;
325 M4OSA_UInt32 startTime = 0;
326 M4OSA_UInt32 seekTimeStamp = 0;
327 M4OSA_Bool bStoryBoardTSBeyondBTEndCutTime = M4OSA_FALSE;
328
329 if (!sourceAlreadyStarted) {
330 err = mSource->start();
331 if (err != OK) {
332 return err;
333 }
334 }
335
336 // Create the BG Audio handler
337 mAudioProcess = new VideoEditorBGAudioProcessing();
James Dong3bd45592012-01-20 19:28:01 -0800338 AudioMixSettings audioMixSettings;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800339
340 // Pass on the audio ducking parameters
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800341 audioMixSettings.lvInDucking_threshold =
342 mAudioMixSettings->uiInDucking_threshold;
343 audioMixSettings.lvInDucking_lowVolume =
344 ((M4OSA_Float)mAudioMixSettings->uiInDucking_lowVolume) / 100.0;
345 audioMixSettings.lvInDucking_enable =
346 mAudioMixSettings->bInDucking_enable;
347 audioMixSettings.lvPTVolLevel =
348 ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal) / 100.0;
349 audioMixSettings.lvBTVolLevel =
350 ((M4OSA_Float)mAudioMixSettings->uiAddVolume) / 100.0;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800351 audioMixSettings.lvBTChannelCount = mAudioMixSettings->uiBTChannelCount;
352 audioMixSettings.lvPTChannelCount = mAudioMixSettings->uiNbChannels;
353
354 // Call to Audio mix param setting
James Dong3bd45592012-01-20 19:28:01 -0800355 mAudioProcess->setMixParams(audioMixSettings);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800356
357 // Get the BG Audio PCM file details
358 if ( mBGAudioPCMFileHandle ) {
359
360 // TODO : 32bits required for OSAL, to be updated once OSAL is updated
361 M4OSA_UInt32 tmp32 = 0;
362 result = M4OSA_fileReadGetOption(mBGAudioPCMFileHandle,
363 M4OSA_kFileReadGetFileSize,
364 (M4OSA_Void**)&tmp32);
365 mBGAudioPCMFileLength = tmp32;
366 mBGAudioPCMFileTrimmedLength = mBGAudioPCMFileLength;
367
368
Steve Block2703f232011-10-20 11:56:09 +0100369 ALOGV("VideoEditorAudioPlayer::start M4OSA_kFileReadGetFileSize = %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800370 mBGAudioPCMFileLength);
371
372 // Get the duration in time of the audio BT
373 if ( result == M4NO_ERROR ) {
Steve Block2703f232011-10-20 11:56:09 +0100374 ALOGV("VEAP: channels = %d freq = %d",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800375 mAudioMixSettings->uiNbChannels, mAudioMixSettings->uiSamplingFrequency);
376
377 // No trim
378 mBGAudioPCMFileDuration = ((
379 (int64_t)(mBGAudioPCMFileLength/sizeof(M4OSA_UInt16)/
380 mAudioMixSettings->uiNbChannels))*1000 ) /
381 mAudioMixSettings->uiSamplingFrequency;
382
Steve Block2703f232011-10-20 11:56:09 +0100383 ALOGV("VideoEditorAudioPlayer:: beginCutMs %d , endCutMs %d",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800384 (unsigned int) mAudioMixSettings->beginCutMs,
385 (unsigned int) mAudioMixSettings->endCutMs);
386
387 // Remove the trim part
388 if ((mAudioMixSettings->beginCutMs == 0) &&
389 (mAudioMixSettings->endCutMs != 0)) {
390 // End time itself the file duration
391 mBGAudioPCMFileDuration = mAudioMixSettings->endCutMs;
392 // Limit the file length also
393 mBGAudioPCMFileTrimmedLength = ((
394 (int64_t)(mBGAudioPCMFileDuration *
395 mAudioMixSettings->uiSamplingFrequency) *
396 mAudioMixSettings->uiNbChannels) *
397 sizeof(M4OSA_UInt16)) / 1000;
398 }
399 else if ((mAudioMixSettings->beginCutMs != 0) &&
400 (mAudioMixSettings->endCutMs == mBGAudioPCMFileDuration)) {
401 // End time itself the file duration
402 mBGAudioPCMFileDuration = mBGAudioPCMFileDuration -
403 mAudioMixSettings->beginCutMs;
404 // Limit the file length also
405 mBGAudioPCMFileTrimmedLength = ((
406 (int64_t)(mBGAudioPCMFileDuration *
407 mAudioMixSettings->uiSamplingFrequency) *
408 mAudioMixSettings->uiNbChannels) *
409 sizeof(M4OSA_UInt16)) / 1000;
410 }
411 else if ((mAudioMixSettings->beginCutMs != 0) &&
412 (mAudioMixSettings->endCutMs != 0)) {
413 // End time itself the file duration
414 mBGAudioPCMFileDuration = mAudioMixSettings->endCutMs -
415 mAudioMixSettings->beginCutMs;
416 // Limit the file length also
417 mBGAudioPCMFileTrimmedLength = ((
418 (int64_t)(mBGAudioPCMFileDuration *
419 mAudioMixSettings->uiSamplingFrequency) *
420 mAudioMixSettings->uiNbChannels) *
421 sizeof(M4OSA_UInt16)) / 1000; /*make to sec from ms*/
422 }
423
Steve Block2703f232011-10-20 11:56:09 +0100424 ALOGV("VideoEditorAudioPlayer: file duration recorded : %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800425 mBGAudioPCMFileDuration);
426 }
427
428 // Last played location to be seeked at for next media item
429 if ( result == M4NO_ERROR ) {
Steve Block2703f232011-10-20 11:56:09 +0100430 ALOGV("VideoEditorAudioPlayer::mBGAudioStoryBoardSkimTimeStamp %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800431 mBGAudioStoryBoardSkimTimeStamp);
Steve Block2703f232011-10-20 11:56:09 +0100432 ALOGV("VideoEditorAudioPlayer::uiAddCts %d",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800433 mAudioMixSettings->uiAddCts);
434 if (mBGAudioStoryBoardSkimTimeStamp >= mAudioMixSettings->uiAddCts) {
435 startTime = (mBGAudioStoryBoardSkimTimeStamp -
436 mAudioMixSettings->uiAddCts);
437 }
438 else {
439 // do nothing
440 }
441
Steve Block2703f232011-10-20 11:56:09 +0100442 ALOGV("VideoEditorAudioPlayer::startTime %d", startTime);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800443 seekTimeStamp = 0;
444 if (startTime) {
445 if (startTime >= mBGAudioPCMFileDuration) {
446 // The BG track should be looped and started again
447 if (mAudioMixSettings->bLoop) {
448 // Add begin cut time to the mod value
449 seekTimeStamp = ((startTime%mBGAudioPCMFileDuration) +
450 mAudioMixSettings->beginCutMs);
451 }else {
452 // Looping disabled, donot do BT Mix , set to file end
453 seekTimeStamp = (mBGAudioPCMFileDuration +
454 mAudioMixSettings->beginCutMs);
455 }
456 }else {
457 // BT still present , just seek to story board time
458 seekTimeStamp = startTime + mAudioMixSettings->beginCutMs;
459 }
460 }
461 else {
462 seekTimeStamp = mAudioMixSettings->beginCutMs;
463 }
464
465 // Convert the seekTimeStamp to file location
466 mBGAudioPCMFileOriginalSeekPoint = (
467 (int64_t)(mAudioMixSettings->beginCutMs)
468 * mAudioMixSettings->uiSamplingFrequency
469 * mAudioMixSettings->uiNbChannels
470 * sizeof(M4OSA_UInt16))/ 1000 ; /*make to sec from ms*/
471
472 mBGAudioPCMFileSeekPoint = ((int64_t)(seekTimeStamp)
473 * mAudioMixSettings->uiSamplingFrequency
474 * mAudioMixSettings->uiNbChannels
475 * sizeof(M4OSA_UInt16))/ 1000 ;
476 }
477 }
478
479 // We allow an optional INFO_FORMAT_CHANGED at the very beginning
480 // of playback, if there is one, getFormat below will retrieve the
481 // updated format, if there isn't, we'll stash away the valid buffer
482 // of data to be used on the first audio callback.
483
484 CHECK(mFirstBuffer == NULL);
485
486 mFirstBufferResult = mSource->read(&mFirstBuffer);
487 if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +0100488 ALOGV("INFO_FORMAT_CHANGED!!!");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800489
490 CHECK(mFirstBuffer == NULL);
491 mFirstBufferResult = OK;
492 mIsFirstBuffer = false;
493 } else {
494 mIsFirstBuffer = true;
495 }
496
497 sp<MetaData> format = mSource->getFormat();
498 const char *mime;
499 bool success = format->findCString(kKeyMIMEType, &mime);
500 CHECK(success);
501 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
502
503 success = format->findInt32(kKeySampleRate, &mSampleRate);
504 CHECK(success);
505
506 int32_t numChannels;
507 success = format->findInt32(kKeyChannelCount, &numChannels);
508 CHECK(success);
509
510 if (mAudioSink.get() != NULL) {
511 status_t err = mAudioSink->open(
Jean-Michel Trivi8162c1a2012-03-02 14:34:10 -0800512 mSampleRate, numChannels, CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800513 DEFAULT_AUDIOSINK_BUFFERCOUNT,
514 &VideoEditorAudioPlayer::AudioSinkCallback, this);
515 if (err != OK) {
516 if (mFirstBuffer != NULL) {
517 mFirstBuffer->release();
518 mFirstBuffer = NULL;
519 }
520
521 if (!sourceAlreadyStarted) {
522 mSource->stop();
523 }
524
525 return err;
526 }
527
528 mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
529 mFrameSize = mAudioSink->frameSize();
530
531 mAudioSink->start();
532 } else {
533 mAudioTrack = new AudioTrack(
Dima Zavin68598372011-04-05 16:13:49 -0700534 AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
Glenn Kasten28b76b32012-07-03 17:24:41 -0700535 audio_channel_out_mask_from_count(numChannels),
Eric Laurent0ca3cf92012-04-18 09:24:29 -0700536 0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800537
538 if ((err = mAudioTrack->initCheck()) != OK) {
Glenn Kasten2799d742013-05-30 14:33:29 -0700539 mAudioTrack.clear();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800540
541 if (mFirstBuffer != NULL) {
542 mFirstBuffer->release();
543 mFirstBuffer = NULL;
544 }
545
546 if (!sourceAlreadyStarted) {
547 mSource->stop();
548 }
549
550 return err;
551 }
552
553 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
554 mFrameSize = mAudioTrack->frameSize();
555
556 mAudioTrack->start();
557 }
558
559 mStarted = true;
560
561 return OK;
562}
563
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800564
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800565void VideoEditorAudioPlayer::reset() {
566
Steve Block2703f232011-10-20 11:56:09 +0100567 ALOGV("reset");
James Dong727f9e12012-01-20 13:09:13 -0800568 clear();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800569
570 // Capture the current seek point
571 mBGAudioPCMFileSeekPoint = 0;
572 mBGAudioStoryBoardSkimTimeStamp =0;
573 mBGAudioStoryBoardCurrentMediaBeginCutTS=0;
574}
575
576size_t VideoEditorAudioPlayer::AudioSinkCallback(
577 MediaPlayerBase::AudioSink *audioSink,
578 void *buffer, size_t size, void *cookie) {
579 VideoEditorAudioPlayer *me = (VideoEditorAudioPlayer *)cookie;
580
581 return me->fillBuffer(buffer, size);
582}
583
584
585size_t VideoEditorAudioPlayer::fillBuffer(void *data, size_t size) {
586
587 if (mReachedEOS) {
588 return 0;
589 }
590
591 size_t size_done = 0;
592 size_t size_remaining = size;
593
594 M4OSA_ERR err = M4NO_ERROR;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800595 M4AM_Buffer16 bgFrame = {NULL, 0};
596 M4AM_Buffer16 mixFrame = {NULL, 0};
597 M4AM_Buffer16 ptFrame = {NULL, 0};
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800598 int64_t currentSteamTS = 0;
599 int64_t startTimeForBT = 0;
600 M4OSA_Float fPTVolLevel =
601 ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal)/100;
Basavapatna Dattaguru100d0182011-03-04 09:48:24 -0800602 M4OSA_Int16 *pPTMdata=NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800603 M4OSA_UInt32 uiPCMsize = 0;
604
Andreas Huber838daaf2011-04-04 11:38:25 -0700605 bool postSeekComplete = false;
606 bool postEOS = false;
607
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800608 while ((size_remaining > 0)&&(err==M4NO_ERROR)) {
609 MediaSource::ReadOptions options;
610
611 {
612 Mutex::Autolock autoLock(mLock);
613 if (mSeeking) {
614 if (mIsFirstBuffer) {
615 if (mFirstBuffer != NULL) {
616 mFirstBuffer->release();
617 mFirstBuffer = NULL;
618 }
619 mIsFirstBuffer = false;
620 }
621
622 options.setSeekTo(mSeekTimeUs);
623
624 if (mInputBuffer != NULL) {
625 mInputBuffer->release();
626 mInputBuffer = NULL;
627 }
628
629 mSeeking = false;
Andreas Huber838daaf2011-04-04 11:38:25 -0700630
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800631 if (mObserver) {
Andreas Huber838daaf2011-04-04 11:38:25 -0700632 postSeekComplete = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800633 }
634 }
635 }
636
637 if (mInputBuffer == NULL) {
638 status_t status = OK;
639
640 if (mIsFirstBuffer) {
641 mInputBuffer = mFirstBuffer;
642 mFirstBuffer = NULL;
643 status = mFirstBufferResult;
644
645 mIsFirstBuffer = false;
646 } else {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800647
648 {
649 Mutex::Autolock autoLock(mLock);
650 status = mSource->read(&mInputBuffer, &options);
651 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800652 // Data is Primary Track, mix with background track
653 // after reading same size from Background track PCM file
654 if (status == OK)
655 {
656 // Mix only when skim point is after startTime of BT
657 if (((mBGAudioStoryBoardSkimTimeStamp* 1000) +
658 (mPositionTimeMediaUs - mSeekTimeUs)) >=
659 (int64_t)(mAudioMixSettings->uiAddCts * 1000)) {
660
Steve Block2703f232011-10-20 11:56:09 +0100661 ALOGV("VideoEditorAudioPlayer::INSIDE MIXING");
662 ALOGV("Checking %lld <= %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800663 mBGAudioPCMFileSeekPoint-mBGAudioPCMFileOriginalSeekPoint,
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800664 mBGAudioPCMFileTrimmedLength);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800665
666
667 M4OSA_Void* ptr;
668 ptr = (M4OSA_Void*)((unsigned int)mInputBuffer->data() +
669 mInputBuffer->range_offset());
670
671 M4OSA_UInt32 len = mInputBuffer->range_length();
672 M4OSA_Context fp = M4OSA_NULL;
673
674 uiPCMsize = (mInputBuffer->range_length())/2;
Kenny Rooteb5b2652011-02-08 11:13:19 -0800675 pPTMdata = (M4OSA_Int16*) ((uint8_t*) mInputBuffer->data()
676 + mInputBuffer->range_offset());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800677
Steve Block2703f232011-10-20 11:56:09 +0100678 ALOGV("mix with background malloc to do len %d", len);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800679
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700680 bgFrame.m_dataAddress = (M4OSA_UInt16*)M4OSA_32bitAlignedMalloc( len, 1,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800681 (M4OSA_Char*)"bgFrame");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800682 bgFrame.m_bufferSize = len;
683
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700684 mixFrame.m_dataAddress = (M4OSA_UInt16*)M4OSA_32bitAlignedMalloc(len, 1,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800685 (M4OSA_Char*)"mixFrame");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800686 mixFrame.m_bufferSize = len;
687
Steve Block2703f232011-10-20 11:56:09 +0100688 ALOGV("mix with bgm with size %lld", mBGAudioPCMFileLength);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800689
690 CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime,
691 &mPositionTimeMediaUs));
692
693 if (mBGAudioPCMFileSeekPoint -
694 mBGAudioPCMFileOriginalSeekPoint <=
695 (mBGAudioPCMFileTrimmedLength - len)) {
696
Steve Block2703f232011-10-20 11:56:09 +0100697 ALOGV("Checking mBGAudioPCMFileHandle %d",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800698 (unsigned int)mBGAudioPCMFileHandle);
699
700 if (mBGAudioPCMFileHandle != M4OSA_NULL) {
Steve Block2703f232011-10-20 11:56:09 +0100701 ALOGV("fillBuffer seeking file to %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800702 mBGAudioPCMFileSeekPoint);
703
704 // TODO : 32bits required for OSAL
705 M4OSA_UInt32 tmp32 =
706 (M4OSA_UInt32)mBGAudioPCMFileSeekPoint;
707 err = M4OSA_fileReadSeek(mBGAudioPCMFileHandle,
708 M4OSA_kFileSeekBeginning,
709 (M4OSA_FilePosition*)&tmp32);
710
711 mBGAudioPCMFileSeekPoint = tmp32;
712
713 if (err != M4NO_ERROR){
Steve Blockf8bd29c2012-01-08 10:14:44 +0000714 ALOGE("M4OSA_fileReadSeek err %d",(int)err);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800715 }
716
717 err = M4OSA_fileReadData(mBGAudioPCMFileHandle,
718 (M4OSA_Int8*)bgFrame.m_dataAddress,
719 (M4OSA_UInt32*)&len);
720 if (err == M4WAR_NO_DATA_YET ) {
721
Steve Block2703f232011-10-20 11:56:09 +0100722 ALOGV("fillBuffer End of file reached");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800723 err = M4NO_ERROR;
724
725 // We reached the end of file
726 // move to begin cut time equal value
727 if (mAudioMixSettings->bLoop) {
728 mBGAudioPCMFileSeekPoint =
729 (((int64_t)(mAudioMixSettings->beginCutMs) *
730 mAudioMixSettings->uiSamplingFrequency) *
731 mAudioMixSettings->uiNbChannels *
732 sizeof(M4OSA_UInt16)) / 1000;
Steve Block2703f232011-10-20 11:56:09 +0100733 ALOGV("fillBuffer Looping \
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800734 to mBGAudioPCMFileSeekPoint %lld",
735 mBGAudioPCMFileSeekPoint);
736 }
737 else {
738 // No mixing;
739 // take care of volume of primary track
740 if (fPTVolLevel < 1.0) {
741 setPrimaryTrackVolume(pPTMdata,
742 uiPCMsize, fPTVolLevel);
743 }
744 }
745 } else if (err != M4NO_ERROR ) {
Steve Block2703f232011-10-20 11:56:09 +0100746 ALOGV("fileReadData for audio err %d", err);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800747 } else {
748 mBGAudioPCMFileSeekPoint += len;
Steve Block2703f232011-10-20 11:56:09 +0100749 ALOGV("fillBuffer mBGAudioPCMFileSeekPoint \
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800750 %lld", mBGAudioPCMFileSeekPoint);
751
752 // Assign the ptr data to primary track
753 ptFrame.m_dataAddress = (M4OSA_UInt16*)ptr;
754 ptFrame.m_bufferSize = len;
755
756 // Call to mix and duck
James Dong3bd45592012-01-20 19:28:01 -0800757 mAudioProcess->mixAndDuck(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800758 &ptFrame, &bgFrame, &mixFrame);
759
760 // Overwrite the decoded buffer
Shyam Pallapothu32ed3f42011-04-20 21:00:48 -0700761 memcpy((void *)ptr,
762 (void *)mixFrame.m_dataAddress, len);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800763 }
764 }
765 } else if (mAudioMixSettings->bLoop){
766 // Move to begin cut time equal value
767 mBGAudioPCMFileSeekPoint =
768 mBGAudioPCMFileOriginalSeekPoint;
769 } else {
770 // No mixing;
771 // take care of volume level of primary track
772 if(fPTVolLevel < 1.0) {
773 setPrimaryTrackVolume(
774 pPTMdata, uiPCMsize, fPTVolLevel);
775 }
776 }
777 if (bgFrame.m_dataAddress) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700778 free(bgFrame.m_dataAddress);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800779 }
780 if (mixFrame.m_dataAddress) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700781 free(mixFrame.m_dataAddress);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800782 }
783 } else {
784 // No mixing;
785 // take care of volume level of primary track
786 if(fPTVolLevel < 1.0) {
787 setPrimaryTrackVolume(pPTMdata, uiPCMsize,
788 fPTVolLevel);
789 }
790 }
791 }
792 }
793
794 CHECK((status == OK && mInputBuffer != NULL)
795 || (status != OK && mInputBuffer == NULL));
796
797 Mutex::Autolock autoLock(mLock);
798
799 if (status != OK) {
Steve Block2703f232011-10-20 11:56:09 +0100800 ALOGV("fillBuffer: mSource->read returned err %d", status);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800801 if (mObserver && !mReachedEOS) {
Andreas Huber838daaf2011-04-04 11:38:25 -0700802 postEOS = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800803 }
804
805 mReachedEOS = true;
806 mFinalStatus = status;
807 break;
808 }
809
810 CHECK(mInputBuffer->meta_data()->findInt64(
811 kKeyTime, &mPositionTimeMediaUs));
812
813 mPositionTimeRealUs =
814 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
815 / mSampleRate;
816
Steve Block2703f232011-10-20 11:56:09 +0100817 ALOGV("buffer->size() = %d, "
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800818 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
819 mInputBuffer->range_length(),
820 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
821 }
822
823 if (mInputBuffer->range_length() == 0) {
824 mInputBuffer->release();
825 mInputBuffer = NULL;
826
827 continue;
828 }
829
830 size_t copy = size_remaining;
831 if (copy > mInputBuffer->range_length()) {
832 copy = mInputBuffer->range_length();
833 }
834
835 memcpy((char *)data + size_done,
836 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
837 copy);
838
839 mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
840 mInputBuffer->range_length() - copy);
841
842 size_done += copy;
843 size_remaining -= copy;
844 }
845
Andreas Huber838daaf2011-04-04 11:38:25 -0700846 {
847 Mutex::Autolock autoLock(mLock);
848 mNumFramesPlayed += size_done / mFrameSize;
849 }
850
851 if (postEOS) {
852 mObserver->postAudioEOS();
853 }
854
855 if (postSeekComplete) {
856 mObserver->postAudioSeekComplete();
857 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800858
859 return size_done;
860}
861
862void VideoEditorAudioPlayer::setAudioMixSettings(
863 M4xVSS_AudioMixingSettings* pAudioMixSettings) {
864 mAudioMixSettings = pAudioMixSettings;
865}
866
867void VideoEditorAudioPlayer::setAudioMixPCMFileHandle(
868 M4OSA_Context pBGAudioPCMFileHandle){
869 mBGAudioPCMFileHandle = pBGAudioPCMFileHandle;
870}
871
872void VideoEditorAudioPlayer::setAudioMixStoryBoardSkimTimeStamp(
873 M4OSA_UInt32 pBGAudioStoryBoardSkimTimeStamp,
874 M4OSA_UInt32 pBGAudioCurrentMediaBeginCutTS,
875 M4OSA_UInt32 pBGAudioCurrentMediaVolumeVal) {
876
877 mBGAudioStoryBoardSkimTimeStamp = pBGAudioStoryBoardSkimTimeStamp;
878 mBGAudioStoryBoardCurrentMediaBeginCutTS = pBGAudioCurrentMediaBeginCutTS;
879 mBGAudioStoryBoardCurrentMediaVolumeVal = pBGAudioCurrentMediaVolumeVal;
880}
881
882void VideoEditorAudioPlayer::setPrimaryTrackVolume(
883 M4OSA_Int16 *data, M4OSA_UInt32 size, M4OSA_Float volLevel) {
884
885 while(size-- > 0) {
886 *data = (M4OSA_Int16)((*data)*volLevel);
887 data++;
888 }
889}
890
891}