blob: 3e8c4983e5673329414bab16354a13c1db84cd6f [file] [log] [blame]
Chih-Chung Chang99698662011-06-30 14:21:38 +08001/*
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
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080017//#define LOG_NDEBUG 0
18#define LOG_TAG "VideoEditorSRC"
Chih-Chung Chang99698662011-06-30 14:21:38 +080019
20#include "VideoEditorSRC.h"
Glenn Kasten7bdbbc72011-12-16 11:07:44 -080021#include <audio_utils/primitives.h>
Chih-Chung Chang99698662011-06-30 14:21:38 +080022#include <media/stagefright/MetaData.h>
23#include <media/stagefright/MediaDebug.h>
24#include <media/stagefright/MediaBuffer.h>
25#include <media/stagefright/MediaDefs.h>
26#include "AudioMixer.h"
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080027#include <utils/Log.h>
Chih-Chung Chang99698662011-06-30 14:21:38 +080028
29namespace android {
30
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080031VideoEditorSRC::VideoEditorSRC(const sp<MediaSource> &source) {
Steve Block2703f232011-10-20 11:56:09 +010032 ALOGV("VideoEditorSRC::VideoEditorSRC %p(%p)", this, source.get());
Chih-Chung Chang99698662011-06-30 14:21:38 +080033 mSource = source;
34 mResampler = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +080035 mChannelCnt = 0;
36 mSampleRate = 0;
37 mOutputSampleRate = DEFAULT_SAMPLING_FREQ;
38 mStarted = false;
Chih-Chung Chang99698662011-06-30 14:21:38 +080039 mInitialTimeStampUs = -1;
40 mAccuOutBufferSize = 0;
41 mSeekTimeUs = -1;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080042 mBuffer = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +080043 mLeftover = 0;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080044 mFormatChanged = false;
Chih-Chung Chang2db76712011-11-15 19:47:25 +080045 mStopPending = false;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080046 mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC;
Chih-Chung Chang99698662011-06-30 14:21:38 +080047
48 // Input Source validation
49 sp<MetaData> format = mSource->getFormat();
50 const char *mime;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080051 CHECK(format->findCString(kKeyMIMEType, &mime));
Chih-Chung Chang99698662011-06-30 14:21:38 +080052 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
53
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080054 // Set the metadata of the output after resampling.
55 mOutputFormat = new MetaData;
56 mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
57 mOutputFormat->setInt32(kKeySampleRate, DEFAULT_SAMPLING_FREQ);
58 mOutputFormat->setInt32(kKeyChannelCount, 2);
Chih-Chung Chang99698662011-06-30 14:21:38 +080059}
60
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080061VideoEditorSRC::~VideoEditorSRC() {
Steve Block2703f232011-10-20 11:56:09 +010062 ALOGV("VideoEditorSRC::~VideoEditorSRC %p(%p)", this, mSource.get());
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080063 stop();
Chih-Chung Chang99698662011-06-30 14:21:38 +080064}
65
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080066status_t VideoEditorSRC::start(MetaData *params) {
Chih-Chung Chang99698662011-06-30 14:21:38 +080067 CHECK(!mStarted);
Steve Block2703f232011-10-20 11:56:09 +010068 ALOGV("VideoEditorSRC:start %p(%p)", this, mSource.get());
Chih-Chung Chang99698662011-06-30 14:21:38 +080069
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -070070 // Set resampler if required
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080071 checkAndSetResampler();
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -070072
Chih-Chung Chang99698662011-06-30 14:21:38 +080073 mSeekTimeUs = -1;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080074 mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC;
Chih-Chung Chang99698662011-06-30 14:21:38 +080075 mStarted = true;
76 mSource->start();
77
78 return OK;
79}
80
81status_t VideoEditorSRC::stop() {
Steve Block2703f232011-10-20 11:56:09 +010082 ALOGV("VideoEditorSRC::stop %p(%p)", this, mSource.get());
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080083 if (!mStarted) return OK;
84 if (mBuffer) {
85 mBuffer->release();
86 mBuffer = NULL;
87 }
Chih-Chung Chang99698662011-06-30 14:21:38 +080088 mSource->stop();
89 if(mResampler != NULL) {
90 delete mResampler;
91 mResampler = NULL;
92 }
93 mStarted = false;
94 mInitialTimeStampUs = -1;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080095 mAccuOutBufferSize = 0;
Chih-Chung Chang99698662011-06-30 14:21:38 +080096 mLeftover = 0;
Chih-Chung Chang99698662011-06-30 14:21:38 +080097
98 return OK;
99}
100
101sp<MetaData> VideoEditorSRC::getFormat() {
Steve Block2703f232011-10-20 11:56:09 +0100102 ALOGV("VideoEditorSRC::getFormat");
Chih-Chung Chang99698662011-06-30 14:21:38 +0800103 return mOutputFormat;
104}
105
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800106status_t VideoEditorSRC::read(
Chih-Chung Chang99698662011-06-30 14:21:38 +0800107 MediaBuffer **buffer_out, const ReadOptions *options) {
Steve Block2703f232011-10-20 11:56:09 +0100108 ALOGV("VideoEditorSRC::read %p(%p)", this, mSource.get());
Chih-Chung Chang99698662011-06-30 14:21:38 +0800109 *buffer_out = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800110
111 if (!mStarted) {
112 return ERROR_END_OF_STREAM;
113 }
114
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800115 if (mResampler) {
Chih-Chung Chang99698662011-06-30 14:21:38 +0800116 // Store the seek parameters
117 int64_t seekTimeUs;
118 ReadOptions::SeekMode mode = ReadOptions::SEEK_PREVIOUS_SYNC;
119 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
Steve Block2703f232011-10-20 11:56:09 +0100120 ALOGV("read Seek %lld", seekTimeUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800121 mSeekTimeUs = seekTimeUs;
122 mSeekMode = mode;
123 }
124
125 // We ask for 1024 frames in output
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800126 const size_t outFrameCnt = 1024;
127 // resampler output is always 2 channels and 32 bits
128 int32_t *pTmpBuffer = (int32_t *)calloc(1, outFrameCnt * 2 * sizeof(int32_t));
Chih-Chung Chang99698662011-06-30 14:21:38 +0800129 // Resample to target quality
130 mResampler->resample(pTmpBuffer, outFrameCnt, this);
131
Chih-Chung Chang2db76712011-11-15 19:47:25 +0800132 if (mStopPending) {
133 stop();
134 mStopPending = false;
135 }
136
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800137 // Change resampler and retry if format change happened
138 if (mFormatChanged) {
139 mFormatChanged = false;
140 checkAndSetResampler();
141 free(pTmpBuffer);
142 return read(buffer_out, NULL);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800143 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800144
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800145 // Create a new MediaBuffer
146 int32_t outBufferSize = outFrameCnt * 2 * sizeof(int16_t);
147 MediaBuffer* outBuffer = new MediaBuffer(outBufferSize);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800148
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800149 // Convert back to 2 channels and 16 bits
Glenn Kasten7bdbbc72011-12-16 11:07:44 -0800150 ditherAndClamp(
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800151 (int32_t *)((uint8_t*)outBuffer->data() + outBuffer->range_offset()),
152 pTmpBuffer, outFrameCnt);
153 free(pTmpBuffer);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800154
155 // Compute and set the new timestamp
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800156 sp<MetaData> to = outBuffer->meta_data();
157 int64_t totalOutDurationUs = (mAccuOutBufferSize * 1000000) / (mOutputSampleRate * 2 * 2);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800158 int64_t timeUs = mInitialTimeStampUs + totalOutDurationUs;
159 to->setInt64(kKeyTime, timeUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800160
161 // update the accumulate size
162 mAccuOutBufferSize += outBufferSize;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800163 *buffer_out = outBuffer;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800164 } else {
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800165 // Resampling not required. Read and pass-through.
Chih-Chung Chang99698662011-06-30 14:21:38 +0800166 MediaBuffer *aBuffer;
167 status_t err = mSource->read(&aBuffer, options);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800168 if (err != OK) {
Steve Block2703f232011-10-20 11:56:09 +0100169 ALOGV("read returns err = %d", err);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800170 }
171
172 if (err == INFO_FORMAT_CHANGED) {
173 checkAndSetResampler();
174 return read(buffer_out, NULL);
175 }
176
177 // EOS or some other error
Chih-Chung Chang99698662011-06-30 14:21:38 +0800178 if(err != OK) {
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800179 stop();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800180 *buffer_out = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800181 return err;
182 }
183 *buffer_out = aBuffer;
184 }
185
186 return OK;
187}
188
189status_t VideoEditorSRC::getNextBuffer(AudioBufferProvider::Buffer *pBuffer) {
Steve Block2703f232011-10-20 11:56:09 +0100190 ALOGV("Requesting %d, chan = %d", pBuffer->frameCount, mChannelCnt);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800191 uint32_t done = 0;
192 uint32_t want = pBuffer->frameCount * mChannelCnt * 2;
193 pBuffer->raw = malloc(want);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800194
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800195 while (mStarted && want > 0) {
196 // If we don't have any data left, read a new buffer.
197 if (!mBuffer) {
198 // if we seek, reset the initial time stamp and accumulated time
199 ReadOptions options;
200 if (mSeekTimeUs >= 0) {
Steve Block2703f232011-10-20 11:56:09 +0100201 ALOGV("%p cacheMore_l Seek requested = %lld", this, mSeekTimeUs);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800202 ReadOptions::SeekMode mode = mSeekMode;
203 options.setSeekTo(mSeekTimeUs, mode);
204 mSeekTimeUs = -1;
205 mInitialTimeStampUs = -1;
206 mAccuOutBufferSize = 0;
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700207 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800208
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800209 status_t err = mSource->read(&mBuffer, &options);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800210
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800211 if (err != OK) {
212 free(pBuffer->raw);
213 pBuffer->raw = NULL;
214 pBuffer->frameCount = 0;
215 }
216
217 if (err == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +0100218 ALOGV("getNextBuffer: source read returned INFO_FORMAT_CHANGED");
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800219 // At this point we cannot switch to a new AudioResampler because
220 // we are in a callback called by the AudioResampler itself. So
221 // just remember the fact that the format has changed, and let
222 // read() handles this.
223 mFormatChanged = true;
224 return err;
225 }
226
227 // EOS or some other error
228 if (err != OK) {
Steve Block2703f232011-10-20 11:56:09 +0100229 ALOGV("EOS or some err: %d", err);
Chih-Chung Chang2db76712011-11-15 19:47:25 +0800230 // We cannot call stop() here because stop() will release the
231 // AudioResampler, and we are in a callback of the AudioResampler.
232 // So just remember the fact and let read() call stop().
233 mStopPending = true;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800234 return err;
235 }
236
237 CHECK(mBuffer);
238 mLeftover = mBuffer->range_length();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800239 if (mInitialTimeStampUs == -1) {
240 int64_t curTS;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800241 sp<MetaData> from = mBuffer->meta_data();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800242 from->findInt64(kKeyTime, &curTS);
Steve Block2703f232011-10-20 11:56:09 +0100243 ALOGV("setting mInitialTimeStampUs to %lld", mInitialTimeStampUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800244 mInitialTimeStampUs = curTS;
245 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800246 }
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800247
248 // Now copy data to the destination
249 uint32_t todo = mLeftover;
250 if (todo > want) {
251 todo = want;
252 }
253
254 uint8_t* end = (uint8_t*)mBuffer->data() + mBuffer->range_offset()
255 + mBuffer->range_length();
256 memcpy((uint8_t*)pBuffer->raw + done, end - mLeftover, todo);
257 done += todo;
258 want -= todo;
259 mLeftover -= todo;
260
261 // Release MediaBuffer as soon as possible.
262 if (mLeftover == 0) {
263 mBuffer->release();
264 mBuffer = NULL;
265 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800266 }
267
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800268 pBuffer->frameCount = done / (mChannelCnt * 2);
Steve Block2703f232011-10-20 11:56:09 +0100269 ALOGV("getNextBuffer done %d", pBuffer->frameCount);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800270 return OK;
271}
272
273
274void VideoEditorSRC::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) {
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800275 free(pBuffer->raw);
276 pBuffer->raw = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800277 pBuffer->frameCount = 0;
278}
279
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800280void VideoEditorSRC::checkAndSetResampler() {
Steve Block2703f232011-10-20 11:56:09 +0100281 ALOGV("checkAndSetResampler");
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700282
283 sp<MetaData> format = mSource->getFormat();
284 const char *mime;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800285 CHECK(format->findCString(kKeyMIMEType, &mime));
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700286 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
287
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800288 CHECK(format->findInt32(kKeySampleRate, &mSampleRate));
289 CHECK(format->findInt32(kKeyChannelCount, &mChannelCnt));
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700290
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800291 // If a resampler exists, delete it first
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700292 if (mResampler != NULL) {
293 delete mResampler;
294 mResampler = NULL;
295 }
296
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800297 // Clear previous buffer
298 if (mBuffer) {
299 mBuffer->release();
300 mBuffer = NULL;
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700301 }
302
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800303 if (mSampleRate != mOutputSampleRate || mChannelCnt != 2) {
Steve Block2703f232011-10-20 11:56:09 +0100304 ALOGV("Resampling required (in rate %d, out rate %d, in channel %d)",
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800305 mSampleRate, mOutputSampleRate, mChannelCnt);
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700306
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800307 mResampler = AudioResampler::create(
308 16 /* bit depth */,
309 mChannelCnt,
310 mOutputSampleRate,
311 AudioResampler::DEFAULT);
312 CHECK(mResampler);
313 mResampler->setSampleRate(mSampleRate);
314 mResampler->setVolume(UNITY_GAIN, UNITY_GAIN);
315 } else {
Steve Block2703f232011-10-20 11:56:09 +0100316 ALOGV("Resampling not required (%d = %d)", mSampleRate, mOutputSampleRate);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800317 }
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700318}
319
Chih-Chung Chang99698662011-06-30 14:21:38 +0800320} //namespce android