blob: 12642153b5f9f69babcaf89f132f94996d0418cf [file] [log] [blame]
James Dongb5742452010-09-30 21:34:12 -07001/*
2 * Copyright (C) 2010 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#include "SineSource.h"
18
19#include <binder/ProcessState.h>
20#include <media/stagefright/AudioPlayer.h>
James Dongb5742452010-09-30 21:34:12 -070021#include <media/stagefright/MediaBufferGroup.h>
22#include <media/stagefright/MediaDebug.h>
23#include <media/stagefright/MediaDefs.h>
24#include <media/stagefright/MetaData.h>
James Dongb5742452010-09-30 21:34:12 -070025#include <media/stagefright/MPEG4Writer.h>
26#include <media/stagefright/OMXClient.h>
27#include <media/stagefright/OMXCodec.h>
28#include <media/MediaPlayerInterface.h>
29
30using namespace android;
31
James Dong10649792010-10-06 18:55:05 -070032// Print usage showing how to use this utility to record videos
James Dongb5742452010-09-30 21:34:12 -070033static void usage(const char *me) {
34 fprintf(stderr, "usage: %s\n", me);
35 fprintf(stderr, " -h(elp)\n");
James Dong10649792010-10-06 18:55:05 -070036 fprintf(stderr, " -b bit rate in bits per second (default: 300000)\n");
37 fprintf(stderr, " -c YUV420 color format: [0] semi planar or [1] planar (default: 1)\n");
38 fprintf(stderr, " -f frame rate in frames per second (default: 30)\n");
39 fprintf(stderr, " -i I frame interval in seconds (default: 1)\n");
40 fprintf(stderr, " -n number of frames to be recorded (default: 300)\n");
41 fprintf(stderr, " -w width in pixels (default: 176)\n");
42 fprintf(stderr, " -t height in pixels (default: 144)\n");
43 fprintf(stderr, " -l encoder level. see omx il header (default: encoder specific)\n");
44 fprintf(stderr, " -p encoder profile. see omx il header (default: encoder specific)\n");
45 fprintf(stderr, " -v video codec: [0] AVC [1] M4V [2] H263 (default: 0)\n");
46 fprintf(stderr, "The output file is /sdcard/output.mp4\n");
James Dongb5742452010-09-30 21:34:12 -070047 exit(1);
48}
49
50class DummySource : public MediaSource {
51
52public:
53 DummySource(int width, int height, int nFrames, int fps, int colorFormat)
54 : mWidth(width),
55 mHeight(height),
56 mMaxNumFrames(nFrames),
57 mFrameRate(fps),
58 mColorFormat(colorFormat),
59 mSize((width * height * 3) / 2) {
James Dong10649792010-10-06 18:55:05 -070060
James Dongb5742452010-09-30 21:34:12 -070061 mGroup.add_buffer(new MediaBuffer(mSize));
62
63 // Check the color format to make sure
64 // that the buffer size mSize it set correctly above.
65 CHECK(colorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
66 colorFormat == OMX_COLOR_FormatYUV420Planar);
67 }
68
69 virtual sp<MetaData> getFormat() {
70 sp<MetaData> meta = new MetaData;
71 meta->setInt32(kKeyWidth, mWidth);
72 meta->setInt32(kKeyHeight, mHeight);
73 meta->setInt32(kKeyColorFormat, mColorFormat);
74 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
75
76 return meta;
77 }
78
79 virtual status_t start(MetaData *params) {
80 mNumFramesOutput = 0;
81 return OK;
82 }
83
84 virtual status_t stop() {
85 return OK;
86 }
87
88 virtual status_t read(
89 MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
90
91 if (mNumFramesOutput % 10 == 0) {
92 fprintf(stderr, ".");
93 }
94 if (mNumFramesOutput == mMaxNumFrames) {
95 return ERROR_END_OF_STREAM;
96 }
97
98 status_t err = mGroup.acquire_buffer(buffer);
99 if (err != OK) {
100 return err;
101 }
102
James Dong10649792010-10-06 18:55:05 -0700103 // We don't care about the contents. we just test video encoder
104 // Also, by skipping the content generation, we can return from
105 // read() much faster.
106 //char x = (char)((double)rand() / RAND_MAX * 255);
107 //memset((*buffer)->data(), x, mSize);
James Dongb5742452010-09-30 21:34:12 -0700108 (*buffer)->set_range(0, mSize);
109 (*buffer)->meta_data()->clear();
110 (*buffer)->meta_data()->setInt64(
111 kKeyTime, (mNumFramesOutput * 1000000) / mFrameRate);
112 ++mNumFramesOutput;
113
114 return OK;
115 }
116
117protected:
118 virtual ~DummySource() {}
119
120private:
121 MediaBufferGroup mGroup;
122 int mWidth, mHeight;
123 int mMaxNumFrames;
124 int mFrameRate;
125 int mColorFormat;
126 size_t mSize;
127 int64_t mNumFramesOutput;;
128
129 DummySource(const DummySource &);
130 DummySource &operator=(const DummySource &);
131};
132
James Dongb5742452010-09-30 21:34:12 -0700133enum {
134 kYUV420SP = 0,
135 kYUV420P = 1,
136};
137
138// returns -1 if mapping of the given color is unsuccessful
139// returns an omx color enum value otherwise
140static int translateColorToOmxEnumValue(int color) {
141 switch (color) {
142 case kYUV420SP:
143 return OMX_COLOR_FormatYUV420SemiPlanar;
144 case kYUV420P:
145 return OMX_COLOR_FormatYUV420Planar;
146 default:
147 fprintf(stderr, "Unsupported color: %d\n", color);
148 return -1;
149 }
150}
151
152int main(int argc, char **argv) {
153
154 // Default values for the program if not overwritten
155 int frameRateFps = 30;
156 int width = 176;
157 int height = 144;
158 int bitRateBps = 300000;
159 int iFramesIntervalSeconds = 1;
160 int colorFormat = OMX_COLOR_FormatYUV420Planar;
161 int nFrames = 300;
James Dong10649792010-10-06 18:55:05 -0700162 int level = -1; // Encoder specific default
163 int profile = -1; // Encoder specific default
James Dongb5742452010-09-30 21:34:12 -0700164 int codec = 0;
165 const char *fileName = "/sdcard/output.mp4";
166
167 android::ProcessState::self()->startThreadPool();
168 int res;
James Dong10649792010-10-06 18:55:05 -0700169 while ((res = getopt(argc, argv, "b:c:f:i:n:w:t:l:p:v:h")) >= 0) {
James Dongb5742452010-09-30 21:34:12 -0700170 switch (res) {
171 case 'b':
172 {
173 bitRateBps = atoi(optarg);
174 break;
175 }
176
177 case 'c':
178 {
179 colorFormat = translateColorToOmxEnumValue(atoi(optarg));
180 if (colorFormat == -1) {
181 usage(argv[0]);
182 }
183 break;
184 }
185
186 case 'f':
187 {
188 frameRateFps = atoi(optarg);
189 break;
190 }
191
192 case 'i':
193 {
194 iFramesIntervalSeconds = atoi(optarg);
195 break;
196 }
197
198 case 'n':
199 {
200 nFrames = atoi(optarg);
201 break;
202 }
203
204 case 'w':
205 {
206 width = atoi(optarg);
207 break;
208 }
209
210 case 't':
211 {
212 height = atoi(optarg);
213 break;
214 }
215
James Dong10649792010-10-06 18:55:05 -0700216 case 'l':
217 {
218 level = atoi(optarg);
219 break;
220 }
221
222 case 'p':
223 {
224 profile = atoi(optarg);
225 break;
226 }
227
James Dongb5742452010-09-30 21:34:12 -0700228 case 'v':
229 {
230 codec = atoi(optarg);
231 if (codec < 0 || codec > 2) {
232 usage(argv[0]);
233 }
234 break;
235 }
236
237 case 'h':
238 default:
239 {
240 usage(argv[0]);
241 break;
242 }
243 }
244 }
245
246 OMXClient client;
247 CHECK_EQ(client.connect(), OK);
248
249 status_t err = OK;
James Dong10649792010-10-06 18:55:05 -0700250 sp<MediaSource> source =
251 new DummySource(width, height, nFrames, frameRateFps, colorFormat);
James Dongb5742452010-09-30 21:34:12 -0700252
253 sp<MetaData> enc_meta = new MetaData;
254 switch (codec) {
255 case 1:
256 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
257 break;
258 case 2:
259 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
260 break;
261 default:
262 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
263 break;
264 }
265 enc_meta->setInt32(kKeyWidth, width);
266 enc_meta->setInt32(kKeyHeight, height);
James Dong75611c82010-11-14 10:57:28 -0800267 enc_meta->setInt32(kKeyFrameRate, frameRateFps);
James Dongb5742452010-09-30 21:34:12 -0700268 enc_meta->setInt32(kKeyBitRate, bitRateBps);
269 enc_meta->setInt32(kKeyStride, width);
270 enc_meta->setInt32(kKeySliceHeight, height);
271 enc_meta->setInt32(kKeyIFramesInterval, iFramesIntervalSeconds);
272 enc_meta->setInt32(kKeyColorFormat, colorFormat);
James Dong10649792010-10-06 18:55:05 -0700273 if (level != -1) {
274 enc_meta->setInt32(kKeyVideoLevel, level);
275 }
276 if (profile != -1) {
277 enc_meta->setInt32(kKeyVideoProfile, profile);
278 }
James Dongb5742452010-09-30 21:34:12 -0700279
280 sp<MediaSource> encoder =
281 OMXCodec::Create(
James Dong10649792010-10-06 18:55:05 -0700282 client.interface(), enc_meta, true /* createEncoder */, source);
James Dongb5742452010-09-30 21:34:12 -0700283
284 sp<MPEG4Writer> writer = new MPEG4Writer(fileName);
285 writer->addSource(encoder);
286 int64_t start = systemTime();
287 CHECK_EQ(OK, writer->start());
288 while (!writer->reachedEOS()) {
289 }
290 err = writer->stop();
291 int64_t end = systemTime();
292
James Dong10649792010-10-06 18:55:05 -0700293 fprintf(stderr, "$\n");
James Dongb5742452010-09-30 21:34:12 -0700294 client.disconnect();
295
296 if (err != OK && err != ERROR_END_OF_STREAM) {
297 fprintf(stderr, "record failed: %d\n", err);
298 return 1;
299 }
300 fprintf(stderr, "encoding %d frames in %lld us\n", nFrames, (end-start)/1000);
301 fprintf(stderr, "encoding speed is: %.2f fps\n", (nFrames * 1E9) / (end-start));
302 return 0;
303}