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