blob: 5ea95b09d221aad719474695a7702ee5cae9db7b [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;
Chih-Chung Chang2db76712011-11-15 19:47:25 +080044 mStopPending = false;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080045 mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC;
Chih-Chung Chang99698662011-06-30 14:21:38 +080046
47 // Input Source validation
48 sp<MetaData> format = mSource->getFormat();
49 const char *mime;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080050 CHECK(format->findCString(kKeyMIMEType, &mime));
Chih-Chung Chang99698662011-06-30 14:21:38 +080051 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
52
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080053 // Set the metadata of the output after resampling.
54 mOutputFormat = new MetaData;
55 mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
56 mOutputFormat->setInt32(kKeySampleRate, DEFAULT_SAMPLING_FREQ);
57 mOutputFormat->setInt32(kKeyChannelCount, 2);
Chih-Chung Chang99698662011-06-30 14:21:38 +080058}
59
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080060VideoEditorSRC::~VideoEditorSRC() {
Steve Block2703f232011-10-20 11:56:09 +010061 ALOGV("VideoEditorSRC::~VideoEditorSRC %p(%p)", this, mSource.get());
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080062 stop();
Chih-Chung Chang99698662011-06-30 14:21:38 +080063}
64
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080065status_t VideoEditorSRC::start(MetaData *params) {
Chih-Chung Chang99698662011-06-30 14:21:38 +080066 CHECK(!mStarted);
Steve Block2703f232011-10-20 11:56:09 +010067 ALOGV("VideoEditorSRC:start %p(%p)", this, mSource.get());
Chih-Chung Chang99698662011-06-30 14:21:38 +080068
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -070069 // Set resampler if required
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080070 checkAndSetResampler();
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -070071
Chih-Chung Chang99698662011-06-30 14:21:38 +080072 mSeekTimeUs = -1;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080073 mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC;
Chih-Chung Chang99698662011-06-30 14:21:38 +080074 mStarted = true;
75 mSource->start();
76
77 return OK;
78}
79
80status_t VideoEditorSRC::stop() {
Steve Block2703f232011-10-20 11:56:09 +010081 ALOGV("VideoEditorSRC::stop %p(%p)", this, mSource.get());
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080082 if (!mStarted) return OK;
83 if (mBuffer) {
84 mBuffer->release();
85 mBuffer = NULL;
86 }
Chih-Chung Chang99698662011-06-30 14:21:38 +080087 mSource->stop();
88 if(mResampler != NULL) {
89 delete mResampler;
90 mResampler = NULL;
91 }
92 mStarted = false;
93 mInitialTimeStampUs = -1;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +080094 mAccuOutBufferSize = 0;
Chih-Chung Chang99698662011-06-30 14:21:38 +080095 mLeftover = 0;
Chih-Chung Chang99698662011-06-30 14:21:38 +080096
97 return OK;
98}
99
100sp<MetaData> VideoEditorSRC::getFormat() {
Steve Block2703f232011-10-20 11:56:09 +0100101 ALOGV("VideoEditorSRC::getFormat");
Chih-Chung Chang99698662011-06-30 14:21:38 +0800102 return mOutputFormat;
103}
104
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800105status_t VideoEditorSRC::read(
Chih-Chung Chang99698662011-06-30 14:21:38 +0800106 MediaBuffer **buffer_out, const ReadOptions *options) {
Steve Block2703f232011-10-20 11:56:09 +0100107 ALOGV("VideoEditorSRC::read %p(%p)", this, mSource.get());
Chih-Chung Chang99698662011-06-30 14:21:38 +0800108 *buffer_out = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800109
110 if (!mStarted) {
111 return ERROR_END_OF_STREAM;
112 }
113
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800114 if (mResampler) {
Chih-Chung Chang99698662011-06-30 14:21:38 +0800115 // Store the seek parameters
116 int64_t seekTimeUs;
117 ReadOptions::SeekMode mode = ReadOptions::SEEK_PREVIOUS_SYNC;
118 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
Steve Block2703f232011-10-20 11:56:09 +0100119 ALOGV("read Seek %lld", seekTimeUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800120 mSeekTimeUs = seekTimeUs;
121 mSeekMode = mode;
122 }
123
124 // We ask for 1024 frames in output
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800125 const size_t outFrameCnt = 1024;
126 // resampler output is always 2 channels and 32 bits
127 int32_t *pTmpBuffer = (int32_t *)calloc(1, outFrameCnt * 2 * sizeof(int32_t));
Chih-Chung Chang99698662011-06-30 14:21:38 +0800128 // Resample to target quality
129 mResampler->resample(pTmpBuffer, outFrameCnt, this);
130
Chih-Chung Chang2db76712011-11-15 19:47:25 +0800131 if (mStopPending) {
132 stop();
133 mStopPending = false;
134 }
135
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800136 // Change resampler and retry if format change happened
137 if (mFormatChanged) {
138 mFormatChanged = false;
139 checkAndSetResampler();
140 free(pTmpBuffer);
141 return read(buffer_out, NULL);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800142 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800143
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800144 // Create a new MediaBuffer
145 int32_t outBufferSize = outFrameCnt * 2 * sizeof(int16_t);
146 MediaBuffer* outBuffer = new MediaBuffer(outBufferSize);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800147
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800148 // Convert back to 2 channels and 16 bits
149 AudioMixer::ditherAndClamp(
150 (int32_t *)((uint8_t*)outBuffer->data() + outBuffer->range_offset()),
151 pTmpBuffer, outFrameCnt);
152 free(pTmpBuffer);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800153
154 // Compute and set the new timestamp
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800155 sp<MetaData> to = outBuffer->meta_data();
156 int64_t totalOutDurationUs = (mAccuOutBufferSize * 1000000) / (mOutputSampleRate * 2 * 2);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800157 int64_t timeUs = mInitialTimeStampUs + totalOutDurationUs;
158 to->setInt64(kKeyTime, timeUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800159
160 // update the accumulate size
161 mAccuOutBufferSize += outBufferSize;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800162 *buffer_out = outBuffer;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800163 } else {
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800164 // Resampling not required. Read and pass-through.
Chih-Chung Chang99698662011-06-30 14:21:38 +0800165 MediaBuffer *aBuffer;
166 status_t err = mSource->read(&aBuffer, options);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800167 if (err != OK) {
Steve Block2703f232011-10-20 11:56:09 +0100168 ALOGV("read returns err = %d", err);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800169 }
170
171 if (err == INFO_FORMAT_CHANGED) {
172 checkAndSetResampler();
173 return read(buffer_out, NULL);
174 }
175
176 // EOS or some other error
Chih-Chung Chang99698662011-06-30 14:21:38 +0800177 if(err != OK) {
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800178 stop();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800179 *buffer_out = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800180 return err;
181 }
182 *buffer_out = aBuffer;
183 }
184
185 return OK;
186}
187
188status_t VideoEditorSRC::getNextBuffer(AudioBufferProvider::Buffer *pBuffer) {
Steve Block2703f232011-10-20 11:56:09 +0100189 ALOGV("Requesting %d, chan = %d", pBuffer->frameCount, mChannelCnt);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800190 uint32_t done = 0;
191 uint32_t want = pBuffer->frameCount * mChannelCnt * 2;
192 pBuffer->raw = malloc(want);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800193
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800194 while (mStarted && want > 0) {
195 // If we don't have any data left, read a new buffer.
196 if (!mBuffer) {
197 // if we seek, reset the initial time stamp and accumulated time
198 ReadOptions options;
199 if (mSeekTimeUs >= 0) {
Steve Block2703f232011-10-20 11:56:09 +0100200 ALOGV("%p cacheMore_l Seek requested = %lld", this, mSeekTimeUs);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800201 ReadOptions::SeekMode mode = mSeekMode;
202 options.setSeekTo(mSeekTimeUs, mode);
203 mSeekTimeUs = -1;
204 mInitialTimeStampUs = -1;
205 mAccuOutBufferSize = 0;
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700206 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800207
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800208 status_t err = mSource->read(&mBuffer, &options);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800209
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800210 if (err != OK) {
211 free(pBuffer->raw);
212 pBuffer->raw = NULL;
213 pBuffer->frameCount = 0;
214 }
215
216 if (err == INFO_FORMAT_CHANGED) {
Steve Block2703f232011-10-20 11:56:09 +0100217 ALOGV("getNextBuffer: source read returned INFO_FORMAT_CHANGED");
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800218 // At this point we cannot switch to a new AudioResampler because
219 // we are in a callback called by the AudioResampler itself. So
220 // just remember the fact that the format has changed, and let
221 // read() handles this.
222 mFormatChanged = true;
223 return err;
224 }
225
226 // EOS or some other error
227 if (err != OK) {
Steve Block2703f232011-10-20 11:56:09 +0100228 ALOGV("EOS or some err: %d", err);
Chih-Chung Chang2db76712011-11-15 19:47:25 +0800229 // We cannot call stop() here because stop() will release the
230 // AudioResampler, and we are in a callback of the AudioResampler.
231 // So just remember the fact and let read() call stop().
232 mStopPending = true;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800233 return err;
234 }
235
236 CHECK(mBuffer);
237 mLeftover = mBuffer->range_length();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800238 if (mInitialTimeStampUs == -1) {
239 int64_t curTS;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800240 sp<MetaData> from = mBuffer->meta_data();
Chih-Chung Chang99698662011-06-30 14:21:38 +0800241 from->findInt64(kKeyTime, &curTS);
Steve Block2703f232011-10-20 11:56:09 +0100242 ALOGV("setting mInitialTimeStampUs to %lld", mInitialTimeStampUs);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800243 mInitialTimeStampUs = curTS;
244 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800245 }
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800246
247 // Now copy data to the destination
248 uint32_t todo = mLeftover;
249 if (todo > want) {
250 todo = want;
251 }
252
253 uint8_t* end = (uint8_t*)mBuffer->data() + mBuffer->range_offset()
254 + mBuffer->range_length();
255 memcpy((uint8_t*)pBuffer->raw + done, end - mLeftover, todo);
256 done += todo;
257 want -= todo;
258 mLeftover -= todo;
259
260 // Release MediaBuffer as soon as possible.
261 if (mLeftover == 0) {
262 mBuffer->release();
263 mBuffer = NULL;
264 }
Chih-Chung Chang99698662011-06-30 14:21:38 +0800265 }
266
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800267 pBuffer->frameCount = done / (mChannelCnt * 2);
Steve Block2703f232011-10-20 11:56:09 +0100268 ALOGV("getNextBuffer done %d", pBuffer->frameCount);
Chih-Chung Chang99698662011-06-30 14:21:38 +0800269 return OK;
270}
271
272
273void VideoEditorSRC::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) {
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800274 free(pBuffer->raw);
275 pBuffer->raw = NULL;
Chih-Chung Chang99698662011-06-30 14:21:38 +0800276 pBuffer->frameCount = 0;
277}
278
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800279void VideoEditorSRC::checkAndSetResampler() {
Steve Block2703f232011-10-20 11:56:09 +0100280 ALOGV("checkAndSetResampler");
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700281
282 sp<MetaData> format = mSource->getFormat();
283 const char *mime;
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800284 CHECK(format->findCString(kKeyMIMEType, &mime));
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700285 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
286
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800287 CHECK(format->findInt32(kKeySampleRate, &mSampleRate));
288 CHECK(format->findInt32(kKeyChannelCount, &mChannelCnt));
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700289
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800290 // If a resampler exists, delete it first
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700291 if (mResampler != NULL) {
292 delete mResampler;
293 mResampler = NULL;
294 }
295
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800296 // Clear previous buffer
297 if (mBuffer) {
298 mBuffer->release();
299 mBuffer = NULL;
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700300 }
301
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800302 if (mSampleRate != mOutputSampleRate || mChannelCnt != 2) {
Steve Block2703f232011-10-20 11:56:09 +0100303 ALOGV("Resampling required (in rate %d, out rate %d, in channel %d)",
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800304 mSampleRate, mOutputSampleRate, mChannelCnt);
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700305
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800306 mResampler = AudioResampler::create(
307 16 /* bit depth */,
308 mChannelCnt,
309 mOutputSampleRate,
310 AudioResampler::DEFAULT);
311 CHECK(mResampler);
312 mResampler->setSampleRate(mSampleRate);
313 mResampler->setVolume(UNITY_GAIN, UNITY_GAIN);
314 } else {
Steve Block2703f232011-10-20 11:56:09 +0100315 ALOGV("Resampling not required (%d = %d)", mSampleRate, mOutputSampleRate);
Chih-Chung Chang3d974e72011-08-18 19:41:30 +0800316 }
Rajneesh Chowdury1c3c5432011-07-20 13:47:34 -0700317}
318
Chih-Chung Chang99698662011-06-30 14:21:38 +0800319} //namespce android