blob: b7182991eaeaefd242e482b3232c43f0922e8b22 [file] [log] [blame]
Andreas Hubere46b7be2009-07-14 16:56:47 -07001/*
2 * Copyright (C) 2009 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
Andreas Huberda050cf22009-09-02 14:01:43 -070017#include "SineSource.h"
18
Andreas Hubere46b7be2009-07-14 16:56:47 -070019#include <binder/ProcessState.h>
Andreas Huberda050cf22009-09-02 14:01:43 -070020#include <media/stagefright/AudioPlayer.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070021#include <media/stagefright/CameraSource.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080022#include <media/stagefright/FileSource.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070023#include <media/stagefright/MediaBufferGroup.h>
Andreas Hubere915a852009-08-28 13:32:48 -070024#include <media/stagefright/MediaDebug.h>
Andreas Hubere6c40962009-09-10 14:13:30 -070025#include <media/stagefright/MediaDefs.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070026#include <media/stagefright/MetaData.h>
Andreas Huber57515f32009-10-23 09:55:10 -070027#include <media/stagefright/MediaExtractor.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070028#include <media/stagefright/MPEG4Writer.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070029#include <media/stagefright/OMXClient.h>
Andreas Huberbe06d262009-08-14 14:37:10 -070030#include <media/stagefright/OMXCodec.h>
Andreas Huberda050cf22009-09-02 14:01:43 -070031#include <media/MediaPlayerInterface.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070032
33using namespace android;
34
James Dongd31c89f2010-08-31 11:46:42 -070035static const int32_t kFramerate = 24; // fps
36static const int32_t kIFramesIntervalSec = 1;
37static const int32_t kVideoBitRate = 512 * 1024;
38static const int32_t kAudioBitRate = 12200;
James Dongd31c89f2010-08-31 11:46:42 -070039static const int64_t kDurationUs = 10000000LL; // 10 seconds
40
Andreas Huberb482ce82009-10-29 12:02:48 -070041#if 1
Andreas Hubere46b7be2009-07-14 16:56:47 -070042class DummySource : public MediaSource {
Andreas Huberb482ce82009-10-29 12:02:48 -070043
Andreas Hubere46b7be2009-07-14 16:56:47 -070044public:
James Dong2749c172010-09-18 16:13:57 -070045 DummySource(int width, int height, int colorFormat)
Andreas Huberbe06d262009-08-14 14:37:10 -070046 : mWidth(width),
47 mHeight(height),
James Dong2749c172010-09-18 16:13:57 -070048 mColorFormat(colorFormat),
Andreas Huberbe06d262009-08-14 14:37:10 -070049 mSize((width * height * 3) / 2) {
Andreas Hubere46b7be2009-07-14 16:56:47 -070050 mGroup.add_buffer(new MediaBuffer(mSize));
James Dong2749c172010-09-18 16:13:57 -070051
52 // Check the color format to make sure
53 // that the buffer size mSize it set correctly above.
54 CHECK(colorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
55 colorFormat == OMX_COLOR_FormatYUV420Planar);
Andreas Hubere46b7be2009-07-14 16:56:47 -070056 }
57
Andreas Huberbe06d262009-08-14 14:37:10 -070058 virtual sp<MetaData> getFormat() {
59 sp<MetaData> meta = new MetaData;
60 meta->setInt32(kKeyWidth, mWidth);
61 meta->setInt32(kKeyHeight, mHeight);
James Dong2749c172010-09-18 16:13:57 -070062 meta->setInt32(kKeyColorFormat, mColorFormat);
Andreas Hubere6c40962009-09-10 14:13:30 -070063 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
Andreas Huberbe06d262009-08-14 14:37:10 -070064
65 return meta;
Andreas Hubere46b7be2009-07-14 16:56:47 -070066 }
67
Andreas Huberbe06d262009-08-14 14:37:10 -070068 virtual status_t start(MetaData *params) {
Andreas Huberb482ce82009-10-29 12:02:48 -070069 mNumFramesOutput = 0;
Andreas Huberbe06d262009-08-14 14:37:10 -070070 return OK;
71 }
72
73 virtual status_t stop() {
74 return OK;
75 }
76
77 virtual status_t read(
78 MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
Andreas Huberb482ce82009-10-29 12:02:48 -070079 if (mNumFramesOutput == kFramerate * 10) {
80 // Stop returning data after 10 secs.
81 return ERROR_END_OF_STREAM;
82 }
83
84 // printf("DummySource::read\n");
Andreas Huberbe06d262009-08-14 14:37:10 -070085 status_t err = mGroup.acquire_buffer(buffer);
86 if (err != OK) {
Andreas Hubere46b7be2009-07-14 16:56:47 -070087 return err;
88 }
89
90 char x = (char)((double)rand() / RAND_MAX * 255);
91 memset((*buffer)->data(), x, mSize);
92 (*buffer)->set_range(0, mSize);
Andreas Huberb482ce82009-10-29 12:02:48 -070093 (*buffer)->meta_data()->clear();
94 (*buffer)->meta_data()->setInt64(
95 kKeyTime, (mNumFramesOutput * 1000000) / kFramerate);
96 ++mNumFramesOutput;
Andreas Hubere46b7be2009-07-14 16:56:47 -070097
Andreas Huberb482ce82009-10-29 12:02:48 -070098 // printf("DummySource::read - returning buffer\n");
99 // LOGI("DummySource::read - returning buffer");
Andreas Huberbe06d262009-08-14 14:37:10 -0700100 return OK;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700101 }
102
Andreas Huberbe06d262009-08-14 14:37:10 -0700103protected:
104 virtual ~DummySource() {}
105
Andreas Hubere46b7be2009-07-14 16:56:47 -0700106private:
107 MediaBufferGroup mGroup;
Andreas Huberbe06d262009-08-14 14:37:10 -0700108 int mWidth, mHeight;
James Dong2749c172010-09-18 16:13:57 -0700109 int mColorFormat;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700110 size_t mSize;
Andreas Huberb482ce82009-10-29 12:02:48 -0700111 int64_t mNumFramesOutput;;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700112
113 DummySource(const DummySource &);
114 DummySource &operator=(const DummySource &);
115};
116
Andreas Huberbe06d262009-08-14 14:37:10 -0700117sp<MediaSource> createSource(const char *filename) {
118 sp<MediaSource> source;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700119
Andreas Huber57515f32009-10-23 09:55:10 -0700120 sp<MediaExtractor> extractor =
Andreas Huber27366fc2009-11-20 09:32:46 -0800121 MediaExtractor::Create(new FileSource(filename));
James Donge4cfcb82010-02-04 18:08:06 -0800122 if (extractor == NULL) {
123 return NULL;
124 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700125
Andreas Huberbe06d262009-08-14 14:37:10 -0700126 size_t num_tracks = extractor->countTracks();
127
Andreas Hubere46b7be2009-07-14 16:56:47 -0700128 sp<MetaData> meta;
Andreas Huberbe06d262009-08-14 14:37:10 -0700129 for (size_t i = 0; i < num_tracks; ++i) {
130 meta = extractor->getTrackMetaData(i);
Andreas Hubere915a852009-08-28 13:32:48 -0700131 CHECK(meta.get() != NULL);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700132
133 const char *mime;
134 if (!meta->findCString(kKeyMIMEType, &mime)) {
135 continue;
136 }
137
138 if (strncasecmp(mime, "video/", 6)) {
139 continue;
140 }
141
Andreas Huberbe06d262009-08-14 14:37:10 -0700142 source = extractor->getTrack(i);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700143 break;
144 }
145
Andreas Huberbe06d262009-08-14 14:37:10 -0700146 return source;
147}
148
James Dong2749c172010-09-18 16:13:57 -0700149enum {
150 kYUV420SP = 0,
151 kYUV420P = 1,
152};
153
154// returns -1 if mapping of the given color is unsuccessful
155// returns an omx color enum value otherwise
156static int translateColorToOmxEnumValue(int color) {
157 switch (color) {
158 case kYUV420SP:
159 return OMX_COLOR_FormatYUV420SemiPlanar;
160 case kYUV420P:
161 return OMX_COLOR_FormatYUV420Planar;
162 default:
163 fprintf(stderr, "Unsupported color: %d\n", color);
164 return -1;
165 }
166}
167
Andreas Huberbe06d262009-08-14 14:37:10 -0700168int main(int argc, char **argv) {
169 android::ProcessState::self()->startThreadPool();
170
Andreas Huber3e1bdd32009-10-29 15:58:10 -0700171 DataSource::RegisterDefaultSniffers();
172
Andreas Huberbe06d262009-08-14 14:37:10 -0700173#if 1
James Dong2749c172010-09-18 16:13:57 -0700174 if (argc != 3) {
175 fprintf(stderr, "usage: %s <filename> <input_color_format>\n", argv[0]);
176 fprintf(stderr, " <input_color_format>: 0 (YUV420SP) or 1 (YUV420P)\n");
Andreas Hubere46b7be2009-07-14 16:56:47 -0700177 return 1;
178 }
179
James Dong2749c172010-09-18 16:13:57 -0700180 int colorFormat = translateColorToOmxEnumValue(atoi(argv[2]));
181 if (colorFormat == -1) {
182 fprintf(stderr, "input color format must be 0 (YUV420SP) or 1 (YUV420P)\n");
183 return 1;
184 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700185 OMXClient client;
Andreas Hubere915a852009-08-28 13:32:48 -0700186 CHECK_EQ(client.connect(), OK);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700187
James Dong2749c172010-09-18 16:13:57 -0700188 status_t err = OK;
189
Andreas Huber71c27d92010-03-19 11:43:15 -0700190#if 0
Andreas Huberbe06d262009-08-14 14:37:10 -0700191 sp<MediaSource> source = createSource(argv[1]);
192
193 if (source == NULL) {
194 fprintf(stderr, "Unable to find a suitable video track.\n");
195 return 1;
196 }
197
198 sp<MetaData> meta = source->getFormat();
199
Andreas Huber91eb0352009-12-07 09:43:00 -0800200 sp<MediaSource> decoder = OMXCodec::Create(
Andreas Huberbe06d262009-08-14 14:37:10 -0700201 client.interface(), meta, false /* createEncoder */, source);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700202
203 int width, height;
204 bool success = meta->findInt32(kKeyWidth, &width);
205 success = success && meta->findInt32(kKeyHeight, &height);
Andreas Hubere915a852009-08-28 13:32:48 -0700206 CHECK(success);
Andreas Huberbe06d262009-08-14 14:37:10 -0700207#else
Andreas Huber71c27d92010-03-19 11:43:15 -0700208 int width = 720;
Andreas Huberb482ce82009-10-29 12:02:48 -0700209 int height = 480;
James Dong2749c172010-09-18 16:13:57 -0700210 sp<MediaSource> decoder = new DummySource(width, height, colorFormat);
Andreas Huberbe06d262009-08-14 14:37:10 -0700211#endif
Andreas Hubere46b7be2009-07-14 16:56:47 -0700212
213 sp<MetaData> enc_meta = new MetaData;
Andreas Hubere6c40962009-09-10 14:13:30 -0700214 // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
Andreas Huber71c27d92010-03-19 11:43:15 -0700215 // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
216 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700217 enc_meta->setInt32(kKeyWidth, width);
218 enc_meta->setInt32(kKeyHeight, height);
James Dongd31c89f2010-08-31 11:46:42 -0700219 enc_meta->setInt32(kKeySampleRate, kFramerate);
220 enc_meta->setInt32(kKeyBitRate, kVideoBitRate);
221 enc_meta->setInt32(kKeyStride, width);
222 enc_meta->setInt32(kKeySliceHeight, height);
223 enc_meta->setInt32(kKeyIFramesInterval, kIFramesIntervalSec);
James Dong2749c172010-09-18 16:13:57 -0700224 enc_meta->setInt32(kKeyColorFormat, colorFormat);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700225
Andreas Huber91eb0352009-12-07 09:43:00 -0800226 sp<MediaSource> encoder =
Andreas Huberbe06d262009-08-14 14:37:10 -0700227 OMXCodec::Create(
228 client.interface(), enc_meta, true /* createEncoder */, decoder);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700229
Andreas Huberb482ce82009-10-29 12:02:48 -0700230#if 1
Andreas Huberbe06d262009-08-14 14:37:10 -0700231 sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
Andreas Huberb482ce82009-10-29 12:02:48 -0700232 writer->addSource(encoder);
James Dongd31c89f2010-08-31 11:46:42 -0700233 writer->setMaxFileDuration(kDurationUs);
James Dong2749c172010-09-18 16:13:57 -0700234 CHECK_EQ(OK, writer->start());
Andreas Huberb482ce82009-10-29 12:02:48 -0700235 while (!writer->reachedEOS()) {
James Dongd31c89f2010-08-31 11:46:42 -0700236 fprintf(stderr, ".");
Andreas Huberb482ce82009-10-29 12:02:48 -0700237 usleep(100000);
238 }
James Dong2749c172010-09-18 16:13:57 -0700239 err = writer->stop();
Andreas Hubere46b7be2009-07-14 16:56:47 -0700240#else
James Dong2749c172010-09-18 16:13:57 -0700241 CHECK_EQ(OK, encoder->start());
Andreas Hubere46b7be2009-07-14 16:56:47 -0700242
243 MediaBuffer *buffer;
Andreas Hubere915a852009-08-28 13:32:48 -0700244 while (encoder->read(&buffer) == OK) {
James Dongd31c89f2010-08-31 11:46:42 -0700245 printf(".");
246 fflush(stdout);
Andreas Huberb482ce82009-10-29 12:02:48 -0700247 int32_t isSync;
248 if (!buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)) {
249 isSync = false;
250 }
251
252 printf("got an output frame of size %d%s\n", buffer->range_length(),
253 isSync ? " (SYNC)" : "");
Andreas Hubere46b7be2009-07-14 16:56:47 -0700254
255 buffer->release();
256 buffer = NULL;
257 }
258
James Dong2749c172010-09-18 16:13:57 -0700259 err = encoder->stop();
Andreas Hubere46b7be2009-07-14 16:56:47 -0700260#endif
261
James Dongd31c89f2010-08-31 11:46:42 -0700262 printf("$\n");
Andreas Hubere46b7be2009-07-14 16:56:47 -0700263 client.disconnect();
Andreas Hubere46b7be2009-07-14 16:56:47 -0700264#endif
265
266#if 0
267 CameraSource *source = CameraSource::Create();
Andreas Huber71c27d92010-03-19 11:43:15 -0700268 source->start();
269
Andreas Hubere46b7be2009-07-14 16:56:47 -0700270 printf("source = %p\n", source);
271
272 for (int i = 0; i < 100; ++i) {
273 MediaBuffer *buffer;
274 status_t err = source->read(&buffer);
Andreas Hubere915a852009-08-28 13:32:48 -0700275 CHECK_EQ(err, OK);
Andreas Hubere46b7be2009-07-14 16:56:47 -0700276
277 printf("got a frame, data=%p, size=%d\n",
278 buffer->data(), buffer->range_length());
279
280 buffer->release();
281 buffer = NULL;
282 }
283
James Dong2749c172010-09-18 16:13:57 -0700284 err = source->stop();
Andreas Huber71c27d92010-03-19 11:43:15 -0700285
Andreas Hubere46b7be2009-07-14 16:56:47 -0700286 delete source;
287 source = NULL;
288#endif
289
James Dong2749c172010-09-18 16:13:57 -0700290 if (err != OK && err != ERROR_END_OF_STREAM) {
291 fprintf(stderr, "record failed: %d\n", err);
292 return 1;
293 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700294 return 0;
295}
Andreas Huber4c483422009-09-02 16:05:36 -0700296#else
Andreas Huberda050cf22009-09-02 14:01:43 -0700297
298int main(int argc, char **argv) {
299 android::ProcessState::self()->startThreadPool();
300
301 OMXClient client;
302 CHECK_EQ(client.connect(), OK);
303
304 const int32_t kSampleRate = 22050;
305 const int32_t kNumChannels = 2;
306 sp<MediaSource> audioSource = new SineSource(kSampleRate, kNumChannels);
307
308#if 0
309 sp<MediaPlayerBase::AudioSink> audioSink;
310 AudioPlayer *player = new AudioPlayer(audioSink);
311 player->setSource(audioSource);
312 player->start();
313
314 sleep(10);
315
316 player->stop();
317#endif
318
319 sp<MetaData> encMeta = new MetaData;
Andreas Hubere6c40962009-09-10 14:13:30 -0700320 encMeta->setCString(kKeyMIMEType,
321 1 ? MEDIA_MIMETYPE_AUDIO_AMR_WB : MEDIA_MIMETYPE_AUDIO_AAC);
Andreas Huberda050cf22009-09-02 14:01:43 -0700322 encMeta->setInt32(kKeySampleRate, kSampleRate);
323 encMeta->setInt32(kKeyChannelCount, kNumChannels);
324 encMeta->setInt32(kKeyMaxInputSize, 8192);
James Dongd31c89f2010-08-31 11:46:42 -0700325 encMeta->setInt32(kKeyBitRate, kAudioBitRate);
Andreas Huberda050cf22009-09-02 14:01:43 -0700326
327 sp<MediaSource> encoder =
328 OMXCodec::Create(client.interface(), encMeta, true, audioSource);
329
330 encoder->start();
331
332 int32_t n = 0;
333 status_t err;
334 MediaBuffer *buffer;
335 while ((err = encoder->read(&buffer)) == OK) {
336 printf(".");
337 fflush(stdout);
338
339 buffer->release();
340 buffer = NULL;
341
Andreas Huberee606e62009-09-08 10:19:21 -0700342 if (++n == 100) {
Andreas Huberda050cf22009-09-02 14:01:43 -0700343 break;
344 }
345 }
346 printf("$\n");
347
348 encoder->stop();
349
350 client.disconnect();
351
352 return 0;
353}
Andreas Huber4c483422009-09-02 16:05:36 -0700354#endif