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