recordvideo.cpp revision c69c13e18a88090c6b06ba8ac244e75cf5e76e38
1/* 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> 21#include <media/stagefright/FileSource.h> 22#include <media/stagefright/MediaBufferGroup.h> 23#include <media/stagefright/MediaDebug.h> 24#include <media/stagefright/MediaDefs.h> 25#include <media/stagefright/MetaData.h> 26#include <media/stagefright/MediaExtractor.h> 27#include <media/stagefright/MPEG4Writer.h> 28#include <media/stagefright/OMXClient.h> 29#include <media/stagefright/OMXCodec.h> 30#include <media/MediaPlayerInterface.h> 31 32using namespace android; 33 34// print usage showing how to use this utility to record videos 35static void usage(const char *me) { 36 fprintf(stderr, "usage: %s\n", me); 37 fprintf(stderr, " -h(elp)\n"); 38 fprintf(stderr, " -b bit rate in bits per second (default 300000)\n"); 39 fprintf(stderr, " -c YUV420 color format: [0] semi planar or [1] planar (default 1)\n"); 40 fprintf(stderr, " -f frame rate in frames per second (default 30)\n"); 41 fprintf(stderr, " -i I frame interval in seconds (default 1)\n"); 42 fprintf(stderr, " -n number of frames to be recorded (default 300)\n"); 43 fprintf(stderr, " -w width in pixels (default 176)\n"); 44 fprintf(stderr, " -t height in pixels (default 144)\n"); 45 fprintf(stderr, " -v video codec: [0] AVC [1] M4V [2] H263 (default 0)\n"); 46 exit(1); 47} 48 49class DummySource : public MediaSource { 50 51public: 52 DummySource(int width, int height, int nFrames, int fps, int colorFormat) 53 : mWidth(width), 54 mHeight(height), 55 mMaxNumFrames(nFrames), 56 mFrameRate(fps), 57 mColorFormat(colorFormat), 58 mSize((width * height * 3) / 2) { 59 mGroup.add_buffer(new MediaBuffer(mSize)); 60 61 // Check the color format to make sure 62 // that the buffer size mSize it set correctly above. 63 CHECK(colorFormat == OMX_COLOR_FormatYUV420SemiPlanar || 64 colorFormat == OMX_COLOR_FormatYUV420Planar); 65 } 66 67 virtual sp<MetaData> getFormat() { 68 sp<MetaData> meta = new MetaData; 69 meta->setInt32(kKeyWidth, mWidth); 70 meta->setInt32(kKeyHeight, mHeight); 71 meta->setInt32(kKeyColorFormat, mColorFormat); 72 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 73 74 return meta; 75 } 76 77 virtual status_t start(MetaData *params) { 78 mNumFramesOutput = 0; 79 return OK; 80 } 81 82 virtual status_t stop() { 83 return OK; 84 } 85 86 virtual status_t read( 87 MediaBuffer **buffer, const MediaSource::ReadOptions *options) { 88 89 if (mNumFramesOutput % 10 == 0) { 90 fprintf(stderr, "."); 91 } 92 if (mNumFramesOutput == mMaxNumFrames) { 93 return ERROR_END_OF_STREAM; 94 } 95 96 status_t err = mGroup.acquire_buffer(buffer); 97 if (err != OK) { 98 return err; 99 } 100 101 char x = (char)((double)rand() / RAND_MAX * 255); 102 memset((*buffer)->data(), x, mSize); 103 (*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 128sp<MediaSource> createSource(const char *filename) { 129 sp<MediaSource> source; 130 131 sp<MediaExtractor> extractor = 132 MediaExtractor::Create(new FileSource(filename)); 133 if (extractor == NULL) { 134 return NULL; 135 } 136 137 size_t num_tracks = extractor->countTracks(); 138 139 sp<MetaData> meta; 140 for (size_t i = 0; i < num_tracks; ++i) { 141 meta = extractor->getTrackMetaData(i); 142 CHECK(meta.get() != NULL); 143 144 const char *mime; 145 if (!meta->findCString(kKeyMIMEType, &mime)) { 146 continue; 147 } 148 149 if (strncasecmp(mime, "video/", 6)) { 150 continue; 151 } 152 153 source = extractor->getTrack(i); 154 break; 155 } 156 157 return source; 158} 159 160enum { 161 kYUV420SP = 0, 162 kYUV420P = 1, 163}; 164 165// returns -1 if mapping of the given color is unsuccessful 166// returns an omx color enum value otherwise 167static int translateColorToOmxEnumValue(int color) { 168 switch (color) { 169 case kYUV420SP: 170 return OMX_COLOR_FormatYUV420SemiPlanar; 171 case kYUV420P: 172 return OMX_COLOR_FormatYUV420Planar; 173 default: 174 fprintf(stderr, "Unsupported color: %d\n", color); 175 return -1; 176 } 177} 178 179int main(int argc, char **argv) { 180 181 // Default values for the program if not overwritten 182 int frameRateFps = 30; 183 int width = 176; 184 int height = 144; 185 int bitRateBps = 300000; 186 int iFramesIntervalSeconds = 1; 187 int colorFormat = OMX_COLOR_FormatYUV420Planar; 188 int nFrames = 300; 189 int codec = 0; 190 const char *fileName = "/sdcard/output.mp4"; 191 192 android::ProcessState::self()->startThreadPool(); 193 int res; 194 while ((res = getopt(argc, argv, "b:c:f:i:n:w:t:v:o:h")) >= 0) { 195 switch (res) { 196 case 'b': 197 { 198 bitRateBps = atoi(optarg); 199 break; 200 } 201 202 case 'c': 203 { 204 colorFormat = translateColorToOmxEnumValue(atoi(optarg)); 205 if (colorFormat == -1) { 206 usage(argv[0]); 207 } 208 break; 209 } 210 211 case 'f': 212 { 213 frameRateFps = atoi(optarg); 214 break; 215 } 216 217 case 'i': 218 { 219 iFramesIntervalSeconds = atoi(optarg); 220 break; 221 } 222 223 case 'n': 224 { 225 nFrames = atoi(optarg); 226 break; 227 } 228 229 case 'w': 230 { 231 width = atoi(optarg); 232 break; 233 } 234 235 case 't': 236 { 237 height = atoi(optarg); 238 break; 239 } 240 241 case 'v': 242 { 243 codec = atoi(optarg); 244 if (codec < 0 || codec > 2) { 245 usage(argv[0]); 246 } 247 break; 248 } 249 250 case 'h': 251 default: 252 { 253 usage(argv[0]); 254 break; 255 } 256 } 257 } 258 259 OMXClient client; 260 CHECK_EQ(client.connect(), OK); 261 262 status_t err = OK; 263 sp<MediaSource> decoder = new DummySource(width, height, nFrames, frameRateFps, colorFormat); 264 265 sp<MetaData> enc_meta = new MetaData; 266 switch (codec) { 267 case 1: 268 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 269 break; 270 case 2: 271 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); 272 break; 273 default: 274 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 275 break; 276 } 277 enc_meta->setInt32(kKeyWidth, width); 278 enc_meta->setInt32(kKeyHeight, height); 279 enc_meta->setInt32(kKeySampleRate, frameRateFps); 280 enc_meta->setInt32(kKeyBitRate, bitRateBps); 281 enc_meta->setInt32(kKeyStride, width); 282 enc_meta->setInt32(kKeySliceHeight, height); 283 enc_meta->setInt32(kKeyIFramesInterval, iFramesIntervalSeconds); 284 enc_meta->setInt32(kKeyColorFormat, colorFormat); 285 286 sp<MediaSource> encoder = 287 OMXCodec::Create( 288 client.interface(), enc_meta, true /* createEncoder */, decoder); 289 290 sp<MPEG4Writer> writer = new MPEG4Writer(fileName); 291 writer->addSource(encoder); 292 int64_t start = systemTime(); 293 CHECK_EQ(OK, writer->start()); 294 while (!writer->reachedEOS()) { 295 } 296 err = writer->stop(); 297 int64_t end = systemTime(); 298 299 printf("$\n"); 300 client.disconnect(); 301 302 if (err != OK && err != ERROR_END_OF_STREAM) { 303 fprintf(stderr, "record failed: %d\n", err); 304 return 1; 305 } 306 fprintf(stderr, "encoding %d frames in %lld us\n", nFrames, (end-start)/1000); 307 fprintf(stderr, "encoding speed is: %.2f fps\n", (nFrames * 1E9) / (end-start)); 308 return 0; 309} 310