Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 996dddff authored by Andreas Huber's avatar Andreas Huber
Browse files

Support for audio recording into AMR NB/WB files as well as audio tracks in MPEG4 files.

related-to-bug: 2295449
parent 03b58bdf
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -20,23 +20,23 @@

#include <stdio.h>

#include <utils/RefBase.h>
#include <media/stagefright/MediaWriter.h>
#include <utils/threads.h>

namespace android {

struct MediaSource;

struct AMRWriter : public RefBase {
struct AMRWriter : public MediaWriter {
    AMRWriter(const char *filename);
    AMRWriter(int fd);

    status_t initCheck() const;

    status_t addSource(const sp<MediaSource> &source);

    status_t start();
    void stop();
    virtual status_t addSource(const sp<MediaSource> &source);
    virtual bool reachedEOS();
    virtual status_t start();
    virtual void stop();

protected:
    virtual ~AMRWriter();
@@ -49,6 +49,7 @@ private:
    sp<MediaSource> mSource;
    bool mStarted;
    volatile bool mDone;
    bool mReachedEOS;
    pthread_t mThread;

    static void *ThreadWrapper(void *);
+6 −6
Original line number Diff line number Diff line
@@ -20,8 +20,8 @@

#include <stdio.h>

#include <media/stagefright/MediaWriter.h>
#include <utils/List.h>
#include <utils/RefBase.h>
#include <utils/threads.h>

namespace android {
@@ -30,15 +30,15 @@ class MediaBuffer;
class MediaSource;
class MetaData;

class MPEG4Writer : public RefBase {
class MPEG4Writer : public MediaWriter {
public:
    MPEG4Writer(const char *filename);
    MPEG4Writer(int fd);

    void addSource(const sp<MediaSource> &source);
    status_t start();
    bool reachedEOS();
    void stop();
    virtual status_t addSource(const sp<MediaSource> &source);
    virtual status_t start();
    virtual bool reachedEOS();
    virtual void stop();

    void beginBox(const char *fourcc);
    void writeInt8(int8_t x);
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MEDIA_WRITER_H_

#define MEDIA_WRITER_H_

#include <utils/RefBase.h>

namespace android {

struct MediaSource;

struct MediaWriter : public RefBase {
    MediaWriter() {}

    virtual status_t addSource(const sp<MediaSource> &source) = 0;
    virtual bool reachedEOS() = 0;
    virtual status_t start() = 0;
    virtual void stop() = 0;

protected:
    virtual ~MediaWriter() {}

private:
    MediaWriter(const MediaWriter &);
    MediaWriter &operator=(const MediaWriter &);
};

}  // namespace android

#endif  // MEDIA_WRITER_H_
+100 −4
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@

#include "StagefrightRecorder.h"

#include <media/stagefright/AudioSource.h>
#include <media/stagefright/AMRWriter.h>
#include <media/stagefright/CameraSource.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/MediaDebug.h>
@@ -146,7 +148,90 @@ status_t StagefrightRecorder::start() {
        return UNKNOWN_ERROR;
    }

    if (mVideoSource == VIDEO_SOURCE_CAMERA) {
    switch (mOutputFormat) {
        case OUTPUT_FORMAT_DEFAULT:
        case OUTPUT_FORMAT_THREE_GPP:
        case OUTPUT_FORMAT_MPEG_4:
            return startMPEG4Recording();

        case OUTPUT_FORMAT_AMR_NB:
        case OUTPUT_FORMAT_AMR_WB:
            return startAMRRecording();

        default:
            return UNKNOWN_ERROR;
    }
}

sp<MediaSource> StagefrightRecorder::createAMRAudioSource() {
    uint32_t sampleRate =
        mAudioEncoder == AUDIO_ENCODER_AMR_NB ? 8000 : 16000;

    sp<AudioSource> audioSource =
        new AudioSource(
                mAudioSource,
                sampleRate,
                AudioSystem::CHANNEL_IN_MONO);

    status_t err = audioSource->initCheck();

    if (err != OK) {
        return NULL;
    }

    sp<MetaData> encMeta = new MetaData;
    encMeta->setCString(
            kKeyMIMEType,
            mAudioEncoder == AUDIO_ENCODER_AMR_NB
                ? MEDIA_MIMETYPE_AUDIO_AMR_NB : MEDIA_MIMETYPE_AUDIO_AMR_WB);

    encMeta->setInt32(kKeyChannelCount, 1);
    encMeta->setInt32(kKeySampleRate, sampleRate);

    OMXClient client;
    CHECK_EQ(client.connect(), OK);

    sp<MediaSource> audioEncoder =
        OMXCodec::Create(client.interface(), encMeta,
                         true /* createEncoder */, audioSource);

    return audioEncoder;
}

status_t StagefrightRecorder::startAMRRecording() {
    if (mAudioSource == AUDIO_SOURCE_LIST_END
        || mVideoSource != VIDEO_SOURCE_LIST_END) {
        return UNKNOWN_ERROR;
    }

    if (mOutputFormat == OUTPUT_FORMAT_AMR_NB
            && mAudioEncoder != AUDIO_ENCODER_DEFAULT
            && mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
        return UNKNOWN_ERROR;
    } else if (mOutputFormat == OUTPUT_FORMAT_AMR_WB
            && mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
        return UNKNOWN_ERROR;
    }

    sp<MediaSource> audioEncoder = createAMRAudioSource();

    if (audioEncoder == NULL) {
        return UNKNOWN_ERROR;
    }

    CHECK(mOutputFd >= 0);
    mWriter = new AMRWriter(dup(mOutputFd));
    mWriter->addSource(audioEncoder);
    mWriter->start();

    return OK;
}

status_t StagefrightRecorder::startMPEG4Recording() {
    mWriter = new MPEG4Writer(dup(mOutputFd));

    if (mVideoSource == VIDEO_SOURCE_DEFAULT
            || mVideoSource == VIDEO_SOURCE_CAMERA) {
        CHECK(mCamera != NULL);

        sp<CameraSource> cameraSource =
@@ -193,11 +278,20 @@ status_t StagefrightRecorder::start() {
                    true /* createEncoder */, cameraSource);

        CHECK(mOutputFd >= 0);
        mWriter = new MPEG4Writer(dup(mOutputFd));
        mWriter->addSource(encoder);
        mWriter->start();
    }

    if (mAudioSource != AUDIO_SOURCE_LIST_END) {
        sp<MediaSource> audioEncoder = createAMRAudioSource();

        if (audioEncoder == NULL) {
            return UNKNOWN_ERROR;
        }

        mWriter->addSource(audioEncoder);
    }

    mWriter->start();
    return OK;
}

@@ -235,7 +329,9 @@ status_t StagefrightRecorder::reset() {
}

status_t StagefrightRecorder::getMaxAmplitude(int *max) {
    return UNKNOWN_ERROR;
    *max = 0;

    return OK;
}

}  // namespace android
+7 −2
Original line number Diff line number Diff line
@@ -23,7 +23,8 @@

namespace android {

class MPEG4Writer;
struct MediaSource;
struct MediaWriter;

struct StagefrightRecorder : public MediaRecorderBase {
    StagefrightRecorder();
@@ -54,7 +55,7 @@ private:
    sp<ICamera> mCamera;
    sp<ISurface> mPreviewSurface;
    sp<IMediaPlayerClient> mListener;
    sp<MPEG4Writer> mWriter;
    sp<MediaWriter> mWriter;

    audio_source mAudioSource;
    video_source mVideoSource;
@@ -66,6 +67,10 @@ private:
    String8 mParams;
    int mOutputFd;

    status_t startMPEG4Recording();
    status_t startAMRRecording();
    sp<MediaSource> createAMRAudioSource();

    StagefrightRecorder(const StagefrightRecorder &);
    StagefrightRecorder &operator=(const StagefrightRecorder &);
};
Loading