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/MediaExtractor.h>
     21 #include <media/stagefright/foundation/ADebug.h>
     22 #include <media/stagefright/foundation/ALooper.h>
     23 #include <media/stagefright/foundation/AMessage.h>
     24 #include <media/stagefright/AudioPlayer.h>
     25 #include <media/stagefright/CameraSource.h>
     26 #include <media/stagefright/FileSource.h>
     27 #include <media/stagefright/MediaBufferGroup.h>
     28 #include <media/stagefright/MediaDefs.h>
     29 #include <media/stagefright/MediaCodecSource.h>
     30 #include <media/stagefright/MetaData.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