record.cpp revision 5fb00a6d1f32523aa254fea95a7bee646f4ae9ae
1/* 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 17#include "SineSource.h" 18 19#include <binder/ProcessState.h> 20#include <media/stagefright/foundation/ADebug.h> 21#include <media/stagefright/foundation/ALooper.h> 22#include <media/stagefright/foundation/AMessage.h> 23#include <media/stagefright/AudioPlayer.h> 24#include <media/stagefright/CameraSource.h> 25#include <media/stagefright/FileSource.h> 26#include <media/stagefright/MediaBufferGroup.h> 27#include <media/stagefright/MediaDefs.h> 28#include <media/stagefright/MediaCodecSource.h> 29#include <media/stagefright/MetaData.h> 30#include <media/stagefright/MediaExtractor.h> 31#include <media/stagefright/MPEG4Writer.h> 32#include <media/stagefright/SimpleDecodingSource.h> 33#include <media/MediaPlayerInterface.h> 34 35using namespace android; 36 37static const int32_t kAudioBitRate = 12200; 38#if 0 39static const int32_t kFramerate = 24; // fps 40static const int32_t kIFramesIntervalSec = 1; 41static const int32_t kVideoBitRate = 512 * 1024; 42static const int64_t kDurationUs = 10000000LL; // 10 seconds 43 44class DummySource : public MediaSource { 45 46public: 47 DummySource(int width, int height, int colorFormat) 48 : mWidth(width), 49 mHeight(height), 50 mColorFormat(colorFormat), 51 mSize((width * height * 3) / 2) { 52 mGroup.add_buffer(new MediaBuffer(mSize)); 53 54 // Check the color format to make sure 55 // that the buffer size mSize it set correctly above. 56 CHECK(colorFormat == OMX_COLOR_FormatYUV420SemiPlanar || 57 colorFormat == OMX_COLOR_FormatYUV420Planar); 58 } 59 60 virtual sp<MetaData> getFormat() { 61 sp<MetaData> meta = new MetaData; 62 meta->setInt32(kKeyWidth, mWidth); 63 meta->setInt32(kKeyHeight, mHeight); 64 meta->setInt32(kKeyColorFormat, mColorFormat); 65 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); 66 67 return meta; 68 } 69 70 virtual status_t start(MetaData *params) { 71 mNumFramesOutput = 0; 72 return OK; 73 } 74 75 virtual status_t stop() { 76 return OK; 77 } 78 79 virtual status_t read( 80 MediaBuffer **buffer, const MediaSource::ReadOptions *options) { 81 if (mNumFramesOutput == kFramerate * 10) { 82 // Stop returning data after 10 secs. 83 return ERROR_END_OF_STREAM; 84 } 85 86 // printf("DummySource::read\n"); 87 status_t err = mGroup.acquire_buffer(buffer); 88 if (err != OK) { 89 return err; 90 } 91 92 char x = (char)((double)rand() / RAND_MAX * 255); 93 memset((*buffer)->data(), x, mSize); 94 (*buffer)->set_range(0, mSize); 95 (*buffer)->meta_data()->clear(); 96 (*buffer)->meta_data()->setInt64( 97 kKeyTime, (mNumFramesOutput * 1000000) / kFramerate); 98 ++mNumFramesOutput; 99 100 // printf("DummySource::read - returning buffer\n"); 101 // ALOGI("DummySource::read - returning buffer"); 102 return OK; 103 } 104 105protected: 106 virtual ~DummySource() {} 107 108private: 109 MediaBufferGroup mGroup; 110 int mWidth, mHeight; 111 int mColorFormat; 112 size_t mSize; 113 int64_t mNumFramesOutput;; 114 115 DummySource(const DummySource &); 116 DummySource &operator=(const DummySource &); 117}; 118 119sp<MediaSource> createSource(const char *filename) { 120 sp<MediaSource> source; 121 122 sp<MediaExtractor> extractor = 123 MediaExtractor::Create(new FileSource(filename)); 124 if (extractor == NULL) { 125 return NULL; 126 } 127 128 size_t num_tracks = extractor->countTracks(); 129 130 sp<MetaData> meta; 131 for (size_t i = 0; i < num_tracks; ++i) { 132 meta = extractor->getTrackMetaData(i); 133 CHECK(meta.get() != NULL); 134 135 const char *mime; 136 if (!meta->findCString(kKeyMIMEType, &mime)) { 137 continue; 138 } 139 140 if (strncasecmp(mime, "video/", 6)) { 141 continue; 142 } 143 144 source = extractor->getTrack(i); 145 break; 146 } 147 148 return source; 149} 150 151enum { 152 kYUV420SP = 0, 153 kYUV420P = 1, 154}; 155 156// returns -1 if mapping of the given color is unsuccessful 157// returns an omx color enum value otherwise 158static int translateColorToOmxEnumValue(int color) { 159 switch (color) { 160 case kYUV420SP: 161 return OMX_COLOR_FormatYUV420SemiPlanar; 162 case kYUV420P: 163 return OMX_COLOR_FormatYUV420Planar; 164 default: 165 fprintf(stderr, "Unsupported color: %d\n", color); 166 return -1; 167 } 168} 169 170int main(int argc, char **argv) { 171 android::ProcessState::self()->startThreadPool(); 172 173 DataSource::RegisterDefaultSniffers(); 174 175#if 1 176 if (argc != 3) { 177 fprintf(stderr, "usage: %s <filename> <input_color_format>\n", argv[0]); 178 fprintf(stderr, " <input_color_format>: 0 (YUV420SP) or 1 (YUV420P)\n"); 179 return 1; 180 } 181 182 int colorFormat = translateColorToOmxEnumValue(atoi(argv[2])); 183 if (colorFormat == -1) { 184 fprintf(stderr, "input color format must be 0 (YUV420SP) or 1 (YUV420P)\n"); 185 return 1; 186 } 187 status_t err = OK; 188 189#if 0 190 sp<MediaSource> source = createSource(argv[1]); 191 192 if (source == NULL) { 193 fprintf(stderr, "Unable to find a suitable video track.\n"); 194 return 1; 195 } 196 197 sp<MetaData> meta = source->getFormat(); 198 199 sp<MediaSource> decoder = SimpleDecodingSource::Create(source); 200 201 int width, height; 202 bool success = meta->findInt32(kKeyWidth, &width); 203 success = success && meta->findInt32(kKeyHeight, &height); 204 CHECK(success); 205#else 206 int width = 720; 207 int height = 480; 208 sp<MediaSource> decoder = new DummySource(width, height, colorFormat); 209#endif 210 211 sp<AMessage> enc_meta = new AMessage; 212 // enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_H263); 213 // enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4); 214 enc_meta->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC); 215 enc_meta->setInt32("width", width); 216 enc_meta->setInt32("height", height); 217 enc_meta->setInt32("sample-rate", kFramerate); 218 enc_meta->setInt32("bit-rate", kVideoBitRate); 219 // enc_meta->setInt32("stride", width); 220 // enc_meta->setInt32("slice-height", height); 221 enc_meta->setInt32("i-frame-interval", kIFramesIntervalSec); 222 enc_meta->setInt32("color-format", colorFormat); 223 224 sp<MediaSource> encoder = 225 MediaCodecSource::Create(looper, format, decoder); 226 227#if 1 228 sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4"); 229 writer->addSource(encoder); 230 writer->setMaxFileDuration(kDurationUs); 231 CHECK_EQ((status_t)OK, writer->start()); 232 while (!writer->reachedEOS()) { 233 fprintf(stderr, "."); 234 usleep(100000); 235 } 236 err = writer->stop(); 237#else 238 CHECK_EQ((status_t)OK, encoder->start()); 239 240 MediaBuffer *buffer; 241 while (encoder->read(&buffer) == OK) { 242 printf("."); 243 fflush(stdout); 244 int32_t isSync; 245 if (!buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)) { 246 isSync = false; 247 } 248 249 printf("got an output frame of size %d%s\n", buffer->range_length(), 250 isSync ? " (SYNC)" : ""); 251 252 buffer->release(); 253 buffer = NULL; 254 } 255 256 err = encoder->stop(); 257#endif 258 259 printf("$\n"); 260#endif 261 262#if 0 263 CameraSource *source = CameraSource::Create( 264 String16(argv[0], strlen(argv[0]))); 265 source->start(); 266 267 printf("source = %p\n", source); 268 269 for (int i = 0; i < 100; ++i) { 270 MediaBuffer *buffer; 271 status_t err = source->read(&buffer); 272 CHECK_EQ(err, (status_t)OK); 273 274 printf("got a frame, data=%p, size=%d\n", 275 buffer->data(), buffer->range_length()); 276 277 buffer->release(); 278 buffer = NULL; 279 } 280 281 err = source->stop(); 282 283 delete source; 284 source = NULL; 285#endif 286 287 if (err != OK && err != ERROR_END_OF_STREAM) { 288 fprintf(stderr, "record failed: %d\n", err); 289 return 1; 290 } 291 return 0; 292} 293#else 294 295int main(int /* argc */, char ** /* argv */) { 296 android::ProcessState::self()->startThreadPool(); 297 298 const int32_t kSampleRate = 22050; 299 const int32_t kNumChannels = 2; 300 sp<MediaSource> audioSource = new SineSource(kSampleRate, kNumChannels); 301 302#if 0 303 sp<MediaPlayerBase::AudioSink> audioSink; 304 AudioPlayer *player = new AudioPlayer(audioSink); 305 player->setSource(audioSource); 306 player->start(); 307 308 sleep(10); 309 310 player->stop(); 311#endif 312 313 sp<AMessage> encMeta = new AMessage; 314 encMeta->setString("mime", 315 0 ? MEDIA_MIMETYPE_AUDIO_AMR_WB : MEDIA_MIMETYPE_AUDIO_AAC); 316 encMeta->setInt32("sample-rate", kSampleRate); 317 encMeta->setInt32("channel-count", kNumChannels); 318 encMeta->setInt32("max-input-size", 8192); 319 encMeta->setInt32("bitrate", kAudioBitRate); 320 321 sp<ALooper> looper = new ALooper; 322 looper->setName("record"); 323 looper->start(); 324 325 sp<IMediaSource> encoder = 326 MediaCodecSource::Create(looper, encMeta, audioSource); 327 328 encoder->start(); 329 330 int32_t n = 0; 331 status_t err; 332 MediaBuffer *buffer; 333 while ((err = encoder->read(&buffer)) == OK) { 334 printf("."); 335 fflush(stdout); 336 337 buffer->release(); 338 buffer = NULL; 339 340 if (++n == 100) { 341 break; 342 } 343 } 344 printf("$\n"); 345 346 encoder->stop(); 347 348 return 0; 349} 350#endif 351