From 114819633470ebd5b346c13c2a82a0025d2d39c0 Mon Sep 17 00:00:00 2001 From: Robert Shih Date: Wed, 9 Jul 2014 20:09:43 -0700 Subject: StagefrightRecorder: webm (video only) support Bug: 16329805 Change-Id: I8a0ecd100fca397add97a1416125bcc6aeb86364 --- include/media/mediarecorder.h | 3 + media/libmedia/mediarecorder.cpp | 7 ++- media/libmediaplayerservice/Android.mk | 1 + .../libmediaplayerservice/StagefrightRecorder.cpp | 73 +++++++++++++--------- media/libmediaplayerservice/StagefrightRecorder.h | 4 +- 5 files changed, 55 insertions(+), 33 deletions(-) diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index 142cb90..2aa8a72 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -61,6 +61,9 @@ enum output_format { OUTPUT_FORMAT_AAC_ADIF = 5, OUTPUT_FORMAT_AAC_ADTS = 6, + OUTPUT_FORMAT_AUDIO_ONLY_END = 7, // Used in validating the output format. Should be the + // at the end of the audio only output formats. + /* Stream over a socket, limited to a single stream */ OUTPUT_FORMAT_RTP_AVP = 7, diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index c8192e9..1952b86 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -186,8 +186,11 @@ status_t MediaRecorder::setOutputFormat(int of) ALOGE("setOutputFormat called in an invalid state: %d", mCurrentState); return INVALID_OPERATION; } - if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_AUDIO_ONLY_START && of != OUTPUT_FORMAT_RTP_AVP && of != OUTPUT_FORMAT_MPEG2TS) { //first non-video output format - ALOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of); + if (mIsVideoSourceSet + && of >= OUTPUT_FORMAT_AUDIO_ONLY_START //first non-video output format + && of < OUTPUT_FORMAT_AUDIO_ONLY_END) { + ALOGE("output format (%d) is meant for audio recording only" + " and incompatible with video recording", of); return INVALID_OPERATION; } diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk index 48d44c1..0c7e590 100644 --- a/media/libmediaplayerservice/Android.mk +++ b/media/libmediaplayerservice/Android.mk @@ -49,6 +49,7 @@ LOCAL_C_INCLUDES := \ $(TOP)/frameworks/av/media/libstagefright/include \ $(TOP)/frameworks/av/media/libstagefright/rtsp \ $(TOP)/frameworks/av/media/libstagefright/wifi-display \ + $(TOP)/frameworks/av/media/libstagefright/webm \ $(TOP)/frameworks/native/include/media/openmax \ $(TOP)/external/tremolo/Tremolo \ diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index bfc075c..217b248 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -19,6 +19,7 @@ #include #include +#include "WebmWriter.h" #include "StagefrightRecorder.h" #include @@ -764,7 +765,8 @@ status_t StagefrightRecorder::prepareInternal() { case OUTPUT_FORMAT_DEFAULT: case OUTPUT_FORMAT_THREE_GPP: case OUTPUT_FORMAT_MPEG_4: - status = setupMPEG4Recording(); + case OUTPUT_FORMAT_WEBM: + status = setupMPEG4orWEBMRecording(); break; case OUTPUT_FORMAT_AMR_NB: @@ -826,9 +828,14 @@ status_t StagefrightRecorder::start() { case OUTPUT_FORMAT_DEFAULT: case OUTPUT_FORMAT_THREE_GPP: case OUTPUT_FORMAT_MPEG_4: + case OUTPUT_FORMAT_WEBM: { + bool isMPEG4 = true; + if (mOutputFormat == OUTPUT_FORMAT_WEBM) { + isMPEG4 = false; + } sp meta = new MetaData; - setupMPEG4MetaData(&meta); + setupMPEG4orWEBMMetaData(&meta); status = mWriter->start(meta.get()); break; } @@ -1538,12 +1545,17 @@ status_t StagefrightRecorder::setupAudioEncoder(const sp& writer) { return OK; } -status_t StagefrightRecorder::setupMPEG4Recording() { +status_t StagefrightRecorder::setupMPEG4orWEBMRecording() { mWriter.clear(); mTotalBitRate = 0; status_t err = OK; - sp writer = new MPEG4Writer(mOutputFd); + sp writer; + if (mOutputFormat == OUTPUT_FORMAT_MPEG_4) { + writer = new MPEG4Writer(mOutputFd); + } else { + writer = new WebmWriter(mOutputFd); + } if (mVideoSource < VIDEO_SOURCE_LIST_END) { @@ -1563,22 +1575,25 @@ status_t StagefrightRecorder::setupMPEG4Recording() { mTotalBitRate += mVideoBitRate; } - // Audio source is added at the end if it exists. - // This help make sure that the "recoding" sound is suppressed for - // camcorder applications in the recorded files. - if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_CNT)) { - err = setupAudioEncoder(writer); - if (err != OK) return err; - mTotalBitRate += mAudioBitRate; - } + if (mOutputFormat == OUTPUT_FORMAT_MPEG_4) { + // Audio source is added at the end if it exists. + // This help make sure that the "recoding" sound is suppressed for + // camcorder applications in the recorded files. + // TODO Audio source is currently unsupported for webm output; vorbis encoder needed. + if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_CNT)) { + err = setupAudioEncoder(writer); + if (err != OK) return err; + mTotalBitRate += mAudioBitRate; + } - if (mInterleaveDurationUs > 0) { - reinterpret_cast(writer.get())-> - setInterleaveDuration(mInterleaveDurationUs); - } - if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) { - reinterpret_cast(writer.get())-> - setGeoData(mLatitudex10000, mLongitudex10000); + if (mInterleaveDurationUs > 0) { + reinterpret_cast(writer.get())-> + setInterleaveDuration(mInterleaveDurationUs); + } + if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) { + reinterpret_cast(writer.get())-> + setGeoData(mLatitudex10000, mLongitudex10000); + } } if (mMaxFileDurationUs != 0) { writer->setMaxFileDuration(mMaxFileDurationUs); @@ -1586,7 +1601,6 @@ status_t StagefrightRecorder::setupMPEG4Recording() { if (mMaxFileSizeBytes != 0) { writer->setMaxFileSize(mMaxFileSizeBytes); } - if (mVideoSource == VIDEO_SOURCE_DEFAULT || mVideoSource == VIDEO_SOURCE_CAMERA) { mStartTimeOffsetMs = mEncoderProfiles->getStartTimeOffsetMs(mCameraId); @@ -1595,8 +1609,7 @@ status_t StagefrightRecorder::setupMPEG4Recording() { mStartTimeOffsetMs = 200; } if (mStartTimeOffsetMs > 0) { - reinterpret_cast(writer.get())-> - setStartTimeOffsetMs(mStartTimeOffsetMs); + writer->setStartTimeOffsetMs(mStartTimeOffsetMs); } writer->setListener(mListener); @@ -1604,20 +1617,22 @@ status_t StagefrightRecorder::setupMPEG4Recording() { return OK; } -void StagefrightRecorder::setupMPEG4MetaData(sp *meta) { +void StagefrightRecorder::setupMPEG4orWEBMMetaData(sp *meta) { int64_t startTimeUs = systemTime() / 1000; (*meta)->setInt64(kKeyTime, startTimeUs); (*meta)->setInt32(kKeyFileType, mOutputFormat); (*meta)->setInt32(kKeyBitRate, mTotalBitRate); - (*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset); if (mMovieTimeScale > 0) { (*meta)->setInt32(kKeyTimeScale, mMovieTimeScale); } - if (mTrackEveryTimeDurationUs > 0) { - (*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); - } - if (mRotationDegrees != 0) { - (*meta)->setInt32(kKeyRotation, mRotationDegrees); + if (mOutputFormat == OUTPUT_FORMAT_MPEG_4) { + (*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset); + if (mTrackEveryTimeDurationUs > 0) { + (*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); + } + if (mRotationDegrees != 0) { + (*meta)->setInt32(kKeyRotation, mRotationDegrees); + } } } diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index 377d168..9062f30 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -128,8 +128,8 @@ private: sp mLooper; status_t prepareInternal(); - status_t setupMPEG4Recording(); - void setupMPEG4MetaData(sp *meta); + status_t setupMPEG4orWEBMRecording(); + void setupMPEG4orWEBMMetaData(sp *meta); status_t setupAMRRecording(); status_t setupAACRecording(); status_t setupRawAudioRecording(); -- cgit v1.1