blob: c40228631ae2f3e8f1edf7efd6afa54daa6a19fb [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");
James Dong43e8a832011-07-07 08:30:10 -070037 fprintf(stderr, " -c YUV420 color format: [0] semi planar or [1] planar or other omx YUV420 color format (default: 1)\n");
James Dong10649792010-10-06 18:55:05 -070038 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));
James Dongb5742452010-09-30 21:34:12 -070062 }
63
64 virtual sp<MetaData> getFormat() {
65 sp<MetaData> meta = new MetaData;
66 meta->setInt32(kKeyWidth, mWidth);
67 meta->setInt32(kKeyHeight, mHeight);
68 meta->setInt32(kKeyColorFormat, mColorFormat);
69 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
70
71 return meta;
72 }
73
74 virtual status_t start(MetaData *params) {
75 mNumFramesOutput = 0;
76 return OK;
77 }
78
79 virtual status_t stop() {
80 return OK;
81 }
82
83 virtual status_t read(
84 MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
85
86 if (mNumFramesOutput % 10 == 0) {
87 fprintf(stderr, ".");
88 }
89 if (mNumFramesOutput == mMaxNumFrames) {
90 return ERROR_END_OF_STREAM;
91 }
92
93 status_t err = mGroup.acquire_buffer(buffer);
94 if (err != OK) {
95 return err;
96 }
97
James Dong10649792010-10-06 18:55:05 -070098 // We don't care about the contents. we just test video encoder
99 // Also, by skipping the content generation, we can return from
100 // read() much faster.
101 //char x = (char)((double)rand() / RAND_MAX * 255);
102 //memset((*buffer)->data(), x, mSize);
James Dongb5742452010-09-30 21:34:12 -0700103 (*buffer)->set_range(0, mSize);
104 (*buffer)->meta_data()->clear();
105 (*buffer)->meta_data()->setInt64(
106 kKeyTime, (mNumFramesOutput * 1000000) / mFrameRate);
107 ++mNumFramesOutput;
108
109 return OK;
110 }
111
112protected:
113 virtual ~DummySource() {}
114
115private:
116 MediaBufferGroup mGroup;
117 int mWidth, mHeight;
118 int mMaxNumFrames;
119 int mFrameRate;
120 int mColorFormat;
121 size_t mSize;
122 int64_t mNumFramesOutput;;
123
124 DummySource(const DummySource &);
125 DummySource &operator=(const DummySource &);
126};
127
James Dongb5742452010-09-30 21:34:12 -0700128enum {
129 kYUV420SP = 0,
130 kYUV420P = 1,
131};
132
133// returns -1 if mapping of the given color is unsuccessful
134// returns an omx color enum value otherwise
135static int translateColorToOmxEnumValue(int color) {
136 switch (color) {
137 case kYUV420SP:
138 return OMX_COLOR_FormatYUV420SemiPlanar;
139 case kYUV420P:
140 return OMX_COLOR_FormatYUV420Planar;
141 default:
James Dong43e8a832011-07-07 08:30:10 -0700142 fprintf(stderr, "Custom OMX color format: %d\n", color);
143 if (color == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar ||
144 color == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
145 return color;
146 }
James Dongb5742452010-09-30 21:34:12 -0700147 }
James Dong43e8a832011-07-07 08:30:10 -0700148 return -1;
James Dongb5742452010-09-30 21:34:12 -0700149}
150
151int main(int argc, char **argv) {
152
153 // Default values for the program if not overwritten
154 int frameRateFps = 30;
155 int width = 176;
156 int height = 144;
157 int bitRateBps = 300000;
158 int iFramesIntervalSeconds = 1;
159 int colorFormat = OMX_COLOR_FormatYUV420Planar;
160 int nFrames = 300;
James Dong10649792010-10-06 18:55:05 -0700161 int level = -1; // Encoder specific default
162 int profile = -1; // Encoder specific default
James Dongb5742452010-09-30 21:34:12 -0700163 int codec = 0;
164 const char *fileName = "/sdcard/output.mp4";
165
166 android::ProcessState::self()->startThreadPool();
167 int res;
James Dong10649792010-10-06 18:55:05 -0700168 while ((res = getopt(argc, argv, "b:c:f:i:n:w:t:l:p:v:h")) >= 0) {
James Dongb5742452010-09-30 21:34:12 -0700169 switch (res) {
170 case 'b':
171 {
172 bitRateBps = atoi(optarg);
173 break;
174 }
175
176 case 'c':
177 {
178 colorFormat = translateColorToOmxEnumValue(atoi(optarg));
179 if (colorFormat == -1) {
180 usage(argv[0]);
181 }
182 break;
183 }
184
185 case 'f':
186 {
187 frameRateFps = atoi(optarg);
188 break;
189 }
190
191 case 'i':
192 {
193 iFramesIntervalSeconds = atoi(optarg);
194 break;
195 }
196
197 case 'n':
198 {
199 nFrames = atoi(optarg);
200 break;
201 }
202
203 case 'w':
204 {
205 width = atoi(optarg);
206 break;
207 }
208
209 case 't':
210 {
211 height = atoi(optarg);
212 break;
213 }
214
James Dong10649792010-10-06 18:55:05 -0700215 case 'l':
216 {
217 level = atoi(optarg);
218 break;
219 }
220
221 case 'p':
222 {
223 profile = atoi(optarg);
224 break;
225 }
226
James Dongb5742452010-09-30 21:34:12 -0700227 case 'v':
228 {
229 codec = atoi(optarg);
230 if (codec < 0 || codec > 2) {
231 usage(argv[0]);
232 }
233 break;
234 }
235
236 case 'h':
237 default:
238 {
239 usage(argv[0]);
240 break;
241 }
242 }
243 }
244
245 OMXClient client;
246 CHECK_EQ(client.connect(), OK);
247
248 status_t err = OK;
James Dong10649792010-10-06 18:55:05 -0700249 sp<MediaSource> source =
250 new DummySource(width, height, nFrames, frameRateFps, colorFormat);
James Dongb5742452010-09-30 21:34:12 -0700251
252 sp<MetaData> enc_meta = new MetaData;
253 switch (codec) {
254 case 1:
255 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
256 break;
257 case 2:
258 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
259 break;
260 default:
261 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
262 break;
263 }
264 enc_meta->setInt32(kKeyWidth, width);
265 enc_meta->setInt32(kKeyHeight, height);
James Dong75611c82010-11-14 10:57:28 -0800266 enc_meta->setInt32(kKeyFrameRate, frameRateFps);
James Dongb5742452010-09-30 21:34:12 -0700267 enc_meta->setInt32(kKeyBitRate, bitRateBps);
268 enc_meta->setInt32(kKeyStride, width);
269 enc_meta->setInt32(kKeySliceHeight, height);
270 enc_meta->setInt32(kKeyIFramesInterval, iFramesIntervalSeconds);
271 enc_meta->setInt32(kKeyColorFormat, colorFormat);
James Dong10649792010-10-06 18:55:05 -0700272 if (level != -1) {
273 enc_meta->setInt32(kKeyVideoLevel, level);
274 }
275 if (profile != -1) {
276 enc_meta->setInt32(kKeyVideoProfile, profile);
277 }
James Dongb5742452010-09-30 21:34:12 -0700278
279 sp<MediaSource> encoder =
280 OMXCodec::Create(
James Dong10649792010-10-06 18:55:05 -0700281 client.interface(), enc_meta, true /* createEncoder */, source);
James Dongb5742452010-09-30 21:34:12 -0700282
283 sp<MPEG4Writer> writer = new MPEG4Writer(fileName);
284 writer->addSource(encoder);
285 int64_t start = systemTime();
286 CHECK_EQ(OK, writer->start());
287 while (!writer->reachedEOS()) {
288 }
289 err = writer->stop();
290 int64_t end = systemTime();
291
James Dong10649792010-10-06 18:55:05 -0700292 fprintf(stderr, "$\n");
James Dongb5742452010-09-30 21:34:12 -0700293 client.disconnect();
294
295 if (err != OK && err != ERROR_END_OF_STREAM) {
296 fprintf(stderr, "record failed: %d\n", err);
297 return 1;
298 }
299 fprintf(stderr, "encoding %d frames in %lld us\n", nFrames, (end-start)/1000);
300 fprintf(stderr, "encoding speed is: %.2f fps\n", (nFrames * 1E9) / (end-start));
301 return 0;
302}