blob: 194e3a604fbe8a2722479f76aef5f6be4e2d480a [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"
21#include <media/stagefright/MetaData.h>
22#include <media/stagefright/MediaDebug.h>
23#include <media/stagefright/MediaBuffer.h>
24#include <media/stagefright/MediaDefs.h>
25#include "AudioMixer.h"
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080026#include <utils/Log.h>
Chih-Chung Chang99698662011-06-30 14:21:38 +080027
28namespace android {
29
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080030VideoEditorSRC::VideoEditorSRC(const sp<MediaSource> &source) {
Steve Block2703f232011-10-20 11:56:09 +010031 ALOGV("VideoEditorSRC::VideoEditorSRC %p(%p)", this, source.get());
Chih-Chung Chang99698662011-06-30 14:21:38 +080032 mSource = source;
33 mResampler = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +080034 mChannelCnt = 0;
35 mSampleRate = 0;
36 mOutputSampleRate = DEFAULT_SAMPLING_FREQ;
37 mStarted = false;
Chih-Chung Chang99698662011-06-30 14:21:38 +080038 mInitialTimeStampUs = -1;
39 mAccuOutBufferSize = 0;
40 mSeekTimeUs = -1;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080041 mBuffer = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +080042 mLeftover = 0;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080043 mFormatChanged = false;
44 mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC;
Chih-Chung Chang99698662011-06-30 14:21:38 +080045
46 // Input Source validation
47 sp<MetaData> format = mSource->getFormat();
48 const char *mime;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080049 CHECK(format->findCString(kKeyMIMEType, &mime));
Chih-Chung Chang99698662011-06-30 14:21:38 +080050 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
51
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080052 // Set the metadata of the output after resampling.
53 mOutputFormat = new MetaData;
54 mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
55 mOutputFormat->setInt32(kKeySampleRate, DEFAULT_SAMPLING_FREQ);
56 mOutputFormat->setInt32(kKeyChannelCount, 2);
Chih-Chung Chang99698662011-06-30 14:21:38 +080057}
58
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080059VideoEditorSRC::~VideoEditorSRC() {
Steve Block2703f232011-10-20 11:56:09 +010060 ALOGV("VideoEditorSRC::~VideoEditorSRC %p(%p)", this, mSource.get());
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080061 stop();
Chih-Chung Chang99698662011-06-30 14:21:38 +080062}
63
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080064status_t VideoEditorSRC::start(MetaData *params) {
Chih-Chung Chang99698662011-06-30 14:21:38 +080065 CHECK(!mStarted);
Steve Block2703f232011-10-20 11:56:09 +010066 ALOGV("VideoEditorSRC:start %p(%p)", this, mSource.get());
Chih-Chung Chang99698662011-06-30 14:21:38 +080067
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -070068 // Set resampler if required
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080069 checkAndSetResampler();
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -070070
Chih-Chung Chang99698662011-06-30 14:21:38 +080071 mSeekTimeUs = -1;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080072 mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC;
Chih-Chung Chang99698662011-06-30 14:21:38 +080073 mStarted = true;
74 mSource->start();
75
76 return OK;
77}
78
79status_t VideoEditorSRC::stop() {
Steve Block2703f232011-10-20 11:56:09 +010080 ALOGV("VideoEditorSRC::stop %p(%p)", this, mSource.get());
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080081 if (!mStarted) return OK;
82 if (mBuffer) {
83 mBuffer->release();
84 mBuffer = NULL;
85 }
Chih-Chung Chang99698662011-06-30 14:21:38 +080086 mSource->stop();
87 if(mResampler != NULL) {
88 delete mResampler;
89 mResampler = NULL;
90 }
91 mStarted = false;
92 mInitialTimeStampUs = -1;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080093 mAccuOutBufferSize = 0;
Chih-Chung Chang99698662011-06-30 14:21:38 +080094 mLeftover = 0;
Chih-Chung Chang99698662011-06-30 14:21:38 +080095
96 return OK;
97}
98
99sp<MetaData> VideoEditorSRC::getFormat() {
Steve Block2703f232011-10-20 11:56:09 +0100100 ALOGV("VideoEditorSRC::getFormat");
Chih-Chung Chang99698662011-06-30 14:21:38 +0800101 return mOutputFormat;
102}
103
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800104status_t VideoEditorSRC::read(
Chih-Chung Chang99698662011-06-30 14:21:38 +0800105 MediaBuffer **buffer_out, const ReadOptions *options) {
Steve Block2703f232011-10-20 11:56:09 +0100106 ALOGV("VideoEditorSRC::read %p(%p)", this, mSource.get());
Chih-Chung Chang99698662011-06-30 14:21:38 +0800107 *buffer_out = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800108
109 if (!mStarted) {
110 return ERROR_END_OF_STREAM;
111 }
112
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800113 if (mResampler) {
Chih-Chung Chang99698662011-06-30 14:21:38 +0800114 // Store the seek parameters
115 int64_t seekTimeUs;
116 ReadOptions::SeekMode mode = ReadOptions::SEEK_PREVIOUS_SYNC;
117 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
Steve Block2703f232011-10-20 11:56:09 +0100118 ALOGV("read Seek %lld", seekTimeUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800119 mSeekTimeUs = seekTimeUs;
120 mSeekMode = mode;
121 }
122
123 // We ask for 1024 frames in output
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800124 const size_t outFrameCnt = 1024;
125 // resampler output is always 2 channels and 32 bits
126 int32_t *pTmpBuffer = (int32_t *)calloc(1, outFrameCnt * 2 * sizeof(int32_t));
Chih-Chung Chang99698662011-06-30 14:21:38 +0800127 // Resample to target quality
128 mResampler->resample(pTmpBuffer, outFrameCnt, this);
129
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800130 // Change resampler and retry if format change happened
131 if (mFormatChanged) {
132 mFormatChanged = false;
133 checkAndSetResampler();
134 free(pTmpBuffer);
135 return read(buffer_out, NULL);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800136 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800137
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800138 // Create a new MediaBuffer
139 int32_t outBufferSize = outFrameCnt * 2 * sizeof(int16_t);
140 MediaBuffer* outBuffer = new MediaBuffer(outBufferSize);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800141
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800142 // Convert back to 2 channels and 16 bits
143 AudioMixer::ditherAndClamp(
144 (int32_t *)((uint8_t*)outBuffer->data() + outBuffer->range_offset()),
145 pTmpBuffer, outFrameCnt);
146 free(pTmpBuffer);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800147
148 // Compute and set the new timestamp
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800149 sp<MetaData> to = outBuffer->meta_data();
150 int64_t totalOutDurationUs = (mAccuOutBufferSize * 1000000) / (mOutputSampleRate * 2 * 2);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800151 int64_t timeUs = mInitialTimeStampUs + totalOutDurationUs;
152 to->setInt64(kKeyTime, timeUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800153
154 // update the accumulate size
155 mAccuOutBufferSize += outBufferSize;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800156 *buffer_out = outBuffer;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800157 } else {
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800158 // Resampling not required. Read and pass-through.
Chih-Chung Chang99698662011-06-30 14:21:38 +0800159 MediaBuffer *aBuffer;
160 status_t err = mSource->read(&aBuffer, options);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800161 if (err != OK) {
Steve Block2703f232011-10-20 11:56:09 +0100162 ALOGV("read returns err = %d", err);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800163 }
164
165 if (err == INFO_FORMAT_CHANGED) {
166 checkAndSetResampler();
167 return read(buffer_out, NULL);
168 }
169
170 // EOS or some other error
Chih-Chung Chang99698662011-06-30 14:21:38 +0800171 if(err != OK) {
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800172 stop();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800173 *buffer_out = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800174 return err;
175 }
176 *buffer_out = aBuffer;
177 }
178
179 return OK;
180}
181
182status_t VideoEditorSRC::getNextBuffer(AudioBufferProvider::Buffer *pBuffer) {
Steve Block2703f232011-10-20 11:56:09 +0100183 ALOGV("Requesting %d, chan = %d", pBuffer->frameCount, mChannelCnt);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800184 uint32_t done = 0;
185 uint32_t want = pBuffer->frameCount * mChannelCnt * 2;
186 pBuffer->raw = malloc(want);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800187
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800188 while (mStarted && want > 0) {
189 // If we don't have any data left, read a new buffer.
190 if (!mBuffer) {
191 // if we seek, reset the initial time stamp and accumulated time
192 ReadOptions options;
193 if (mSeekTimeUs >= 0) {
Steve Block2703f232011-10-20 11:56:09 +0100194 ALOGV("%p cacheMore_l Seek requested = %lld", this, mSeekTimeUs);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800195 ReadOptions::SeekMode mode = mSeekMode;
196 options.setSeekTo(mSeekTimeUs, mode);
197 mSeekTimeUs = -1;
198 mInitialTimeStampUs = -1;
199 mAccuOutBufferSize = 0;
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700200 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800201
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800202 status_t err = mSource->read(&mBuffer, &options);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800203
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800204 if (err != OK) {
205 free(pBuffer->raw);
206 pBuffer->raw = NULL;
207 pBuffer->frameCount = 0;
208 }
209
210 if (err == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +0100211 ALOGV("getNextBuffer: source read returned INFO_FORMAT_CHANGED");
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800212 // At this point we cannot switch to a new AudioResampler because
213 // we are in a callback called by the AudioResampler itself. So
214 // just remember the fact that the format has changed, and let
215 // read() handles this.
216 mFormatChanged = true;
217 return err;
218 }
219
220 // EOS or some other error
221 if (err != OK) {
Steve Block2703f232011-10-20 11:56:09 +0100222 ALOGV("EOS or some err: %d", err);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800223 stop();
224 return err;
225 }
226
227 CHECK(mBuffer);
228 mLeftover = mBuffer->range_length();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800229 if (mInitialTimeStampUs == -1) {
230 int64_t curTS;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800231 sp<MetaData> from = mBuffer->meta_data();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800232 from->findInt64(kKeyTime, &curTS);
Steve Block2703f232011-10-20 11:56:09 +0100233 ALOGV("setting mInitialTimeStampUs to %lld", mInitialTimeStampUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800234 mInitialTimeStampUs = curTS;
235 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800236 }
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800237
238 // Now copy data to the destination
239 uint32_t todo = mLeftover;
240 if (todo > want) {
241 todo = want;
242 }
243
244 uint8_t* end = (uint8_t*)mBuffer->data() + mBuffer->range_offset()
245 + mBuffer->range_length();
246 memcpy((uint8_t*)pBuffer->raw + done, end - mLeftover, todo);
247 done += todo;
248 want -= todo;
249 mLeftover -= todo;
250
251 // Release MediaBuffer as soon as possible.
252 if (mLeftover == 0) {
253 mBuffer->release();
254 mBuffer = NULL;
255 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800256 }
257
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800258 pBuffer->frameCount = done / (mChannelCnt * 2);
Steve Block2703f232011-10-20 11:56:09 +0100259 ALOGV("getNextBuffer done %d", pBuffer->frameCount);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800260 return OK;
261}
262
263
264void VideoEditorSRC::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) {
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800265 free(pBuffer->raw);
266 pBuffer->raw = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800267 pBuffer->frameCount = 0;
268}
269
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800270void VideoEditorSRC::checkAndSetResampler() {
Steve Block2703f232011-10-20 11:56:09 +0100271 ALOGV("checkAndSetResampler");
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700272
273 sp<MetaData> format = mSource->getFormat();
274 const char *mime;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800275 CHECK(format->findCString(kKeyMIMEType, &mime));
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700276 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
277
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800278 CHECK(format->findInt32(kKeySampleRate, &mSampleRate));
279 CHECK(format->findInt32(kKeyChannelCount, &mChannelCnt));
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700280
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800281 // If a resampler exists, delete it first
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700282 if (mResampler != NULL) {
283 delete mResampler;
284 mResampler = NULL;
285 }
286
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800287 // Clear previous buffer
288 if (mBuffer) {
289 mBuffer->release();
290 mBuffer = NULL;
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700291 }
292
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800293 if (mSampleRate != mOutputSampleRate || mChannelCnt != 2) {
Steve Block2703f232011-10-20 11:56:09 +0100294 ALOGV("Resampling required (in rate %d, out rate %d, in channel %d)",
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800295 mSampleRate, mOutputSampleRate, mChannelCnt);
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700296
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800297 mResampler = AudioResampler::create(
298 16 /* bit depth */,
299 mChannelCnt,
300 mOutputSampleRate,
301 AudioResampler::DEFAULT);
302 CHECK(mResampler);
303 mResampler->setSampleRate(mSampleRate);
304 mResampler->setVolume(UNITY_GAIN, UNITY_GAIN);
305 } else {
Steve Block2703f232011-10-20 11:56:09 +0100306 ALOGV("Resampling not required (%d = %d)", mSampleRate, mOutputSampleRate);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800307 }
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700308}
309
Chih-Chung Chang99698662011-06-30 14:21:38 +0800310} //namespce android