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