• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "VideoEditorSRC"
19 
20 #include <stdlib.h>
21 #include <utils/Log.h>
22 #include <audio_utils/primitives.h>
23 #include <media/stagefright/foundation/ADebug.h>
24 #include <media/stagefright/MetaData.h>
25 #include <media/stagefright/MediaBuffer.h>
26 #include <media/stagefright/MediaDefs.h>
27 #include "VideoEditorSRC.h"
28 
29 
30 namespace android {
31 
VideoEditorSRC(const sp<MediaSource> & source)32 VideoEditorSRC::VideoEditorSRC(const sp<MediaSource> &source) {
33     ALOGV("VideoEditorSRC %p(%p)", this, source.get());
34     static const int32_t kDefaultSamplingFreqencyHz = kFreq32000Hz;
35     mSource = source;
36     mResampler = NULL;
37     mChannelCnt = 0;
38     mSampleRate = 0;
39     mOutputSampleRate = kDefaultSamplingFreqencyHz;
40     mStarted = false;
41     mInitialTimeStampUs = -1;
42     mAccuOutBufferSize  = 0;
43     mSeekTimeUs = -1;
44     mBuffer = NULL;
45     mLeftover = 0;
46     mFormatChanged = false;
47     mStopPending = false;
48     mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC;
49 
50     // Input Source validation
51     sp<MetaData> format = mSource->getFormat();
52     const char *mime;
53     CHECK(format->findCString(kKeyMIMEType, &mime));
54     CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
55 
56     // Set the metadata of the output after resampling.
57     mOutputFormat = new MetaData;
58     mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
59     mOutputFormat->setInt32(kKeySampleRate, kDefaultSamplingFreqencyHz);
60     mOutputFormat->setInt32(kKeyChannelCount, 2);  // always stereo
61 }
62 
~VideoEditorSRC()63 VideoEditorSRC::~VideoEditorSRC() {
64     ALOGV("~VideoEditorSRC %p(%p)", this, mSource.get());
65     stop();
66 }
67 
start(MetaData * params)68 status_t VideoEditorSRC::start(MetaData *params) {
69     ALOGV("start %p(%p)", this, mSource.get());
70     CHECK(!mStarted);
71 
72     // Set resampler if required
73     checkAndSetResampler();
74 
75     mSeekTimeUs = -1;
76     mSeekMode = ReadOptions::SEEK_PREVIOUS_SYNC;
77     mStarted = true;
78     mSource->start();
79 
80     return OK;
81 }
82 
stop()83 status_t VideoEditorSRC::stop() {
84     ALOGV("stop %p(%p)", this, mSource.get());
85     if (!mStarted) {
86         return OK;
87     }
88 
89     if (mBuffer) {
90         mBuffer->release();
91         mBuffer = NULL;
92     }
93     mSource->stop();
94     if (mResampler != NULL) {
95         delete mResampler;
96         mResampler = NULL;
97     }
98 
99     mStarted = false;
100     mInitialTimeStampUs = -1;
101     mAccuOutBufferSize = 0;
102     mLeftover = 0;
103 
104     return OK;
105 }
106 
getFormat()107 sp<MetaData> VideoEditorSRC::getFormat() {
108     ALOGV("getFormat");
109     return mOutputFormat;
110 }
111 
read(MediaBuffer ** buffer_out,const ReadOptions * options)112 status_t VideoEditorSRC::read(
113         MediaBuffer **buffer_out, const ReadOptions *options) {
114     ALOGV("read %p(%p)", this, mSource.get());
115     *buffer_out = NULL;
116 
117     if (!mStarted) {
118         return ERROR_END_OF_STREAM;
119     }
120 
121     if (mResampler) {
122         // Store the seek parameters
123         int64_t seekTimeUs;
124         ReadOptions::SeekMode mode = ReadOptions::SEEK_PREVIOUS_SYNC;
125         if (options && options->getSeekTo(&seekTimeUs, &mode)) {
126             ALOGV("read Seek %lld", seekTimeUs);
127             mSeekTimeUs = seekTimeUs;
128             mSeekMode = mode;
129         }
130 
131         // We ask for 1024 frames in output
132         // resampler output is always 2 channels and 32 bits
133         const size_t kOutputFrameCount = 1024;
134         const size_t kBytes = kOutputFrameCount * 2 * sizeof(int32_t);
135         int32_t *pTmpBuffer = (int32_t *)calloc(1, kBytes);
136         if (!pTmpBuffer) {
137             ALOGE("calloc failed to allocate memory: %d bytes", kBytes);
138             return NO_MEMORY;
139         }
140 
141         // Resample to target quality
142         mResampler->resample(pTmpBuffer, kOutputFrameCount, this);
143 
144         if (mStopPending) {
145             stop();
146             mStopPending = false;
147         }
148 
149         // Change resampler and retry if format change happened
150         if (mFormatChanged) {
151             mFormatChanged = false;
152             checkAndSetResampler();
153             free(pTmpBuffer);
154             return read(buffer_out, NULL);
155         }
156 
157         // Create a new MediaBuffer
158         int32_t outBufferSize = kOutputFrameCount * 2 * sizeof(int16_t);
159         MediaBuffer* outBuffer = new MediaBuffer(outBufferSize);
160 
161         // Convert back to 2 channels and 16 bits
162         ditherAndClamp(
163                 (int32_t *)((uint8_t*)outBuffer->data() + outBuffer->range_offset()),
164                 pTmpBuffer, kOutputFrameCount);
165         free(pTmpBuffer);
166 
167         // Compute and set the new timestamp
168         sp<MetaData> to = outBuffer->meta_data();
169         int64_t totalOutDurationUs = (mAccuOutBufferSize * 1000000) / (mOutputSampleRate * 2 * 2);
170         int64_t timeUs = mInitialTimeStampUs + totalOutDurationUs;
171         to->setInt64(kKeyTime, timeUs);
172 
173         // update the accumulate size
174         mAccuOutBufferSize += outBufferSize;
175         *buffer_out = outBuffer;
176     } else {
177         // Resampling not required. Read and pass-through.
178         MediaBuffer *aBuffer;
179         status_t err = mSource->read(&aBuffer, options);
180         if (err != OK) {
181             ALOGV("read returns err = %d", err);
182         }
183 
184         if (err == INFO_FORMAT_CHANGED) {
185             checkAndSetResampler();
186             return read(buffer_out, NULL);
187         }
188 
189         // EOS or some other error
190         if(err != OK) {
191             stop();
192             *buffer_out = NULL;
193             return err;
194         }
195         *buffer_out = aBuffer;
196     }
197 
198     return OK;
199 }
200 
getNextBuffer(AudioBufferProvider::Buffer * pBuffer,int64_t pts)201 status_t VideoEditorSRC::getNextBuffer(AudioBufferProvider::Buffer *pBuffer, int64_t pts) {
202     ALOGV("getNextBuffer %d, chan = %d", pBuffer->frameCount, mChannelCnt);
203     uint32_t done = 0;
204     uint32_t want = pBuffer->frameCount * mChannelCnt * 2;
205     pBuffer->raw = malloc(want);
206 
207     while (mStarted && want > 0) {
208         // If we don't have any data left, read a new buffer.
209         if (!mBuffer) {
210             // if we seek, reset the initial time stamp and accumulated time
211             ReadOptions options;
212             if (mSeekTimeUs >= 0) {
213                 ALOGV("%p cacheMore_l Seek requested = %lld", this, mSeekTimeUs);
214                 ReadOptions::SeekMode mode = mSeekMode;
215                 options.setSeekTo(mSeekTimeUs, mode);
216                 mSeekTimeUs = -1;
217                 mInitialTimeStampUs = -1;
218                 mAccuOutBufferSize = 0;
219             }
220 
221             status_t err = mSource->read(&mBuffer, &options);
222 
223             if (err != OK) {
224                 free(pBuffer->raw);
225                 pBuffer->raw = NULL;
226                 pBuffer->frameCount = 0;
227             }
228 
229             if (err == INFO_FORMAT_CHANGED) {
230                 ALOGV("getNextBuffer: source read returned INFO_FORMAT_CHANGED");
231                 // At this point we cannot switch to a new AudioResampler because
232                 // we are in a callback called by the AudioResampler itself. So
233                 // just remember the fact that the format has changed, and let
234                 // read() handles this.
235                 mFormatChanged = true;
236                 return err;
237             }
238 
239             // EOS or some other error
240             if (err != OK) {
241                 ALOGV("EOS or some err: %d", err);
242                 // We cannot call stop() here because stop() will release the
243                 // AudioResampler, and we are in a callback of the AudioResampler.
244                 // So just remember the fact and let read() call stop().
245                 mStopPending = true;
246                 return err;
247             }
248 
249             CHECK(mBuffer);
250             mLeftover = mBuffer->range_length();
251             if (mInitialTimeStampUs == -1) {
252                 int64_t curTS;
253                 sp<MetaData> from = mBuffer->meta_data();
254                 from->findInt64(kKeyTime, &curTS);
255                 ALOGV("setting mInitialTimeStampUs to %lld", mInitialTimeStampUs);
256                 mInitialTimeStampUs = curTS;
257             }
258         }
259 
260         // Now copy data to the destination
261         uint32_t todo = mLeftover;
262         if (todo > want) {
263             todo = want;
264         }
265 
266         uint8_t* end = (uint8_t*)mBuffer->data() + mBuffer->range_offset()
267                 + mBuffer->range_length();
268         memcpy((uint8_t*)pBuffer->raw + done, end - mLeftover, todo);
269         done += todo;
270         want -= todo;
271         mLeftover -= todo;
272 
273         // Release MediaBuffer as soon as possible.
274         if (mLeftover == 0) {
275             mBuffer->release();
276             mBuffer = NULL;
277         }
278     }
279 
280     pBuffer->frameCount = done / (mChannelCnt * 2);
281     ALOGV("getNextBuffer done %d", pBuffer->frameCount);
282     return OK;
283 }
284 
285 
releaseBuffer(AudioBufferProvider::Buffer * pBuffer)286 void VideoEditorSRC::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) {
287     ALOGV("releaseBuffer: %p", pBuffers);
288     free(pBuffer->raw);
289     pBuffer->raw = NULL;
290     pBuffer->frameCount = 0;
291 }
292 
checkAndSetResampler()293 void VideoEditorSRC::checkAndSetResampler() {
294     ALOGV("checkAndSetResampler");
295 
296     static const uint16_t kUnityGain = 0x1000;
297     sp<MetaData> format = mSource->getFormat();
298     const char *mime;
299     CHECK(format->findCString(kKeyMIMEType, &mime));
300     CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
301 
302     CHECK(format->findInt32(kKeySampleRate, &mSampleRate));
303     CHECK(format->findInt32(kKeyChannelCount, &mChannelCnt));
304 
305     // If a resampler exists, delete it first
306     if (mResampler != NULL) {
307         delete mResampler;
308         mResampler = NULL;
309     }
310 
311     // Clear previous buffer
312     if (mBuffer) {
313         mBuffer->release();
314         mBuffer = NULL;
315     }
316 
317     if (mSampleRate != mOutputSampleRate || mChannelCnt != 2) {
318         ALOGV("Resampling required (%d => %d Hz, # channels = %d)",
319             mSampleRate, mOutputSampleRate, mChannelCnt);
320 
321         mResampler = AudioResampler::create(
322                         16 /* bit depth */,
323                         mChannelCnt,
324                         mOutputSampleRate);
325         CHECK(mResampler);
326         mResampler->setSampleRate(mSampleRate);
327         mResampler->setVolume(kUnityGain, kUnityGain);
328     } else {
329         ALOGV("Resampling not required (%d => %d Hz, # channels = %d)",
330             mSampleRate, mOutputSampleRate, mChannelCnt);
331     }
332 }
333 
334 } //namespce android
335