blob: c111ba81da6f71d3c672f30ee02bcc5330108719 [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)
James Dong727f9e12012-01-20 13:09:13 -080038 : 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) {
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080055
James Dong727f9e12012-01-20 13:09:13 -080056 ALOGV("Constructor");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080057 mBGAudioPCMFileHandle = NULL;
Dheeraj Sharma5bc7fb42011-02-13 20:31:27 -080058 mAudioProcess = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080059 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;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -080068 mSource = NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080069}
70
71VideoEditorAudioPlayer::~VideoEditorAudioPlayer() {
72
James Dong727f9e12012-01-20 13:09:13 -080073 ALOGV("Destructor");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080074 if (mStarted) {
75 reset();
76 }
Santosh Madhava5df81852011-02-11 00:43:26 -080077 if (mAudioProcess != NULL) {
78 delete mAudioProcess;
79 mAudioProcess = NULL;
80 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -080081}
James Dong727f9e12012-01-20 13:09:13 -080082
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
James Dong3bd45592012-01-20 19:28:01 -0800157 AudioMixSettings audioMixSettings;
James Dong727f9e12012-01-20 13:09:13 -0800158
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
James Dong3bd45592012-01-20 19:28:01 -0800176 mAudioProcess->setMixParams(audioMixSettings);
James Dong727f9e12012-01-20 13:09:13 -0800177
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
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800260void VideoEditorAudioPlayer::setSource(const sp<MediaSource> &source) {
261 Mutex::Autolock autoLock(mLock);
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800262
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) {
Steve Block2703f232011-10-20 11:56:09 +0100273 ALOGV("VideoEditorAudioPlayer releasing input buffer.");
Rajneesh Chowduryb6e2b5c2011-02-25 22:59:46 -0800274
275 mInputBuffer->release();
276 mInputBuffer = NULL;
277 }
278
279 if (mSource != NULL) {
280 mSource->stop();
281 mSource.clear();
282 }
283
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800284 mSource = source;
285 mReachedEOS = false;
286}
287
288sp<MediaSource> VideoEditorAudioPlayer::getSource() {
289 Mutex::Autolock autoLock(mLock);
290 return mSource;
291}
292
James Dong00f742c2012-01-13 17:34:42 -0800293void VideoEditorAudioPlayer::setObserver(PreviewPlayer *observer) {
Steve Block2703f232011-10-20 11:56:09 +0100294 ALOGV("setObserver");
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800295 //CHECK(!mStarted);
296 mObserver = observer;
297}
298
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800299bool VideoEditorAudioPlayer::isStarted() {
300 return mStarted;
301}
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800302
James Dong727f9e12012-01-20 13:09:13 -0800303// 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
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800320status_t VideoEditorAudioPlayer::start(bool sourceAlreadyStarted) {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800321 Mutex::Autolock autoLock(mLock);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800322 CHECK(!mStarted);
323 CHECK(mSource != NULL);
Steve Block2703f232011-10-20 11:56:09 +0100324 ALOGV("Start");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800325 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();
James Dong3bd45592012-01-20 19:28:01 -0800340 AudioMixSettings audioMixSettings;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800341
342 // Pass on the audio ducking parameters
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800343 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;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800353 audioMixSettings.lvBTChannelCount = mAudioMixSettings->uiBTChannelCount;
354 audioMixSettings.lvPTChannelCount = mAudioMixSettings->uiNbChannels;
355
356 // Call to Audio mix param setting
James Dong3bd45592012-01-20 19:28:01 -0800357 mAudioProcess->setMixParams(audioMixSettings);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800358
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
Steve Block2703f232011-10-20 11:56:09 +0100371 ALOGV("VideoEditorAudioPlayer::start M4OSA_kFileReadGetFileSize = %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800372 mBGAudioPCMFileLength);
373
374 // Get the duration in time of the audio BT
375 if ( result == M4NO_ERROR ) {
Steve Block2703f232011-10-20 11:56:09 +0100376 ALOGV("VEAP: channels = %d freq = %d",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800377 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
Steve Block2703f232011-10-20 11:56:09 +0100385 ALOGV("VideoEditorAudioPlayer:: beginCutMs %d , endCutMs %d",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800386 (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
Steve Block2703f232011-10-20 11:56:09 +0100426 ALOGV("VideoEditorAudioPlayer: file duration recorded : %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800427 mBGAudioPCMFileDuration);
428 }
429
430 // Last played location to be seeked at for next media item
431 if ( result == M4NO_ERROR ) {
Steve Block2703f232011-10-20 11:56:09 +0100432 ALOGV("VideoEditorAudioPlayer::mBGAudioStoryBoardSkimTimeStamp %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800433 mBGAudioStoryBoardSkimTimeStamp);
Steve Block2703f232011-10-20 11:56:09 +0100434 ALOGV("VideoEditorAudioPlayer::uiAddCts %d",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800435 mAudioMixSettings->uiAddCts);
436 if (mBGAudioStoryBoardSkimTimeStamp >= mAudioMixSettings->uiAddCts) {
437 startTime = (mBGAudioStoryBoardSkimTimeStamp -
438 mAudioMixSettings->uiAddCts);
439 }
440 else {
441 // do nothing
442 }
443
Steve Block2703f232011-10-20 11:56:09 +0100444 ALOGV("VideoEditorAudioPlayer::startTime %d", startTime);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800445 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) {
Steve Block2703f232011-10-20 11:56:09 +0100490 ALOGV("INFO_FORMAT_CHANGED!!!");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800491
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(
Jean-Michel Trivi8162c1a2012-03-02 14:34:10 -0800514 mSampleRate, numChannels, CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800515 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(
Dima Zavin68598372011-04-05 16:13:49 -0700536 AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
Glenn Kasten28b76b32012-07-03 17:24:41 -0700537 audio_channel_out_mask_from_count(numChannels),
Eric Laurent0ca3cf92012-04-18 09:24:29 -0700538 0, AUDIO_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800539
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
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800567
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800568void VideoEditorAudioPlayer::reset() {
569
Steve Block2703f232011-10-20 11:56:09 +0100570 ALOGV("reset");
James Dong727f9e12012-01-20 13:09:13 -0800571 clear();
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800572
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;
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800598 M4AM_Buffer16 bgFrame = {NULL, 0};
599 M4AM_Buffer16 mixFrame = {NULL, 0};
600 M4AM_Buffer16 ptFrame = {NULL, 0};
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800601 int64_t currentSteamTS = 0;
602 int64_t startTimeForBT = 0;
603 M4OSA_Float fPTVolLevel =
604 ((M4OSA_Float)mBGAudioStoryBoardCurrentMediaVolumeVal)/100;
Basavapatna Dattaguru100d0182011-03-04 09:48:24 -0800605 M4OSA_Int16 *pPTMdata=NULL;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800606 M4OSA_UInt32 uiPCMsize = 0;
607
Andreas Huber838daaf2011-04-04 11:38:25 -0700608 bool postSeekComplete = false;
609 bool postEOS = false;
610
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800611 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;
Andreas Huber838daaf2011-04-04 11:38:25 -0700633
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800634 if (mObserver) {
Andreas Huber838daaf2011-04-04 11:38:25 -0700635 postSeekComplete = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800636 }
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 {
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800650
651 {
652 Mutex::Autolock autoLock(mLock);
653 status = mSource->read(&mInputBuffer, &options);
654 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800655 // 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
Steve Block2703f232011-10-20 11:56:09 +0100664 ALOGV("VideoEditorAudioPlayer::INSIDE MIXING");
665 ALOGV("Checking %lld <= %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800666 mBGAudioPCMFileSeekPoint-mBGAudioPCMFileOriginalSeekPoint,
Rajneesh Chowdury1c97d9a2011-02-21 15:43:33 -0800667 mBGAudioPCMFileTrimmedLength);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800668
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;
Kenny Rooteb5b2652011-02-08 11:13:19 -0800678 pPTMdata = (M4OSA_Int16*) ((uint8_t*) mInputBuffer->data()
679 + mInputBuffer->range_offset());
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800680
Steve Block2703f232011-10-20 11:56:09 +0100681 ALOGV("mix with background malloc to do len %d", len);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800682
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700683 bgFrame.m_dataAddress = (M4OSA_UInt16*)M4OSA_32bitAlignedMalloc( len, 1,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800684 (M4OSA_Char*)"bgFrame");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800685 bgFrame.m_bufferSize = len;
686
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700687 mixFrame.m_dataAddress = (M4OSA_UInt16*)M4OSA_32bitAlignedMalloc(len, 1,
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800688 (M4OSA_Char*)"mixFrame");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800689 mixFrame.m_bufferSize = len;
690
Steve Block2703f232011-10-20 11:56:09 +0100691 ALOGV("mix with bgm with size %lld", mBGAudioPCMFileLength);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800692
693 CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime,
694 &mPositionTimeMediaUs));
695
696 if (mBGAudioPCMFileSeekPoint -
697 mBGAudioPCMFileOriginalSeekPoint <=
698 (mBGAudioPCMFileTrimmedLength - len)) {
699
Steve Block2703f232011-10-20 11:56:09 +0100700 ALOGV("Checking mBGAudioPCMFileHandle %d",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800701 (unsigned int)mBGAudioPCMFileHandle);
702
703 if (mBGAudioPCMFileHandle != M4OSA_NULL) {
Steve Block2703f232011-10-20 11:56:09 +0100704 ALOGV("fillBuffer seeking file to %lld",
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800705 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){
Steve Blockf8bd29c2012-01-08 10:14:44 +0000717 ALOGE("M4OSA_fileReadSeek err %d",(int)err);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800718 }
719
720 err = M4OSA_fileReadData(mBGAudioPCMFileHandle,
721 (M4OSA_Int8*)bgFrame.m_dataAddress,
722 (M4OSA_UInt32*)&len);
723 if (err == M4WAR_NO_DATA_YET ) {
724
Steve Block2703f232011-10-20 11:56:09 +0100725 ALOGV("fillBuffer End of file reached");
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800726 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;
Steve Block2703f232011-10-20 11:56:09 +0100736 ALOGV("fillBuffer Looping \
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800737 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 ) {
Steve Block2703f232011-10-20 11:56:09 +0100749 ALOGV("fileReadData for audio err %d", err);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800750 } else {
751 mBGAudioPCMFileSeekPoint += len;
Steve Block2703f232011-10-20 11:56:09 +0100752 ALOGV("fillBuffer mBGAudioPCMFileSeekPoint \
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800753 %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
James Dong3bd45592012-01-20 19:28:01 -0800760 mAudioProcess->mixAndDuck(
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800761 &ptFrame, &bgFrame, &mixFrame);
762
763 // Overwrite the decoded buffer
Shyam Pallapothu32ed3f42011-04-20 21:00:48 -0700764 memcpy((void *)ptr,
765 (void *)mixFrame.m_dataAddress, len);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800766 }
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) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700781 free(bgFrame.m_dataAddress);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800782 }
783 if (mixFrame.m_dataAddress) {
Shyam Pallapothu694816d2011-04-21 09:48:41 -0700784 free(mixFrame.m_dataAddress);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800785 }
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) {
Steve Block2703f232011-10-20 11:56:09 +0100803 ALOGV("fillBuffer: mSource->read returned err %d", status);
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800804 if (mObserver && !mReachedEOS) {
Andreas Huber838daaf2011-04-04 11:38:25 -0700805 postEOS = true;
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800806 }
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
Steve Block2703f232011-10-20 11:56:09 +0100820 ALOGV("buffer->size() = %d, "
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800821 "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
Andreas Huber838daaf2011-04-04 11:38:25 -0700849 {
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 }
Dharmaray Kundargi643290d2011-01-16 16:02:42 -0800861
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}