record.cpp revision 693d271e62a3726689ff68f4505ba49228eb94b2
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/* 220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project 320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License. 620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at 720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software 1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and 1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License. 1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */ 1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#undef NDEBUG 1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <assert.h> 1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <binder/ProcessState.h> 2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/CameraSource.h> 2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h> 2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Extractor.h> 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MPEG4Writer.h> 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MmapSource.h> 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/OMXClient.h> 28693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#include <media/stagefright/OMXCodec.h> 2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/OMXDecoder.h> 3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberusing namespace android; 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass DummySource : public MediaSource { 3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber DummySource(int width, int height) 36693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber : mWidth(width), 37693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber mHeight(height), 38693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber mSize((width * height * 3) / 2) { 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup.add_buffer(new MediaBuffer(mSize)); 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 42693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber virtual sp<MetaData> getFormat() { 43693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MetaData> meta = new MetaData; 44693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber meta->setInt32(kKeyWidth, mWidth); 45693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber meta->setInt32(kKeyHeight, mHeight); 46693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber meta->setCString(kKeyMIMEType, "video/raw"); 47693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 48693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return meta; 49693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber } 50693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 51693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber virtual status_t getMaxSampleSize(size_t *max_size) { 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *max_size = mSize; 53693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return OK; 54693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber } 55693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 56693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber virtual status_t start(MetaData *params) { 57693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return OK; 58693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber } 59693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 60693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber virtual status_t stop() { 61693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return OK; 6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 64693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber virtual status_t read( 65693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber MediaBuffer **buffer, const MediaSource::ReadOptions *options) { 66693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber status_t err = mGroup.acquire_buffer(buffer); 67693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber if (err != OK) { 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber char x = (char)((double)rand() / RAND_MAX * 255); 7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber memset((*buffer)->data(), x, mSize); 7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (*buffer)->set_range(0, mSize); 7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 75693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return OK; 7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected: 79693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber virtual ~DummySource() {} 80693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBufferGroup mGroup; 83693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber int mWidth, mHeight; 8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t mSize; 8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber DummySource(const DummySource &); 8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber DummySource &operator=(const DummySource &); 8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 90693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#define USE_OMX_CODEC 1 9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 92693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> createSource(const char *filename) { 93693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> source; 9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MPEG4Extractor> extractor = 96693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber new MPEG4Extractor(new MmapSource(filename)); 97693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 98693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber size_t num_tracks = extractor->countTracks(); 9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> meta; 101693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber for (size_t i = 0; i < num_tracks; ++i) { 102693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber meta = extractor->getTrackMetaData(i); 10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber assert(meta.get() != NULL); 10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (!meta->findCString(kKeyMIMEType, &mime)) { 10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (strncasecmp(mime, "video/", 6)) { 11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber continue; 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber source = extractor->getTrack(i); 11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return source; 119693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber} 120693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 121693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberint main(int argc, char **argv) { 122693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber android::ProcessState::self()->startThreadPool(); 123693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 124693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#if 1 125693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber if (argc != 2) { 126693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber fprintf(stderr, "usage: %s filename\n", argv[0]); 12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return 1; 12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber OMXClient client; 13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber assert(client.connect() == android::OK); 13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#if 0 134693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> source = createSource(argv[1]); 135693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 136693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber if (source == NULL) { 137693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber fprintf(stderr, "Unable to find a suitable video track.\n"); 138693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return 1; 139693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber } 140693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 141693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MetaData> meta = source->getFormat(); 142693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 143693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#if USE_OMX_CODEC 144693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<OMXCodec> decoder = OMXCodec::Create( 145693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber client.interface(), meta, false /* createEncoder */, source); 146693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#else 147693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<OMXDecoder> decoder = OMXDecoder::Create( 148693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber &client, meta, false /* createEncoder */, source); 149693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#endif 15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int width, height; 15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = meta->findInt32(kKeyWidth, &width); 15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber success = success && meta->findInt32(kKeyHeight, &height); 15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber assert(success); 155693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#else 156693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber int width = 320; 157693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber int height = 240; 158693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MediaSource> decoder = new DummySource(width, height); 159693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#endif 16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> enc_meta = new MetaData; 162693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber // enc_meta->setCString(kKeyMIMEType, "video/3gpp"); 163693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber enc_meta->setCString(kKeyMIMEType, "video/mp4v-es"); 16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber enc_meta->setInt32(kKeyWidth, width); 16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber enc_meta->setInt32(kKeyHeight, height); 16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 167693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#if USE_OMX_CODEC 168693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<OMXCodec> encoder = 169693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber OMXCodec::Create( 170693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber client.interface(), enc_meta, true /* createEncoder */, decoder); 171693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#else 172693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<OMXDecoder> encoder = OMXDecoder::Create( 173693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber &client, enc_meta, true /* createEncoder */, decoder); 174693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber#endif 17520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 1 177693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4"); 178693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber writer->addSource(enc_meta, encoder); 179693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber writer->start(); 180bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber sleep(20); 181bf37f3364804f521cc61845b1f1ce16fe133814bAndreas Huber printf("stopping now.\n"); 182693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber writer->stop(); 18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#else 18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber encoder->start(); 18520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (encoder->read(&buffer) == ::OK) { 18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("got an output frame of size %d\n", buffer->range_length()); 18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber encoder->stop(); 19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif 19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber client.disconnect(); 19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif 19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0 20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber CameraSource *source = CameraSource::Create(); 20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("source = %p\n", source); 20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (int i = 0; i < 100; ++i) { 20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *buffer; 20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = source->read(&buffer); 20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber assert(err == OK); 20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("got a frame, data=%p, size=%d\n", 21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->data(), buffer->range_length()); 21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer->release(); 21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber buffer = NULL; 21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete source; 21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber source = NULL; 21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif 21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return 0; 22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 223