Home | History | Annotate | Download | only in stagefright
      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