blob: 1d34ca5b6d259014ec618d6f82d00a4e1f6f6b11 [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
James Dong00f742c2012-01-13 17:34:42 -080020#include <stdlib.h>
21#include <utils/Log.h>
Glenn Kasten7bdbbc72011-12-16 11:07:44 -080022#include <audio_utils/primitives.h>
James Dongc4689fa2012-02-08 13:51:46 -080023#include <media/stagefright/foundation/ADebug.h>
Chih-Chung Chang99698662011-06-30 14:21:38 +080024#include <media/stagefright/MetaData.h>
Chih-Chung Chang99698662011-06-30 14:21:38 +080025#include <media/stagefright/MediaBuffer.h>
26#include <media/stagefright/MediaDefs.h>
27#include "AudioMixer.h"
James Dong00f742c2012-01-13 17:34:42 -080028#include "VideoEditorSRC.h"
29
Chih-Chung Chang99698662011-06-30 14:21:38 +080030
31namespace android {
32
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080033VideoEditorSRC::VideoEditorSRC(const sp<MediaSource> &source) {
James Dong00f742c2012-01-13 17:34:42 -080034 ALOGV("VideoEditorSRC %p(%p)", this, source.get());
35 static const int32_t kDefaultSamplingFreqencyHz = kFreq32000Hz;
Chih-Chung Chang99698662011-06-30 14:21:38 +080036 mSource = source;
37 mResampler = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +080038 mChannelCnt = 0;
39 mSampleRate = 0;
James Dong00f742c2012-01-13 17:34:42 -080040 mOutputSampleRate = kDefaultSamplingFreqencyHz;
Chih-Chung Chang99698662011-06-30 14:21:38 +080041 mStarted = false;
Chih-Chung Chang99698662011-06-30 14:21:38 +080042 mInitialTimeStampUs = -1;
43 mAccuOutBufferSize = 0;
44 mSeekTimeUs = -1;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080045 mBuffer = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +080046 mLeftover = 0;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080047 mFormatChanged = false;
Chih-Chung Chang2db76712011-11-15 19:47:25 +080048 mStopPending = false;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080049 mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC;
Chih-Chung Chang99698662011-06-30 14:21:38 +080050
51 // Input Source validation
52 sp<MetaData> format = mSource->getFormat();
53 const char *mime;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080054 CHECK(format->findCString(kKeyMIMEType, &mime));
Chih-Chung Chang99698662011-06-30 14:21:38 +080055 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
56
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080057 // Set the metadata of the output after resampling.
58 mOutputFormat = new MetaData;
59 mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
James Dong00f742c2012-01-13 17:34:42 -080060 mOutputFormat->setInt32(kKeySampleRate, kDefaultSamplingFreqencyHz);
61 mOutputFormat->setInt32(kKeyChannelCount, 2); // always stereo
Chih-Chung Chang99698662011-06-30 14:21:38 +080062}
63
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080064VideoEditorSRC::~VideoEditorSRC() {
James Dong00f742c2012-01-13 17:34:42 -080065 ALOGV("~VideoEditorSRC %p(%p)", this, mSource.get());
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080066 stop();
Chih-Chung Chang99698662011-06-30 14:21:38 +080067}
68
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080069status_t VideoEditorSRC::start(MetaData *params) {
James Dong00f742c2012-01-13 17:34:42 -080070 ALOGV("start %p(%p)", this, mSource.get());
Chih-Chung Chang99698662011-06-30 14:21:38 +080071 CHECK(!mStarted);
Chih-Chung Chang99698662011-06-30 14:21:38 +080072
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -070073 // Set resampler if required
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080074 checkAndSetResampler();
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -070075
Chih-Chung Chang99698662011-06-30 14:21:38 +080076 mSeekTimeUs = -1;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080077 mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC;
Chih-Chung Chang99698662011-06-30 14:21:38 +080078 mStarted = true;
79 mSource->start();
80
81 return OK;
82}
83
84status_t VideoEditorSRC::stop() {
James Dong00f742c2012-01-13 17:34:42 -080085 ALOGV("stop %p(%p)", this, mSource.get());
86 if (!mStarted) {
87 return OK;
88 }
89
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080090 if (mBuffer) {
91 mBuffer->release();
92 mBuffer = NULL;
93 }
Chih-Chung Chang99698662011-06-30 14:21:38 +080094 mSource->stop();
James Dong00f742c2012-01-13 17:34:42 -080095 if (mResampler != NULL) {
Chih-Chung Chang99698662011-06-30 14:21:38 +080096 delete mResampler;
97 mResampler = NULL;
98 }
James Dong00f742c2012-01-13 17:34:42 -080099
Chih-Chung Chang99698662011-06-30 14:21:38 +0800100 mStarted = false;
101 mInitialTimeStampUs = -1;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800102 mAccuOutBufferSize = 0;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800103 mLeftover = 0;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800104
105 return OK;
106}
107
108sp<MetaData> VideoEditorSRC::getFormat() {
James Dong00f742c2012-01-13 17:34:42 -0800109 ALOGV("getFormat");
Chih-Chung Chang99698662011-06-30 14:21:38 +0800110 return mOutputFormat;
111}
112
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800113status_t VideoEditorSRC::read(
Chih-Chung Chang99698662011-06-30 14:21:38 +0800114 MediaBuffer **buffer_out, const ReadOptions *options) {
James Dong00f742c2012-01-13 17:34:42 -0800115 ALOGV("read %p(%p)", this, mSource.get());
Chih-Chung Chang99698662011-06-30 14:21:38 +0800116 *buffer_out = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800117
118 if (!mStarted) {
119 return ERROR_END_OF_STREAM;
120 }
121
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800122 if (mResampler) {
Chih-Chung Chang99698662011-06-30 14:21:38 +0800123 // Store the seek parameters
124 int64_t seekTimeUs;
125 ReadOptions::SeekMode mode = ReadOptions::SEEK_PREVIOUS_SYNC;
126 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
Steve Block2703f232011-10-20 11:56:09 +0100127 ALOGV("read Seek %lld", seekTimeUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800128 mSeekTimeUs = seekTimeUs;
129 mSeekMode = mode;
130 }
131
132 // We ask for 1024 frames in output
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800133 // resampler output is always 2 channels and 32 bits
James Dong00f742c2012-01-13 17:34:42 -0800134 const size_t kOutputFrameCount = 1024;
135 const size_t kBytes = kOutputFrameCount * 2 * sizeof(int32_t);
136 int32_t *pTmpBuffer = (int32_t *)calloc(1, kBytes);
137 if (!pTmpBuffer) {
138 ALOGE("calloc failed to allocate memory: %d bytes", kBytes);
139 return NO_MEMORY;
140 }
141
Chih-Chung Chang99698662011-06-30 14:21:38 +0800142 // Resample to target quality
James Dong00f742c2012-01-13 17:34:42 -0800143 mResampler->resample(pTmpBuffer, kOutputFrameCount, this);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800144
Chih-Chung Chang2db76712011-11-15 19:47:25 +0800145 if (mStopPending) {
146 stop();
147 mStopPending = false;
148 }
149
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800150 // Change resampler and retry if format change happened
151 if (mFormatChanged) {
152 mFormatChanged = false;
153 checkAndSetResampler();
154 free(pTmpBuffer);
155 return read(buffer_out, NULL);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800156 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800157
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800158 // Create a new MediaBuffer
James Dong00f742c2012-01-13 17:34:42 -0800159 int32_t outBufferSize = kOutputFrameCount * 2 * sizeof(int16_t);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800160 MediaBuffer* outBuffer = new MediaBuffer(outBufferSize);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800161
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800162 // Convert back to 2 channels and 16 bits
Glenn Kasten7bdbbc72011-12-16 11:07:44 -0800163 ditherAndClamp(
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800164 (int32_t *)((uint8_t*)outBuffer->data() + outBuffer->range_offset()),
James Dong00f742c2012-01-13 17:34:42 -0800165 pTmpBuffer, kOutputFrameCount);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800166 free(pTmpBuffer);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800167
168 // Compute and set the new timestamp
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800169 sp<MetaData> to = outBuffer->meta_data();
170 int64_t totalOutDurationUs = (mAccuOutBufferSize * 1000000) / (mOutputSampleRate * 2 * 2);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800171 int64_t timeUs = mInitialTimeStampUs + totalOutDurationUs;
172 to->setInt64(kKeyTime, timeUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800173
174 // update the accumulate size
175 mAccuOutBufferSize += outBufferSize;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800176 *buffer_out = outBuffer;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800177 } else {
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800178 // Resampling not required. Read and pass-through.
Chih-Chung Chang99698662011-06-30 14:21:38 +0800179 MediaBuffer *aBuffer;
180 status_t err = mSource->read(&aBuffer, options);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800181 if (err != OK) {
Steve Block2703f232011-10-20 11:56:09 +0100182 ALOGV("read returns err = %d", err);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800183 }
184
185 if (err == INFO_FORMAT_CHANGED) {
186 checkAndSetResampler();
187 return read(buffer_out, NULL);
188 }
189
190 // EOS or some other error
Chih-Chung Chang99698662011-06-30 14:21:38 +0800191 if(err != OK) {
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800192 stop();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800193 *buffer_out = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800194 return err;
195 }
196 *buffer_out = aBuffer;
197 }
198
199 return OK;
200}
201
202status_t VideoEditorSRC::getNextBuffer(AudioBufferProvider::Buffer *pBuffer) {
James Dong00f742c2012-01-13 17:34:42 -0800203 ALOGV("getNextBuffer %d, chan = %d", pBuffer->frameCount, mChannelCnt);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800204 uint32_t done = 0;
205 uint32_t want = pBuffer->frameCount * mChannelCnt * 2;
206 pBuffer->raw = malloc(want);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800207
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800208 while (mStarted && want > 0) {
209 // If we don't have any data left, read a new buffer.
210 if (!mBuffer) {
211 // if we seek, reset the initial time stamp and accumulated time
212 ReadOptions options;
213 if (mSeekTimeUs >= 0) {
Steve Block2703f232011-10-20 11:56:09 +0100214 ALOGV("%p cacheMore_l Seek requested = %lld", this, mSeekTimeUs);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800215 ReadOptions::SeekMode mode = mSeekMode;
216 options.setSeekTo(mSeekTimeUs, mode);
217 mSeekTimeUs = -1;
218 mInitialTimeStampUs = -1;
219 mAccuOutBufferSize = 0;
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700220 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800221
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800222 status_t err = mSource->read(&mBuffer, &options);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800223
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800224 if (err != OK) {
225 free(pBuffer->raw);
226 pBuffer->raw = NULL;
227 pBuffer->frameCount = 0;
228 }
229
230 if (err == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +0100231 ALOGV("getNextBuffer: source read returned INFO_FORMAT_CHANGED");
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800232 // At this point we cannot switch to a new AudioResampler because
233 // we are in a callback called by the AudioResampler itself. So
234 // just remember the fact that the format has changed, and let
235 // read() handles this.
236 mFormatChanged = true;
237 return err;
238 }
239
240 // EOS or some other error
241 if (err != OK) {
Steve Block2703f232011-10-20 11:56:09 +0100242 ALOGV("EOS or some err: %d", err);
Chih-Chung Chang2db76712011-11-15 19:47:25 +0800243 // We cannot call stop() here because stop() will release the
244 // AudioResampler, and we are in a callback of the AudioResampler.
245 // So just remember the fact and let read() call stop().
246 mStopPending = true;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800247 return err;
248 }
249
250 CHECK(mBuffer);
251 mLeftover = mBuffer->range_length();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800252 if (mInitialTimeStampUs == -1) {
253 int64_t curTS;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800254 sp<MetaData> from = mBuffer->meta_data();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800255 from->findInt64(kKeyTime, &curTS);
Steve Block2703f232011-10-20 11:56:09 +0100256 ALOGV("setting mInitialTimeStampUs to %lld", mInitialTimeStampUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800257 mInitialTimeStampUs = curTS;
258 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800259 }
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800260
261 // Now copy data to the destination
262 uint32_t todo = mLeftover;
263 if (todo > want) {
264 todo = want;
265 }
266
267 uint8_t* end = (uint8_t*)mBuffer->data() + mBuffer->range_offset()
268 + mBuffer->range_length();
269 memcpy((uint8_t*)pBuffer->raw + done, end - mLeftover, todo);
270 done += todo;
271 want -= todo;
272 mLeftover -= todo;
273
274 // Release MediaBuffer as soon as possible.
275 if (mLeftover == 0) {
276 mBuffer->release();
277 mBuffer = NULL;
278 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800279 }
280
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800281 pBuffer->frameCount = done / (mChannelCnt * 2);
Steve Block2703f232011-10-20 11:56:09 +0100282 ALOGV("getNextBuffer done %d", pBuffer->frameCount);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800283 return OK;
284}
285
286
287void VideoEditorSRC::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) {
James Dong00f742c2012-01-13 17:34:42 -0800288 ALOGV("releaseBuffer: %p", pBuffers);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800289 free(pBuffer->raw);
290 pBuffer->raw = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800291 pBuffer->frameCount = 0;
292}
293
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800294void VideoEditorSRC::checkAndSetResampler() {
Steve Block2703f232011-10-20 11:56:09 +0100295 ALOGV("checkAndSetResampler");
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700296
James Dong00f742c2012-01-13 17:34:42 -0800297 static const uint16_t kUnityGain = 0x1000;
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700298 sp<MetaData> format = mSource->getFormat();
299 const char *mime;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800300 CHECK(format->findCString(kKeyMIMEType, &mime));
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700301 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
302
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800303 CHECK(format->findInt32(kKeySampleRate, &mSampleRate));
304 CHECK(format->findInt32(kKeyChannelCount, &mChannelCnt));
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700305
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800306 // If a resampler exists, delete it first
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700307 if (mResampler != NULL) {
308 delete mResampler;
309 mResampler = NULL;
310 }
311
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800312 // Clear previous buffer
313 if (mBuffer) {
314 mBuffer->release();
315 mBuffer = NULL;
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700316 }
317
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800318 if (mSampleRate != mOutputSampleRate || mChannelCnt != 2) {
James Dong00f742c2012-01-13 17:34:42 -0800319 ALOGV("Resampling required (%d => %d Hz, # channels = %d)",
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800320 mSampleRate, mOutputSampleRate, mChannelCnt);
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700321
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800322 mResampler = AudioResampler::create(
323 16 /* bit depth */,
324 mChannelCnt,
325 mOutputSampleRate,
326 AudioResampler::DEFAULT);
327 CHECK(mResampler);
328 mResampler->setSampleRate(mSampleRate);
James Dong00f742c2012-01-13 17:34:42 -0800329 mResampler->setVolume(kUnityGain, kUnityGain);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800330 } else {
James Dong00f742c2012-01-13 17:34:42 -0800331 ALOGV("Resampling not required (%d => %d Hz, # channels = %d)",
332 mSampleRate, mOutputSampleRate, mChannelCnt);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800333 }
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700334}
335
Chih-Chung Chang99698662011-06-30 14:21:38 +0800336} //namespce android